Oracle Database SQLJ Developer's Guide and Reference

7 downloads 389 Views 7MB Size Report
Oracle, JD Edwards, PeopleSoft, and Siebel are registered trademarks of Oracle Corporation .... Requirements for Using the Oracle SQLJ Implementation.
Oracle® Database SQLJ Developer’s Guide and Reference 11g Release 1 (11.1) B31227-03

September 2007

Oracle Database SQLJ Developer’s Guide and Reference, 11g Release 1 (11.1) B31227-03 Copyright © 1999, 2007, Oracle. All rights reserved. Primary Author:

Tulika Das

Contributing Author:

Venkatasubramaniam Iyer, Brian Wright, Janice Nygard

Contributor: Amit Bande, Krishna Mohan, Amoghavarsha Ramappa, Dhilipkumar Gopal, Quan Wang, Angela Barone, Ekkehard Rohwedder, Brian Becker, Alan Thiesen, Lei Tang, Julie Basu, Pierre Dufour, Jerry Schwarz, Risto Lakinen, Cheuk Chau, Vishu Krishnamurthy, Rafiul Ahad, Jack Melnick, Tim Smith, Thomas Pfaeffle, Tom Portfolio, Ellen Barnes, Susan Kraft, Sheryl Maring The Programs (which include both the software and documentation) contain proprietary information; they are provided under a license agreement containing restrictions on use and disclosure and are also protected by copyright, patent, and other intellectual and industrial property laws. Reverse engineering, disassembly, or decompilation of the Programs, except to the extent required to obtain interoperability with other independently created software or as specified by law, is prohibited. The information contained in this document is subject to change without notice. If you find any problems in the documentation, please report them to us in writing. This document is not warranted to be error-free. Except as may be expressly permitted in your license agreement for these Programs, no part of these Programs may be reproduced or transmitted in any form or by any means, electronic or mechanical, for any purpose. If the Programs are delivered to the United States Government or anyone licensing or using the Programs on behalf of the United States Government, the following notice is applicable: U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, and adaptation of the Programs, including documentation and technical data, shall be subject to the licensing restrictions set forth in the applicable Oracle license agreement, and, to the extent applicable, the additional rights set forth in FAR 52.227-19, Commercial Computer Software--Restricted Rights (June 1987). Oracle USA, Inc., 500 Oracle Parkway, Redwood City, CA 94065. The Programs are not intended for use in any nuclear, aviation, mass transit, medical, or other inherently dangerous applications. It shall be the licensee's responsibility to take all appropriate fail-safe, backup, redundancy and other measures to ensure the safe use of such applications if the Programs are used for such purposes, and we disclaim liability for any damages caused by such use of the Programs. Oracle, JD Edwards, PeopleSoft, and Siebel are registered trademarks of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. The Programs may provide links to Web sites and access to content, products, and services from third parties. Oracle is not responsible for the availability of, or any content provided on, third-party Web sites. You bear all risks associated with the use of such content. If you choose to purchase any products or services from a third party, the relationship is directly between you and the third party. Oracle is not responsible for: (a) the quality of third-party products or services; or (b) fulfilling any of the terms of the agreement with the third party, including delivery of products or services and warranty obligations related to purchased products or services. Oracle is not responsible for any loss or damage of any sort that you may incur from dealing with any third party.

Contents Preface ............................................................................................................................................................... xv Audience..................................................................................................................................................... xv Documentation Accessibility ................................................................................................................... xv Related Documents ................................................................................................................................... xvi Conventions .............................................................................................................................................. xvii

What’s New in 11g Release 1 (11.1)

......................................................................................... xxi

Support for JDK 1.5 and JDK 1.6 ............................................................................................................. xxi Enhanced Profile Print Option ............................................................................................................... xxii Outline Generation................................................................................................................................... xxii Support for Global Transactions ............................................................................................................ xxii

1

Getting Started Assumptions and Requirements ........................................................................................................... Assumptions About Your Environment......................................................................................... Requirements for Using the Oracle SQLJ Implementation.......................................................... SQLJ Environment ............................................................................................................................. Environment Considerations ........................................................................................................... SQLJ Backward Compatibility ......................................................................................................... Checking the Installation and Configuration..................................................................................... Check for Availability of SQLJ and Demo Applications.............................................................. Check for Installed Directories and Files........................................................................................ Set the Path and Classpath................................................................................................................ Verify Installation of the sqljutl Package ........................................................................................ Testing the Setup...................................................................................................................................... Set Up the Run Time Connection .................................................................................................... Create a Table to Verify the Database ............................................................................................. Verify the JDBC Driver...................................................................................................................... Verify the SQLJ Translator and Run Time ..................................................................................... Verify the SQLJ Translator Connection to the Database ..............................................................

2

1-1 1-1 1-2 1-2 1-3 1-3 1-3 1-3 1-4 1-4 1-5 1-5 1-6 1-7 1-7 1-7 1-8

Introduction to SQLJ Overview of SQLJ .................................................................................................................................... 2-1 Overview of SQLJ Components ............................................................................................................ 2-2 SQLJ Translator .................................................................................................................................. 2-2 iii

SQLJ Run Time .................................................................................................................................. 2-2 Overview of Oracle Extensions to the SQLJ Standard...................................................................... 2-3 SQLJ Type Extensions........................................................................................................................ 2-3 SQLJ Functionality Extensions ......................................................................................................... 2-4 Basic Translation Steps and Run-Time Processing ........................................................................... 2-5 SQLJ Translation Steps ...................................................................................................................... 2-5 Summary of Translator Input and Output ..................................................................................... 2-7 Translator Input .......................................................................................................................... 2-7 Translator Output ....................................................................................................................... 2-7 Output File Locations ................................................................................................................. 2-8 SQLJ Run-Time Processing............................................................................................................... 2-8 SQLJ Sample Code................................................................................................................................... 2-8 SQLJ Version of the Sample Code ................................................................................................... 2-9 JDBC Version of the Sample Code................................................................................................ 2-10 Alternative Deployment Scenarios.................................................................................................... 2-11 Running SQLJ in Applets............................................................................................................... 2-12 General Development and Deployment Considerations................................................... 2-12 General End User Considerations ......................................................................................... 2-13 Java Environment and the Java Plug-In ............................................................................... 2-13 Overview of SQLJ in the Server .................................................................................................... 2-13 Alternative Development Scenarios.................................................................................................. 2-15 SQLJ Globalization Support .......................................................................................................... 2-15 SQLJ in Oracle JDeveloper 10g and Other IDEs ......................................................................... 2-15 Windows Considerations............................................................................................................... 2-15

3

Key Programming Considerations Selection of the JDBC Driver ................................................................................................................. 3-1 Overview of Oracle JDBC Drivers ................................................................................................... 3-1 Driver Selection for Translation ....................................................................................................... 3-3 Driver Selection and Registration for Run Time ........................................................................... 3-4 Connection Considerations .................................................................................................................... 3-4 Single Connection or Multiple Connections Using DefaultContext........................................... 3-5 Closing Connections .......................................................................................................................... 3-8 Multiple Connections Using Declared Connection Context Classes.......................................... 3-9 More About the Oracle Class ........................................................................................................... 3-9 More About the DefaultContext Class ......................................................................................... 3-11 Connection for Translation ............................................................................................................ 3-13 Connection for Customization ...................................................................................................... 3-13 NULL-Handling..................................................................................................................................... 3-14 Wrapper Classes for NULL-Handling ......................................................................................... 3-14 Examples of NULL-Handling ...................................................................................................... 3-15 Exception-Handling Basics.................................................................................................................. 3-15 SQLJ and JDBC Exception-Handling Requirements.................................................................. 3-16 Processing Exceptions .................................................................................................................... 3-17 Using SQLException Subclasses ................................................................................................... 3-18 Basic Transaction Control.................................................................................................................... 3-18 Overview of Transactions .............................................................................................................. 3-19

iv

Automatic Commits Versus Manual Commits........................................................................... Specifying Auto-Commit as You Define a Connection ............................................................. Modifying Auto-Commit in an Existing Connection ................................................................ Using Manual COMMIT and ROLLBACK ................................................................................. Effect of Commits and Rollbacks on Iterators and Result Sets................................................. Using Savepoints............................................................................................................................. Summary: First Steps in SQLJ Code.................................................................................................. Oracle-Specific Code Generation (No Profiles) .............................................................................. Code Considerations and Limitations with Oracle-Specific Code Generation...................... SQLJ Usage Changes with Oracle-Specific Code Generation................................................... Server-Side Considerations with Oracle-Specific Code Generation........................................ Advantages and Disadvantages of Oracle-Specific Code Generation .................................... ISO Standard Code Generation.......................................................................................................... Environment Requirements for ISO Standard Code Generation............................................. SQLJ Translator and SQLJ Run Time ........................................................................................... SQLJ Profiles .................................................................................................................................... Overview of Profiles ................................................................................................................ Binary Portability ..................................................................................................................... SQLJ Translation Steps ................................................................................................................... Summary of Translator Input and Output .................................................................................. Translator Input ....................................................................................................................... Translator Output .................................................................................................................... Output File Locations .............................................................................................................. SQLJ Run-Time Processing............................................................................................................ Deployment Scenarios.................................................................................................................... Oracle-Specific Code Generation Versus ISO Standard Code Generation............................... Requirements and Restrictions for Naming .................................................................................... Java Namespace: Local Variable and Class Naming Restrictions............................................ SQLJ Namespace ............................................................................................................................. SQL Namespace .............................................................................................................................. File Name Requirements and Restrictions .................................................................................. Considerations for SQLJ in the Middle Tier ...................................................................................

4

3-19 3-19 3-20 3-20 3-21 3-21 3-23 3-28 3-28 3-30 3-31 3-31 3-32 3-32 3-33 3-33 3-33 3-34 3-34 3-35 3-35 3-36 3-37 3-37 3-37 3-39 3-39 3-40 3-41 3-41 3-41 3-42

Basic Language Features Overview of SQLJ Declarations ............................................................................................................ 4-1 Rules for SQLJ Declarations ............................................................................................................. 4-2 Iterator Declarations .......................................................................................................................... 4-2 Connection Context Declarations .................................................................................................... 4-3 Declaration IMPLEMENTS Clause.................................................................................................. 4-3 Declaration WITH Clause ................................................................................................................. 4-4 Standard WITH Clause Usage .................................................................................................. 4-4 Oracle-Specific WITH Clause Usage........................................................................................ 4-6 Example: Returnability .............................................................................................................. 4-7 Overview of SQLJ Executable Statements .......................................................................................... 4-8 Rules for SQLJ Executable Statements ............................................................................................ 4-8 SQLJ Clauses ....................................................................................................................................... 4-9 Specifying Connection Context Instances and Execution Context Instances......................... 4-10

v

Executable Statement Examples.................................................................................................... PL/SQL Blocks in Executable Statements ................................................................................... Java Host, Context, and Result Expressions..................................................................................... Overview of Host Expressions ...................................................................................................... Basic Host Expression Syntax........................................................................................................ Examples of Host Expressions ...................................................................................................... Overview of Result Expressions and Context Expressions ...................................................... Evaluation of Java Expressions at Run Time .............................................................................. Examples of Evaluation of Java Expressions at Run Time (ISO Code Generation) .............. Restrictions on Host Expressions.................................................................................................. Single-Row Query Results: SELECT INTO Statements................................................................ SELECT INTO Syntax..................................................................................................................... Examples of SELECT INTO Statements....................................................................................... Examples with Host Expressions in SELECT-List ..................................................................... SELECT INTO Error Conditions................................................................................................... Multirow Query Results: SQLJ Iterators .......................................................................................... Iterator Concepts ............................................................................................................................. Overview of Strongly Typed Iterators .................................................................................. Overview of Weakly Typed Iterators.................................................................................... General Steps in Using an Iterator................................................................................................ Named, Positional, and Result Set Iterators................................................................................ Using Named Iterators ................................................................................................................... Using Positional Iterators............................................................................................................... Using Iterators and Result Sets as Host Variables ..................................................................... Using Iterators and Result Sets as Iterator Columns ................................................................. Assignment Statements (SET) ............................................................................................................ Stored Procedure and Function Calls ................................................................................................ Calling Stored Procedures ............................................................................................................. Calling Stored Functions................................................................................................................ Using Iterators and Result Sets as Stored Function Returns ....................................................

5

4-11 4-11 4-12 4-13 4-13 4-15 4-17 4-17 4-18 4-24 4-24 4-24 4-25 4-25 4-26 4-26 4-27 4-27 4-29 4-29 4-30 4-31 4-34 4-37 4-39 4-41 4-42 4-43 4-44 4-45

Type Support Supported Types for Host Expressions................................................................................................ 5-1 Summary of Supported Types ......................................................................................................... 5-1 Supported Types and Requirements for JDBC 2.0 ........................................................................ 5-6 Using PL/SQL BOOLEAN, RECORD Types, and TABLE Types .............................................. 5-7 Support for Streams ................................................................................................................................. 5-8 General Use of SQLJ Streams ........................................................................................................... 5-9 Key Aspects of Stream Support Classes ......................................................................................... 5-9 Using SQLJ Streams to Send Data ................................................................................................ 5-10 Retrieving Data into Streams: Precautions.................................................................................. 5-12 Using SQLJ Streams to Retrieve Data .......................................................................................... 5-13 Stream Class Methods .................................................................................................................... 5-15 Examples of Retrieving and Processing Stream Data................................................................ 5-17 SQLJ Stream Objects as Output Parameters and Function Return Values............................. 5-18 Support for JDBC 2.0 LOB Types and Oracle Type Extensions................................................... 5-20 Package oracle.sql ........................................................................................................................... 5-20

vi

Support for BLOB, CLOB, and BFILE .......................................................................................... Support for Oracle ROWID ........................................................................................................... Support for Oracle REF CURSOR Types ..................................................................................... Support for Other Oracle Database 11g Data Types .................................................................. Extended Support for BigDecimal................................................................................................

6

5-21 5-26 5-29 5-31 5-31

Objects, Collections, and OPAQUE Types Oracle Objects and Collections ............................................................................................................. 6-1 Overview of Objects and Collections .............................................................................................. 6-1 Oracle Object Fundamentals ............................................................................................................ 6-3 Oracle Collection Fundamentals...................................................................................................... 6-3 Object and Collection Data Types ................................................................................................... 6-4 Custom Java Classes ................................................................................................................................ 6-4 Custom Java Class Interface Specifications .................................................................................... 6-5 Custom Java Class Support for Object Methods ........................................................................... 6-7 Custom Java Class Requirements .................................................................................................... 6-8 Compiling Custom Java Classes ................................................................................................... 6-12 Reading and Writing Custom Data .............................................................................................. 6-13 Additional Uses for ORAData Implementations ....................................................................... 6-13 User-Defined Types.............................................................................................................................. 6-17 JPublisher and the Creation of Custom Java Classes..................................................................... 6-20 What JPublisher Produces ............................................................................................................. 6-21 Generating Custom Java Classes .................................................................................................. 6-23 JPublisher INPUT Files and Properties Files............................................................................... 6-30 Creating Custom Java Classes and Specifying Member Names .............................................. 6-32 JPublisher Implementation of Wrapper Methods ...................................................................... 6-33 JPublisher Custom Java Class Examples ..................................................................................... 6-34 Extending Classes Generated by JPublisher ............................................................................... 6-37 Strongly Typed Objects and References in SQLJ Executable Statements................................. 6-39 Selecting Objects and Object References into Iterator Columns .............................................. 6-40 Updating an Object ......................................................................................................................... 6-40 Inserting an Object Created from Individual Object Attributes............................................... 6-42 Updating an Object Reference....................................................................................................... 6-43 Strongly Typed Collections in SQLJ Executable Statements ....................................................... 6-44 Accessing Nested Tables: TABLE syntax and CURSOR syntax............................................... 6-44 Inserting a Row that Includes a Nested Table ............................................................................ 6-45 Selecting a Nested Table into a Host Expression ....................................................................... 6-45 Manipulating a Nested Table Using TABLE Syntax.................................................................. 6-47 Selecting Data from a Nested Table Using a Nested Iterator ................................................... 6-47 Selecting a VARRAY into a Host Expression.............................................................................. 6-49 Inserting a Row that Includes a VARRAY .................................................................................. 6-50 Serialized Java Objects......................................................................................................................... 6-50 Serializing Java Classes to RAW and BLOB Columns............................................................... 6-51 SerializableDatum: an ORAData Implementation..................................................................... 6-52 SerializableDatum in SQLJ Applications..................................................................................... 6-55 SerializableDatum (Complete Class)............................................................................................ 6-55 Weakly Typed Objects, References, and Collections..................................................................... 6-57

vii

Support for Weakly Typed Objects, References, and Collections............................................ 6-57 Restrictions on Weakly Typed Objects, References, and Collections ...................................... 6-57 Oracle OPAQUE Types ........................................................................................................................ 6-58

7

Advanced Language Features Connection Contexts................................................................................................................................ 7-1 Connection Context Concepts .......................................................................................................... 7-2 Connection Context Logistics........................................................................................................... 7-3 More About Declaring and Using a Connection Context Class.................................................. 7-4 Example of Multiple Connection Contexts .................................................................................... 7-6 Implementation and Functionality of Connection Context Classes ........................................... 7-7 Using the IMPLEMENTS Clause in Connection Context Declarations ..................................... 7-8 Semantics-Checking of Your Connection Context Usage ............................................................ 7-9 Standard Data Source Support......................................................................................................... 7-9 SQLJ-Specific Data Sources............................................................................................................ 7-11 SQLJ-Specific Connection JavaBeans for JavaServer Pages ...................................................... 7-14 SQLJ Support for Global Transactions ......................................................................................... 7-17 Execution Contexts................................................................................................................................ 7-24 Relation of Execution Contexts to Connection Contexts........................................................... 7-24 Creating and Specifying Execution Context Instances .............................................................. 7-25 Execution Context Synchronization ............................................................................................. 7-26 Execution Context Methods .......................................................................................................... 7-26 Status Methods ......................................................................................................................... 7-27 Control Methods ...................................................................................................................... 7-27 Cancellation Method ............................................................................................................... 7-28 Update Batching Methods ...................................................................................................... 7-28 Savepoint Methods .................................................................................................................. 7-29 Close Method............................................................................................................................ 7-30 Example: Using ExecutionContext Methods ....................................................................... 7-30 Relation of Execution Contexts to Multithreading..................................................................... 7-31 Multithreading in SQLJ ....................................................................................................................... 7-31 Iterator Class Implementation and Advanced Functionality ....................................................... 7-33 Implementation and Functionality of Iterator Classes .............................................................. 7-34 Using the IMPLEMENTS Clause in Iterator Declarations ........................................................ 7-35 Support for Extending Iterator Classes........................................................................................ 7-35 Result Set Iterators .......................................................................................................................... 7-36 Scrollable Iterators........................................................................................................................... 7-36 Advanced Transaction Control........................................................................................................... 7-41 SET TRANSACTION Syntax......................................................................................................... 7-42 Access Mode Settings ..................................................................................................................... 7-42 Isolation Level Settings................................................................................................................... 7-43 Using JDBC Connection Class Methods ...................................................................................... 7-43 SQLJ and JDBC Interoperability........................................................................................................ 7-44 SQLJ Connection Context and JDBC Connection Interoperability.......................................... 7-44 SQLJ Iterator and JDBC Result Set Interoperability................................................................... 7-48 Support for Dynamic SQL................................................................................................................... 7-50 Meta Bind Expressions ................................................................................................................... 7-51

viii

SQLJ Dynamic SQL Examples....................................................................................................... 7-52 Execution Plan Fixing ........................................................................................................................... 7-54

8

Translator Command Line and Options Translator Command Line and Properties Files ................................................................................ 8-1 SQLJ Options, Flags, and Prefixes ................................................................................................... 8-2 Command-Line Syntax and Operations ......................................................................................... 8-9 Properties Files for Option Settings.............................................................................................. 8-12 SQLJ_OPTIONS Environment Variable for Option Settings.................................................... 8-15 Order of Precedence of Option Settings ...................................................................................... 8-15 Basic Translator Options...................................................................................................................... 8-16 Basic Options for the Command Line Only ................................................................................ 8-17 Options for Output Files and Directories .................................................................................... 8-21 Connection Options ........................................................................................................................ 8-25 Options for Reporting and Line-Mapping .................................................................................. 8-33 Options for DMS ............................................................................................................................. 8-38 Options for Code Generation, Optimizations, and CHAR Comparisons .............................. 8-40 Advanced Translator Options............................................................................................................. 8-47 Prefixes that Pass Option Settings to Other Executables........................................................... 8-48 Flags for Special Processing........................................................................................................... 8-51 Semantics-Checking and Offline-Parsing Options..................................................................... 8-56 Translator Support and Options for Alternative Environments.................................................. 8-62 Java and Compiler Options ........................................................................................................... 8-62 Customization Options .................................................................................................................. 8-67

9

Translator and Run Time Functionality Internal Translator Operations .............................................................................................................. 9-1 Java and SQLJ Code-Parsing and Syntax-Checking ..................................................................... 9-1 SQL Semantics-Checking and Offline Parsing .............................................................................. 9-2 Code Generation................................................................................................................................. 9-3 Java Compilation................................................................................................................................ 9-6 Profile Customization (ISO Code Generation) .............................................................................. 9-7 Functionality of Translator Errors, Messages, and Exit Codes........................................................ 9-8 Translator Error, Warning, and Information Messages ............................................................... 9-8 Translator Status Messages............................................................................................................ 9-10 Translator Exit Codes ..................................................................................................................... 9-11 SQLJ Run Time...................................................................................................................................... 9-11 SQLJ Run Time Packages ............................................................................................................... 9-12 Categories of Run-Time Errors ..................................................................................................... 9-13 Globalization Support in the Translator and Run Time ............................................................... 9-13 Character Encoding and Language Support............................................................................... 9-14 SQLJ and Java Settings for Character Encoding and Language Support ............................... 9-16 SQLJ Extended Globalization Support ........................................................................................ 9-18 Manipulation Outside of SQLJ for Globalization Support ....................................................... 9-22

ix

10

Performance and Debugging Performance Enhancement Features.................................................................................................. Row Prefetching .............................................................................................................................. Statement Caching .......................................................................................................................... Update Batching .............................................................................................................................. Column Definitions....................................................................................................................... Parameter Size Definitions........................................................................................................... SQLJ Debugging Features ................................................................................................................. SQLJ -linemap Flag for Debugging ............................................................................................ Server-Side debug Option............................................................................................................ Overview of the AuditorInstaller Specialized Customizer..................................................... Overview of Developing and Debugging in Oracle10g JDeveloper...................................... SQLJ Support for Oracle Performance Monitoring...................................................................... Overview of SQLJ DMS Support ................................................................................................ Summary of SQLJ Command-Line Options for DMS ............................................................. SQLJ Run Time Commands and Properties File Settings for DMS ....................................... SQLJ DMS Sensors and Metrics .................................................................................................. SQLJ DMS Examples ....................................................................................................................

11

SQLJ in the Server Overview of Server-Side SQLJ ........................................................................................................... Creating SQLJ Code for Use in the Server ....................................................................................... Database Connections Within the Server .................................................................................... Coding Issues Within the Server................................................................................................... Default Output Device in the Server ............................................................................................ Name Resolution in the Server ..................................................................................................... SQL Names Versus Java Names ................................................................................................... Translating SQLJ Source on a Client and Loading Components ................................................ Loading Classes and Resources into the Server ......................................................................... Naming of Loaded Class and Resource Schema Objects .......................................................... Publishing the Application After Loading Class and Resource Files...................................... Summary: Running a Client Application in the Server............................................................. Loading SQLJ Source and Translating in the Server ................................................................... Loading SQLJ Source Code into the Server............................................................................... Option Support in the Server Embedded Translator............................................................... Naming of Loaded Source and Generated Class and Resource Schema Objects ................ Error Output from the Server Embedded Translator .............................................................. Publishing the Application After Loading Source Files.......................................................... Dropping Java Schema Objects ........................................................................................................ Additional Server-Side Considerations.......................................................................................... Java Multithreading in the Server............................................................................................... Recursive SQLJ Calls in the Server ............................................................................................. Verifying that Code is Running in the Server...........................................................................

A

10-1 10-2 10-3 10-9 10-16 10-17 10-19 10-19 10-20 10-20 10-20 10-20 10-21 10-22 10-23 10-24 10-26

11-1 11-2 11-3 11-3 11-4 11-5 11-5 11-5 11-6 11-7 11-9 11-9 11-10 11-11 11-12 11-15 11-16 11-16 11-17 11-17 11-17 11-18 11-19

Customization and Specialized Customizers More About Profiles ............................................................................................................................... A-1

x

Creation of a Profile During Code Generation ............................................................................. Sample Profile Entry ......................................................................................................................... SQLJ Executable Statement....................................................................................................... Corresponding SQLJ Profile Entry .......................................................................................... More About Profile Customization ..................................................................................................... Overview of the Customizer Harness and Customizers............................................................. Steps in the Customization Process................................................................................................ Creation and Registration of a Profile Customization................................................................. Customization Error and Status Messages.................................................................................... Functionality of a Customized Profile at Run Time..................................................................... Customization Options and Choosing a Customizer....................................................................... Overview of Customizer Harness Options ................................................................................... Syntax for Customizer Harness Options ................................................................................ Options Supported by the Customizer Harness ................................................................... General Customizer Harness Options ........................................................................................... Profile Backup Option (backup) .............................................................................................. Customization Connection Context Option (context) .......................................................... Customizer Option (customizer) ........................................................................................... Customization JAR File Digests Option (digests) ............................................................... Customization Help Option (help)........................................................................................ Customization Verbose Option (verbose) ............................................................................ Customizer Harness Options for Connections ........................................................................... Customization User Option (user) ........................................................................................ Customization Password Option (password) ..................................................................... Customization URL Option (url)........................................................................................... Customization JDBC Driver Option (driver) ....................................................................... Customizer Harness Options that Invoke Specialized Customizers....................................... Specialized Customizer: Profile Debug Option (debug).................................................... Specialized Customizer: Profile Print Option (print) ......................................................... Specialized Customizer: Profile Semantics-Checking Option (verify) ............................ Overview of Customizer-Specific Options.................................................................................. Oracle Customizer Options ........................................................................................................... Options Supported by Oracle Customizer........................................................................... Oracle Customizer Version Compatibility Option (compat) ............................................ Oracle Customizer Force Option (force)............................................................................... Oracle Customizer Column Definition Option (optcols) ................................................... Oracle Customizer Parameter Definition Option (optparams)......................................... Oracle Customizer Parameter Default Size Option (optparamdefaults)......................... Oracle Customizer CHAR Comparisons with Blank Padding (fixedchar) ..................... Oracle Customizer Show-SQL Option (showSQL)............................................................. Oracle Customizer Statement Cache Size Option (stmtcache).......................................... Oracle Customizer Summary Option (summary)............................................................... Options for Other Customizers..................................................................................................... SQLJ Translator Options for Profile Customization .................................................................. JAR Files for Profiles ............................................................................................................................ JAR File Requirements ................................................................................................................... JAR File Logistics ............................................................................................................................

A-2 A-2 A-2 A-3 A-3 A-4 A-4 A-5 A-6 A-6 A-6 A-7 A-7 A-8 A-8 A-9 A-9 A-10 A-10 A-11 A-12 A-12 A-12 A-13 A-14 A-14 A-15 A-15 A-16 A-17 A-18 A-18 A-18 A-19 A-20 A-20 A-22 A-23 A-24 A-25 A-26 A-27 A-28 A-29 A-29 A-29 A-30

xi

SQLCheckerCustomizer for Profile Semantics-Checking ............................................................ Invoking SQLCheckerCustomizer with the Customizer Harness verify Option.................. SQLCheckerCustomizer Options.................................................................................................. SQLCheckerCustomizer Semantics-Checker Option (checker) ........................................ SQLCheckerCustomizer Warnings Option (warn)............................................................. AuditorInstaller Customizer for Debugging ................................................................................... Overview of Auditors and Code Layers...................................................................................... Invoking AuditorInstaller with the Customizer Harness debug Option ............................... AuditorInstaller Run Time Output............................................................................................... AuditorInstaller Options................................................................................................................ AuditorInstaller Depth Option (depth) ................................................................................ AuditorInstaller Log File Option (log).................................................................................. AuditorInstaller Prefix Option (prefix)................................................................................. AuditorInstaller Return Arguments Option (showReturns)............................................. AuditorInstaller Thread Names Option (showThreads) ................................................... AuditorInstaller Uninstall Option (uninstall)...................................................................... Full Command-Line Examples .....................................................................................................

Index

xii

A-30 A-31 A-32 A-32 A-33 A-33 A-34 A-34 A-35 A-36 A-37 A-37 A-38 A-38 A-39 A-39 A-40

List of Tables 4–1 4–2 5–1 5–2 5–3 6–1 7–1 8–1 8–2 8–3 8–4 8–5 8–6 9–1 9–2 9–3

SQLJ Statement Clauses ............................................................................................................ 4-9 SQLJ Assignment Clauses ..................................................................................................... 4-10 Type Mappings for Supported Host Expression Types ....................................................... 5-2 Correlation between Oracle Extensions and JDBC 2.0 Types ............................................. 5-6 Plausible values for the for_update option and the corresponding SQL statement ..... 5-29 JPublisher SQL Type Categories, Supported Settings, and Defaults .............................. 6-28 Table showing the options and values for generating outlines ....................................... 7-57 SQLJ Translator Options ........................................................................................................... 8-2 SQLJ Support for javac Options............................................................................................... 8-8 Tests and Flags for SQLJ Warnings...................................................................................... 8-34 Oracle Online Semantics-Checkers Chosen by OracleChecker........................................ 8-57 Oracle Offline Semantics-Checkers Chosen by OracleChecker ....................................... 8-57 Feature Comparison: Offline Parsing Versus Online Semantics-Checking ................... 8-57 Steps for Generated Calls, ISO Standard Versus Oracle-Specific ....................................... 9-5 SQLJ Translator Error Message Categories......................................................................... 9-10 JDBC and SQLJ Types and Corresponding Globalization Types .................................... 9-19

-xiii

-xiv Oracle Database SQLJ Developer’s Guide and Reference

Preface This preface introduces you to the Oracle Database SQLJ Developer’s Guide and Reference, discussing the intended audience and conventions of this document. A list of related Oracle documents is also provided.

Audience This manual is intended for anyone with an interest in SQLJ programming but assumes at least some prior knowledge of the following: ■

Java



SQL



PL/SQL



Oracle Database

Although general knowledge of SQL is sufficient, any knowledge of JDBC and Oracle-specific SQL features would be helpful as well.

Documentation Accessibility Our goal is to make Oracle products, services, and supporting documentation accessible, with good usability, to the disabled community. To that end, our documentation includes features that make information available to users of assistive technology. This documentation is available in HTML format, and contains markup to facilitate access by the disabled community. Accessibility standards will continue to evolve over time, and Oracle is actively engaged with other market-leading technology vendors to address technical obstacles so that our documentation can be accessible to all of our customers. For more information, visit the Oracle Accessibility Program Web site at http://www.oracle.com/accessibility/ Accessibility of Code Examples in Documentation Screen readers may not always correctly read the code examples in this document. The conventions for writing code require that closing braces should appear on an otherwise empty line; however, some screen readers may not always read a line of text that consists solely of a bracket or brace.

xv

Accessibility of Links to External Web Sites in Documentation This documentation may contain links to Web sites of other companies or organizations that Oracle does not own or control. Oracle neither evaluates nor makes any representations regarding the accessibility of these Web sites. TTY Access to Oracle Support Services Oracle provides dedicated Text Telephone (TTY) access to Oracle Support Services within the United States of America 24 hours a day, 7 days a week. For TTY support, call 800.446.2398. Outside the United States, call +1.407.458.2479.

Related Documents Also available from the Oracle Java Platform group are the following Oracle resources: ■

Oracle Database Java Developer's Guide This book introduces the basic concepts of Java in Oracle Database 11g and provides general information about server-side configuration and functionality. Information that pertains to Oracle Database Java environment in general, rather than to a particular product such as JDBC or SQLJ, is in this book. It also discusses Java stored procedures, which are programs that run directly in Oracle Database. With stored procedures, Java developers can implement business logic at the server level, thereby improving application performance, scalability, and security.



Oracle Database JDBC Developer's Guide and Reference This book covers programming syntax and features of the Oracle implementation of the JDBC standard. This includes an overview of the Oracle JDBC drivers, details of the Oracle implementation of JDBC 1.22, 2.0, 3.0, and 4.0 features, and discussion of Oracle JDBC type extensions and performance extensions.



Oracle Database JPublisher User's Guide This book describes how to use the Oracle JPublisher utility to translate user-defined SQL types or PL/SQL packages into Java classes. If you are developing SQLJ or JDBC applications that use object types, VARRAY types, nested table types, object reference types, or PL/SQL packages, then JPublisher can generate custom Java classes to map to them.

The following documents are from the Oracle Server Technologies group:

xvi



Oracle XML DB Developer's Guide



Oracle XML Developer's Kit Programmer's Guide



Oracle Database XML Java API Reference



Oracle Database Advanced Application Developer's Guide



Oracle Database SecureFiles and Large Objects Developer's Guide



Oracle Database Object-Relational Developer's Guide



Oracle Database PL/SQL Packages and Types Reference



Oracle Database PL/SQL Language Reference



Oracle Database SQL Language Reference



Oracle Database Net Services Administrator's Guide



Oracle Database Advanced Security Administrator's Guide



Oracle Database Globalization Support Guide



Oracle Database Reference



Oracle Database Sample Schemas Oracle error message documentation is available in HTML only. If you have access to the Oracle Documentation CD only, you can browse the error messages by range. Once you find the specific range, use the "find in page" feature of your browser to locate the specific message. When connected to the Internet, you can search for a specific error message using the error message search feature of the Oracle online documentation.

Note:

For documentation of SQLJ standard features and syntax, refer to the following ANSI specification: Information Technology - Database Languages - SQL - Part 10: Object Language Bindings (SQL/OLB) You can obtain this from ANSI through the following Web site: http://www.ansi.org/

(Click "eStandards Store" and search for the specification number.) The following location has SQLJ sample applications: http://www.oracle.com/technology/sample_code/tech/java/sqlj_jdbc/sqlj.h tml

Conventions This section describes the conventions used in the text and code examples of this documentation set. It describes: ■

Conventions in Text



Conventions in Code Examples Also note that command-line examples are for a UNIX environment with a system prompt of "%". This is only by convention and can be adjusted as appropriate for your operating system.

Note:

Conventions in Text There are various conventions in text to help you more quickly identify special terms. The following table describes those conventions and provides examples of their use. Convention

Meaning

Example

Italics

Italic typeface indicates book titles or Oracle Database Concepts emphasis, or terms that are defined in the Ensure that the recovery catalog and target text. database do not reside on the same disk.

xvii

Convention

Meaning

Example

UPPERCASE monospace (fixed-width) font

Uppercase monospace typeface indicates elements supplied by the system. Such elements include parameters, privileges, data types, RMAN keywords, SQL keywords, SQL*Plus or utility commands, packages and methods, as well as system-supplied column names, database objects and structures, usernames, and roles.

You can specify this clause only for a NUMBER column.

Lowercase monospace typeface indicates executables, filenames, directory names, and sample user-supplied elements. Such elements include computer and database names, net service names, and connect identifiers, as well as user-supplied database objects and structures, column names, packages and classes, usernames and roles, program units, and parameter values.

Enter sqlplus to open SQL*Plus.

lowercase monospace (fixed-width) font

You can back up the database by using the BACKUP command. Query the TABLE_NAME column in the USER_TABLES data dictionary view. Use the DBMS_STATS.GENERATE_STATS procedure.

The password is specified in the orapwd file. Back up the data files and control files in the /disk1/oracle/dbs directory. The department_id, department_name, and location_id columns are in the hr.departments table. Set the QUERY_REWRITE_ENABLED initialization parameter to true.

Note: Some programmatic elements use a mixture of UPPERCASE and lowercase. Connect as oe user. Enter these elements as shown. The JRepUtil class implements these methods. Lowercase italic monospace font lowercase represents place holders or variables. italic monospace (fixed-width) font

You can specify the parallel_clause. Run old_release.SQL where old_release refers to the release you installed prior to upgrading.

Conventions in Code Examples Code examples illustrate SQL, PL/SQL, SQL*Plus, or other command-line statements. They are displayed in a monospace (fixed-width) font and separated from standard text as shown in this example: SELECT username FROM dba_users WHERE username = ’MIGRATE’;

The following table describes typographic conventions used in code examples and provides examples of their use.

Convention

Meaning

Example



In this document, angle brackets are used instead of regular brackets to enclose one or more optional items. Do not enter the angle brackets. (Regular brackets are not used due to SQLJ syntax considerations.)

DECIMAL (digits < , precision >)

|

A vertical bar represents a choice of two {ENABLE | DISABLE} or more options within brackets or braces. [COMPRESS | NOCOMPRESS] Enter one of the options. Do not enter the vertical bar.

xviii

Convention

Meaning

...

Horizontal ellipsis points indicate either: ■



Other notation

Italics

Example

Omission of parts of the code that are CREATE TABLE ... AS subquery; not directly related to the example That you can repeat a portion of the code

You must enter symbols other than brackets, braces, vertical bars, and ellipsis points as shown. Italicized text indicates place holders or variables for which you must supply particular values.

SELECT col1, col2, ... , coln FROM employees; acctbal NUMBER(11,2); acct

CONSTANT NUMBER(4) := 3;

CONNECT SYSTEM Enter password: password DB_NAME = database_name

UPPERCASE

lowercase

Uppercase typeface indicates elements supplied by the system. These terms are in uppercase to distinguish them from terms you define. Unless terms appear in brackets, enter them in the order and with the spelling shown. However, because these terms are not case-sensitive, you can enter them in lowercase.

SELECT last_name, employee_id FROM employees;

Lowercase typeface indicates programmatic elements that you supply. For example, lowercase indicates names of tables, columns, or files.

SELECT last_name, employee_id FROM employees;

SELECT * FROM USER_TABLES; DROP TABLE hr.employees;

sqlplus hr/hr

CREATE USER mjones IDENTIFIED BY Note: Some programmatic elements use a ty3MU9; mixture of UPPERCASE and lowercase. Enter these elements as shown.

xix

xx

What’s New in 11g Release 1 (11.1) The following new SQLJ-related features have been introduced in Oracle Database 11g Release 1 (11.1): ■

Support for JDK 1.5 and JDK 1.6



Enhanced Profile Print Option



Outline Generation



Support for Global Transactions

Support for JDK 1.5 and JDK 1.6 In Oracle Database 11g Release 1 (11.1) SQLJ programs, the following JDK1.5 specific language structures are allowed outside the #SQL region: JDK 1.5 ■ strictfp ■

Assert



Generics



Enhanced for Loop



Autoboxing/Unboxing



Typesafe Enums



Varargs



Static Import



Annotation

Note: Visit the following Sun site more information about all the JDK 1.5 features: http://java.sun.com/j2se/1.5.0/docs/relnotes/features.htm l

JDK 1.6 Starting from Oracle Database 11g Release 1 (11.1), SQLJ programs are supported in JDK 1.6.x environment. Refer to Chapter 1, "Getting Started" for more information.

xxi

Enhanced Profile Print Option The SQLJ profile print option has been enhanced to output all the options set on the customizer. This feature is discussed in detail in "Profile Customization (ISO Code Generation)" on page 9-7.

Outline Generation You can use the outline feature of Oracle to support plan stability. This feature is discussed in detail in "Execution Plan Fixing" on page 7-54.

Support for Global Transactions The X/Open Distributed Transaction Processing coordinates the work between application programs and resource managers into global transactions. This feature is discussed in detail in"SQLJ Support for Global Transactions" on page 7-17.

xxii

1 Getting Started This chapter guides you through the basics of testing your Oracle SQLJ installation and configuration and running a simple application. This chapter discusses the following topics: ■

Assumptions and Requirements



Checking the Installation and Configuration



Testing the Setup

Assumptions and Requirements This section discusses basic assumptions about your environment and requirements of your system so that you can run SQLJ, covering the following topics: ■

Assumptions About Your Environment



Requirements for Using the Oracle SQLJ Implementation



SQLJ Environment



Environment Considerations



SQLJ Backward Compatibility

Assumptions About Your Environment The following assumptions are made about the system on which you will be running the Oracle SQLJ implementation: ■

You have a standard Java environment that is operational on your system. This would typically be using a Sun Microsystems Java Development Kit (JDK), but other implementations of Java will work. Ensure that you can run Java (typically java) and the Java compiler (typically javac). To translate and run SQLJ applications on a Sun JDK, you must use JDK 1.5.x or JDK 1.6.x. You must use the JDBC driver of the same version as that of SQLJ, can be thin or OCI8 driver See Also:

"SQLJ Environment" on page 1-2

Getting Started 1-1

Assumptions and Requirements

A Java run-time environment (JRE), such as the one installed with Oracle Database 11g, is not by itself sufficient for translating SQLJ programs. However, a JRE is sufficient for running SQLJ programs that have already been translated and compiled.

Note:



You can already run JDBC applications in your environment. See also: Oracle Database JDBC Developer's Guide and Reference for more information about JDBC drivers

Requirements for Using the Oracle SQLJ Implementation The following are required to use the Oracle SQLJ implementation: ■

A database system that is accessible using your JDBC driver



Class files for the SQLJ translator Translator-related classes are available in the following file: ORACLE_HOME/sqlj/lib/translator.jar

For more information about translator.jar, refer to "Set the Path and Classpath" on page 1-4.

Note:



Class files for the SQLJ run time. ORACLE_HOME/sqlj/lib/runtime12.jar

Note: runtime12ee.jar has been deprecated in Oracle Database 11g Release 1 (11.1). Use runtime12.jar instead.

SQLJ Environment To ensure that you have a fully working environment, you must consider several aspects of your environment: SQLJ and its code generation mode, JDBC, and the JDK. Code generation is determined by the SQLJ -codegen option. Refer to "Code Generation (-codegen)" on page 8-41 for more information.

Note:

The following is a typical environment setup for Oracle-specific code generation: ■

SQLJ code generation: -codegen=oracle (default)



SQLJ translation library: translator.jar



SQLJ run time library: runtime12.jar



JDBC drivers: Oracle 11g release 1 (11.1)



JDK version: 1.5.x or 1.6.x

1-2 Oracle Database SQLJ Developer’s Guide and Reference

Checking the Installation and Configuration

If you are running against different JDBC versions, then translate against the earlier version.

Note:

Environment Considerations You can run the application against a JDK version that is at least as high as the version you translated the code under.

For more information about translator.jar, refer to "Set the Path and Classpath" on page 1-4.

Note:

SQLJ Backward Compatibility You must keep in mind the following points regarding backward compatibility of the Oracle SQLJ implementation: ■



Code generated with an earlier release of the SQLJ translator can continue to run and compile against current run time libraries. However, this is subject to the cross-compatibility limitations discussed in "Environment Considerations" on page 1-3. Oracle-specific translator output, that is, code generated with the default -codegen=oracle setting, must be created and executed using the runtime12.jar library. In addition: –

Such code will be executable under future Oracle JDBC and SQLJ implementations.



Such code, however, will not be executable under earlier releases of Oracle JDBC drivers and Oracle SQLJ run time. In these circumstances, you will have to retranslate the code.

Checking the Installation and Configuration After you have verified that the preceding assumptions and requirements are satisfied, you must check your SQLJ installation. You must: ■

Check for Availability of SQLJ and Demo Applications



Check for Installed Directories and Files



Set the Path and Classpath



Verify Installation of the sqljutl Package

Check for Availability of SQLJ and Demo Applications Following are the release-specific notes regarding availability of SQLJ and its demo applications: ■

SQLJ and its demo applications are available from the Oracle Technology Network (OTN) at the following location: http://www.oracle.com/technology/sample_code/tech/java/sqlj_j dbc/sqlj.html



For Oracle Database 11g, SQLJ and its demo applications are included with the installation. Getting Started 1-3

Checking the Installation and Configuration

Check for Installed Directories and Files Verify that the following directories have been installed and are populated: Directories for JDBC Refer to the Oracle Database JDBC Developer's Guide and Reference for information about JDBC files that should be installed on your system. Directories for SQLJ Installing the Oracle Database 11g Java environment includes, among other things, installing a sqlj directory under your ORACLE_HOME directory. The sqlj directory contains the following subdirectories: ■

demo (demo applications, including some referenced in this chapter)



lib (.jar files containing class files for SQLJ)

Check whether all these directories have been created and populated, especially lib. The ORACLE_HOME/bin directory contains utilities for all Java product areas, including the SQLJ and JPublisher executable files.

Set the Path and Classpath Ensure that the PATH and CLASSPATH environment variables have the necessary settings for the Oracle SQLJ implementation. Set the PATH and CLASSPATH environment variables as follows for the Oracle SQLJ implementation: ■

Setting PATH To run the sqlj script, which invokes the SQLJ translator, without having to fully specify its path, verify that the PATH environment variable has been updated to include the following: ORACLE_HOME/bin

Use backslash (\) for Microsoft Windows. Replace ORACLE_HOME with your actual Oracle home directory. ■

Setting CLASSPATH Update the CLASSPATH environment variable to include the current directory as well as the following: ORACLE_HOME/sqlj/lib/translator.jar

Use backslash (\) for Microsoft Windows. Replace ORACLE_HOME with your actual Oracle home directory.

Include the following run time library in the CLASSPATH: ORACLE_HOME/sqlj/lib/runtime12.jar

In addition, you must include one of the following JDBC JARs in the CLASSPATH: ORACLE_HOME/jdbc/lib/ojdbc5*.jar ORACLE_HOME/jdbc/lib/ojdbc6*.jar

1-4 Oracle Database SQLJ Developer’s Guide and Reference

Testing the Setup

To translate or run SQLJ programs in JDK 1.5.x environment, you should have ojdbc5.jar in the classpath and to translate or run SQLJ programs in JDK 1.6.x environment, you should have ojdbc6.jar in the classpath. Ensure that the correct JDBC JAR is picked up at runtime for connecting to Oracle Database.

Note:

See Also: "Requirements for Using the Oracle SQLJ Implementation" on page 1-2

You will not be able to run the SQLJ translator if you do not add a run time library. You must specify a run time library as well as the translator library in the CLASSPATH.

Note:

To see if SQLJ is installed correctly, and to see the version information for SQLJ, JDBC, and Java, run the following command: % sqlj -version-long

Verify Installation of the sqljutl Package The sqljutl package is required for online checking of stored procedures and functions in Oracle Database instance. Beginning with Oracle8i Database release 8.1.5, it is installed automatically under the SYS schema during installation of the server-side Java virtual machine (JVM) for a Java-enabled database. If your database is not Java-enabled, then you will have to manually install this package. If you want to verify the installation of sqljutl, then issue the following SQL command from SQL*Plus: describe sys.sqljutl

This should result in a brief description of the package. If you get a message indicating that the package cannot be found, or if you want to install an updated version of the package, then you can install it by using SQL*Plus to run the sqljutl.sql script (or sqljutl8.sql for Oracle8i Database), which is located at: ORACLE_HOME/sqlj/lib/sqljutl.sql

Testing the Setup You can test your database, JDBC, and SQLJ setup using demo applications defined in the following source files: ■

TestInstallCreateTable.java



TestInstallJDBC.java



TestInstallSQLJ.sqlj



TestInstallSQLJChecker.sqlj

There is also a Java properties file, connect.properties, that helps you set up your database connection. You must edit this file to set appropriate user, password, and URL values. Getting Started 1-5

Testing the Setup

The demo applications discussed here are provided with your SQLJ installation in the demo directory: ORACLE_HOME/sqlj/demo

You may have to edit some of the source files and translate and compile them, as appropriate. The demo applications provided with the Oracle SQLJ implementation refer to tables on Oracle Database account with user name scott and password tiger. Most Oracle Database installations have this account. You can substitute other values for scott and tiger if desired. Running the demo applications requires that the demo directory be the current directory, and that the current directory (".") should be specified in the CLASSPATH.

Note:

This section covers the following topics: ■

Set Up the Run Time Connection



Create a Table to Verify the Database



Verify the JDBC Driver



Verify the SQLJ Translator and Run Time



Verify the SQLJ Translator Connection to the Database See Also:

"Check for Availability of SQLJ and Demo Applications"

on page 1-3

Set Up the Run Time Connection This section describes how to update the connect.properties file to configure your Oracle connection for run time. The file is in the demo directory and looks something like the following: In the Oracle Database 11g JDBC implementation, database URL connection strings using SIDs are deprecated. Following is an example, where orcl is the SID:

Note:

jdbc:oracle:thin:@localhost:1521:orcl

This would now generate a warning, but not a fatal error. Instead, you are encouraged to use database service names, such as myservice in the following example: jdbc:oracle:thin:@localhost:1521/myservice

Refer to the Oracle Database JDBC Developer's Guide and Reference for information about database service names. # Users should uncomment one of the following URLs or add their own. # (If using Thin, edit as appropriate.) #sqlj.url=jdbc:oracle:thin:@localhost:1521/myservice #sqlj.url=jdbc:oracle:oci:@ # # User name and password here sqlj.user=scott sqlj.password=tiger

1-6 Oracle Database SQLJ Developer’s Guide and Reference

Testing the Setup

Connecting with an Oracle JDBC Driver Use oci in the connection string for Oracle JDBC OCI driver in any new code. For backward compatibility, however, oci8 is still accepted. Therefore, you do not have to change existing code. If you are using the JDBC Thin driver, then uncomment the thin URL line in connect.properties and edit it as appropriate for your Oracle connection. Use the same URL that was specified when your JDBC driver was set up.

Create a Table to Verify the Database The following tests assume a table called SALES. Compile and run TestInstallCreateTable as follows: % javac TestInstallCreateTable.java % java TestInstallCreateTable

This will create the table for you if the database and the JDBC driver are working and the connection is set up properly in the connect.properties file. Note: If you already have a table called SALES in your schema and do not want it altered, edit TestInstallCreateTable.java to change the table name. Otherwise, your original table will be dropped and replaced.

If you do not want to use TestInstallCreateTable, then you can create the SALES table using the following SQL statement: CREATE TABLE SALES ( ITEM_NUMBER NUMBER, ITEM_NAME CHAR(30), SALES_DATE DATE, COST NUMBER, SALES_REP_NUMBER NUMBER, SALES_REP_NAME CHAR(20));

Verify the JDBC Driver If you want to further test Oracle JDBC driver, then use the TestInstallJDBC demo. Verify that your connection is set up properly in connect.properties. Then, compile and run TestInstallJDBC, as follows: % javac TestInstallJDBC.java % java TestInstallJDBC

The program should print: Hello, JDBC!

Verify the SQLJ Translator and Run Time Now translate and run the TestInstallSQLJ demo, a SQLJ application that has functionality similar to that of TestInstallJDBC. Use the following command to translate the source: % sqlj TestInstallSQLJ.sqlj

Getting Started 1-7

Testing the Setup

Note that this command also compiles the application. On a UNIX environment, the sqlj script is in ORACLE_HOME/bin, which should already be in the PATH. On Windows, use the sqlj.exe executable in the bin directory. The SQLJ translator.jar file has the class files for the SQLJ translator and run time. It is located in ORACLE_HOME/sqlj/lib and should already be in the CLASSPATH. See Also:

"Set the Path and Classpath" on page 1-4

Now run the application as follows: % java TestInstallSQLJ

The program should print: Hello, SQLJ!

Verify the SQLJ Translator Connection to the Database If the SQLJ translator is able to connect to a database, then it can provide online semantics-checking of your SQL operations during translation. The SQLJ translator is written in Java and uses JDBC to get information it needs from a database connection that you specify. You provide the connection parameters for online semantics-checking using the sqlj script command line or using a SQLJ properties file, which is sqlj.properties by default. While still in the demo directory, edit the sqlj.properties file and update, comment, or uncomment the sqlj.password, sqlj.url, and sqlj.driver lines, as appropriate, to reflect your database connection information. For assistance, refer to the comments in the sqlj.properties file. Following is an example of what the appropriate driver, URL, and password settings might be if you are using Oracle JDBC OCI driver. sqlj.url=jdbc:oracle:oci:@ sqlj.driver=oracle.jdbc.OracleDriver sqlj.password=tiger

Online semantics-checking is enabled as soon as you specify a user name for the translation-time connection. You can specify the user name either by uncommenting the sqlj.user line in the sqlj.properties file or by using the -user command-line option. The user, password, url, and driver options all can be set either on the command line or in the properties file. See Also:

"Connection Options" on page 8-25

You can test online semantics-checking by translating the TestInstallSQLJChecker.sqlj file located in the demo directory, as follows (or using another user name, if appropriate): % sqlj -user=scott TestInstallSQLJChecker.sqlj

This should produce the following error message if you are using one of Oracle JDBC drivers: TestInstallSQLJChecker.sqlj:41: Warning: Unable to check SQL query. Error returned by database is: ORA-00904: invalid column name

1-8 Oracle Database SQLJ Developer’s Guide and Reference

Testing the Setup

Edit TestInstallSQLJChecker.sqlj to fix the error on line 41. The column name should be ITEM_NAME instead of ITEM_NAMAE. Once you make this change, you can translate and run the application without error using the following commands: % sqlj -user=scott TestInstallSQLJChecker.sqlj % java TestInstallSQLJChecker

If everything works, then the following line is displayed: Hello, SQLJ Checker!

Getting Started 1-9

Testing the Setup

1-10 Oracle Database SQLJ Developer’s Guide and Reference

2 Introduction to SQLJ This chapter provides a general overview of SQLJ features and scenarios. The following topics are discussed: ■

Overview of SQLJ



Overview of SQLJ Components



Overview of Oracle Extensions to the SQLJ Standard



Basic Translation Steps and Run-Time Processing



SQLJ Sample Code



Alternative Deployment Scenarios



Alternative Development Scenarios

Overview of SQLJ This section introduces the basic concepts of SQLJ and discusses the complementary relationship between Java and PL/SQL in Oracle Database applications. SQLJ enables applications programmers to embed SQL statements in Java code in a way that is compatible with the Java design philosophy. A SQLJ program is a Java program containing embedded SQL statements that comply with the International Standardization Organization (ISO) standard SQLJ Language Reference syntax. The Oracle SQLJ implementation supports the ISO SQLJ standard specification. The standard covers only static SQL operations, which are predefined SQL operations that do not change in real time while a user runs the application. The Oracle SQLJ implementation also offers extensions to support dynamic SQL operations, which are not predefined and the operations can change in real time. It is also possible to use dynamic SQL operations through Java Database Connectivity (JDBC) code or PL/SQL code within a SQLJ application. Typical applications contain more static SQL operations than dynamic SQL operations. SQLJ consists of a translator and a run-time component and is smoothly integrated into your development environment. You can run the translator to translate, compile, and customize the code in a single step using the sqlj front-end utility. The translation process replaces embedded SQL statements with calls to the SQLJ run time, which processes the SQL statements. In ISO standard SQLJ this is typically, but not necessarily, performed through calls to a JDBC driver. To access Oracle Database, you would typically use an Oracle JDBC driver. When you run the SQLJ application, the run time is started to handle the SQL operations. The SQLJ translator is conceptually similar to other Oracle precompilers and enables you to check SQL syntax, verify SQL operations against what is available in the

Introduction to SQLJ

2-1

Overview of SQLJ Components

schema, and check the compatibility of Java types with corresponding database types. In this way, you can catch errors during development rather than a user catching the errors at run time. The translator checks the following: ■ ■

Syntax of the embedded SQL statements SQL constructs, against a specified database schema to ensure consistency within a particular set of SQL entities (optional) For example, it verifies table names and column names.



Data types, to ensure that the data exchanged between Java and SQL have compatible types and proper type conversions

The SQLJ methodology of embedding SQL statements directly in Java code is very convenient and concise in a way that it reduces development and maintenance costs in Java programs that require database connectivity. Java programs can call PL/SQL stored procedures and anonymous blocks through JDBC or SQLJ. In particular, SQLJ provides syntax for calling stored procedures and functions from within a SQLJ statement and also supports embedded PL/SQL anonymous blocks within a SQLJ statement.

Using PL/SQL anonymous blocks within SQLJ statements is one way to support dynamic SQL operations in a SQLJ application. However, the Oracle SQLJ implementation includes extensions to support dynamic SQL directly.

Note:

Overview of SQLJ Components This section introduces the main two major SQLJ components in Oracle SQLJ implementation. It covers the following topics: ■

SQLJ Translator



SQLJ Run Time

SQLJ Translator This component is a precompiler that you run after creating SQLJ source code. The translator, which is written in pure Java, supports a programming syntax that enables you to embed SQL statements in SQLJ executable statements. SQLJ executable statements and SQLJ declarations are preceded by the #sql token and can be interspersed with Java statements in a SQLJ source code file. SQLJ source code file names must have the .sqlj extension. The following is a sample SQLJ statement: #sql { INSERT INTO emp (ename, sal) VALUES (’Joe’, 43000) };

The translator produces a .java file. You can invoke the translator using the sqlj command-line utility. On the command line, specify the files that need to be translated and any desired SQLJ option settings. See Also:

Chapter 8, "Translator Command Line and Options"

SQLJ Run Time This component is also written in pure Java and is invoked automatically each time you run a SQLJ application. 2-2 Oracle Database SQLJ Developer’s Guide and Reference

Overview of Oracle Extensions to the SQLJ Standard

Oracle JDBC calls are generated directly into the translated code and the SQLJ run time plays a much smaller role. See Also:

"SQLJ Run Time" on page 9-11

From Oracle Database 10g release 1 (10.1), only Oracle JDBC drivers are supported with SQLJ.

Note:

Overview of Oracle Extensions to the SQLJ Standard The Oracle SQLJ implementation supports the ISO SQLJ specification. Because the ISO SQLJ standard is a superset of the American National Standards Institute (ANSI) SQLJ standard, using its features requires a Java Development Kit (JDK) 1.5.x or later environment that complies with Java2 Platform, Enterprise Edition (J2EE). The SQLJ translator accepts a broader range of SQL syntax than the ANSI SQLJ standard specifies. Note:

Oracle SQLJ implementation is supported only with JDK

1.5.x. The ANSI standard addresses not only the SQL92 dialect of SQL, but also enables extension beyond that. The Oracle SQLJ implementation supports the Oracle SQL dialect, which is a superset of SQL92. If you need to create SQLJ programs that work with other databases, then avoid using SQL syntax and SQL types that are not in the standard and, therefore, may not be supported in other environments. This section covers the following topics: ■

SQLJ Type Extensions



SQLJ Functionality Extensions See Also: Chapter 5, "Type Support", and Chapter 6, "Objects, Collections, and OPAQUE Types" for information about SQLJ extensions provided by Oracle Database

SQLJ Type Extensions The Oracle SQLJ implementation supports the following Java types as extensions to the SQLJ standard: ■

Instances of oracle.sql.* classes as wrappers for SQL data. See Also: "Support for JDBC 2.0 LOB Types and Oracle Type Extensions" on page 5-20



Custom Java classes, typically produced by the JPublisher utility to correspond to SQL objects, object references, and collections. For example, classes that implement the oracle.sql.ORAData interface or the JDBC standard java.sql.SQLdata interface. Note: The SQLData interface is standard. Classes that implement it are supported by JDBC drivers and databases of other vendors.

Introduction to SQLJ

2-3

Overview of Oracle Extensions to the SQLJ Standard

See Also: ■

Stream instances: BinaryStream and CharacterStream, the latter of which replaces the deprecated AsciiStream and UnicodeStream, used as output parameters. See Also:



"Custom Java Classes" on page 6-4

"Support for Streams" on page 5-8

Iterator and result set instances as input or output parameters. The SQLJ standard specifies them only in result expressions or cast statements. See Also: "Using Iterators and Result Sets as Host Variables" on page 4-37 and "Using Iterators and Result Sets as Stored Function Returns" on page 4-45



Unicode character types: NString, NCHAR, NCLOB, and NcharCharacterStream, the latter of which replaces the deprecated NcharAsciiStream and NcharUnicodeStream. See Also:

"SQLJ Extended Globalization Support" on page 9-18

Using any of these extensions requires Oracle-specific code generation or Oracle customization during translation, as well as Oracle SQLJ run time and an Oracle JDBC driver when your application runs. Do not use these or other types if you want to use your code in other environments. To ensure that your application is portable, use the SQLJ -warn=portable flag. See Also:

See "Translator Command Line and Options" on page 8-1

SQLJ Functionality Extensions The Oracle SQLJ implementation also supports the following extended functionality: ■

Oracle-specific code generation This generates JDBC code directly. Much of the SQLJ run time functionality is bypassed during program execution. See Also: "Oracle-Specific Code Generation (No Profiles)" on page 3-28



Dynamic SQL in SQLJ statements See Also:



Scrollable result set iterators with additional navigation methods, and FETCH syntax from result set iterators and scrollable result set iterators See Also:



"Support for Dynamic SQL" on page 7-50

"Scrollable Iterators" on page 7-36

Optimization flags for column and parameter size definitions See Also: "Column Definitions" on page 10-16, "Parameter Size Definitions" on page 10-17, and "Options for Code Generation, Optimizations, and CHAR Comparisons" on page 8-40

2-4 Oracle Database SQLJ Developer’s Guide and Reference

Basic Translation Steps and Run-Time Processing



Flags for modified translator behavior, such as for binding host expressions by identifier or accounting for blank padding in CHAR comparisons for WHERE clauses See Also: "Binding Host Expressions by Identifier (-bind-by-identifier)" on page 8-55 and "CHAR Comparisons with Blank Padding (-fixedchar)" on page 8-46



SQLJ statement caching on connection contexts See Also:

"Statement Caching" on page 10-3

Basic Translation Steps and Run-Time Processing SQLJ source code contains a mixture of standard Java source together with SQLJ class declarations and SQLJ executable statements containing embedded SQL statements. SQLJ source files have the .sqlj file name extension. The file name must be a legal Java identifier. If the source file declares a public class, then the file name must match the name of this class. If the source file does not declare a public class, then the file name should match the name of the first defined class. This section covers the following topics: ■

SQLJ Translation Steps



Summary of Translator Input and Output



SQLJ Run-Time Processing

SQLJ Translation Steps After you have written your .sqlj file, you must run SQLJ to process the files. The following example shows SQLJ being run in its simplest form with no command-line options for the Foo.sqlj source file with the public class Foo: % sqlj Foo.sqlj

This command runs a front-end script or utility depending on the platform. The script or utility reads the command line, invokes a Java virtual machine (JVM), and passes arguments to it. The JVM invokes the SQLJ translator and acts as a front end. Figure 2–1 Oracle SQLJ emp.sqlj

emp.java

SQLJ Translator

emp.class

Java Compiler

Checker

DBMS

% sqlj emp.sqlj -user=scott/tiger % java emp

The following sequence of events occurs, presuming each step completes without error:

Introduction to SQLJ

2-5

Basic Translation Steps and Run-Time Processing

1.

The JVM invokes the SQLJ translator.

2.

The translator parses the SQLJ and Java code in the .sqlj file, checking for proper SQLJ syntax and looking for type mismatches between the declared SQL data types and corresponding Java host variables. Host variables are Java local variables that are used as input or output parameters in SQL operations. See Also:

3.

"Java Host, Context, and Result Expressions" on page 4-12

Depending on the SQLJ option settings, the translator invokes the online semantics-checker, the offline parser, neither, or both. This is to verify syntax of embedded SQL and PL/SQL statements and to check the use of database elements in the code against an appropriate database schema, for online checking. Even when neither is specified, some basic level of checking is performed. When online checking is specified, SQLJ will connect to a specified database schema to verify that the database supports all the database tables, stored procedures, and SQL syntax that the application uses. It also verifies that the host variable types in the SQLJ application are compatible with data types of corresponding database columns.

4.

For Oracle-specific SQLJ code generation (-codegen=oracle, which is default), SQL operations are converted directly into Oracle JDBC calls. See Also: "Oracle-Specific Code Generation (No Profiles)" on page 3-28

Generated Java code is put into a .java output file containing the following: ■ ■

Any class definitions and Java code from the .sqlj source file Class definitions created as a result of the SQLJ iterator and connection context declarations See Also:



"Overview of SQLJ Declarations" on page 4-1

Calls to Oracle JDBC drivers to implement the actions of the embedded SQL operations

5.

The JVM invokes the Java compiler, which is usually, but not necessarily, the standard javac provided with the Sun Microsystems JDK.

6.

The compiler compiles the Java source file generated in Step 4 and produces Java .class files as appropriate. This will include a .class file for each class that is defined, each of the SQLJ declarations. See Also:

"Internal Translator Operations" on page 9-1

General SQLJ Notes Consider the following when translating and running SQLJ applications: ■

It is also possible to specify existing .java files on the command line to be compiled and to be available for type resolution as well. See Also: "Translator Command Line and Properties Files" on page 8-1



Your application requires an Oracle JDBC driver when it runs, even if your code does not use Oracle-specific features.

2-6 Oracle Database SQLJ Developer’s Guide and Reference

Basic Translation Steps and Run-Time Processing

Summary of Translator Input and Output This section summarizes what the SQLJ translator takes as input, what it produces as output, and where it places its output. This section covers the following topics: ■

Translator Input



Translator Output



Output File Locations This discussion mentions iterator class and connection context class declarations. Iterators are similar to JDBC result sets and connection contexts are used for database connections.

Note:

Translator Input The SQLJ translator takes one or more .sqlj source files as input, which can be specified on the command line. The name of the main .sqlj file is based on the public class it defines, if any, else on the first class it defines. If the main .sqlj file defines the MyClass class, then the source file name must be: MyClass.sqlj

This must also be the file name if there are no public class definitions, but MyClass is the first class defined. You must define each public class in separate.sqlj files. When you run SQLJ, you can also specify numerous SQLJ options on the command line or in the properties files. See Also:

"Translator Command Line and Properties Files" on

page 8-1

Translator Output The translation step produces a Java source file for each .sqlj file in the application, presuming the source code uses SQLJ executable statements. SQLJ generates Java source files as follows: ■

Java source files are .java files with the same base names as the .sqlj files. For example, the translator produces MyClass.java corresponding to MyClass.sqlj, which defines the MyClass class. The output .java file also contains class definitions for any iterators or connection context classes declared in the .sqlj file.

The compilation step compiles the Java source file into multiple class files. One .class file is generated for each class defined in the .sqlj source file. Additional .class files are produced if you declared any SQLJ iterators or connection contexts. Also, separate .class files will be produced for any inner classes or anonymous classes in the code. See Also:

"Overview of SQLJ Declarations" on page 4-1

The .class files are named as follows: ■

The class file for each class defined consists of the name of the class with the .class extension. For example, the translator output file MyClass.java is compiled into the MyClass.class class file.

Introduction to SQLJ

2-7

SQLJ Sample Code



The translator names iterator classes and connection context classes according to how you declare them. For example, if you declare an iterator MyIter, then the compiler will generate a corresponding MyIter.class class file.

Output File Locations By default, SQLJ places the generated .java files in the same directory as the .sqlj file. You can specify a different .java file location using the SQLJ -dir option. By default, SQLJ places the generated .class and .ser files in the same directory as the generated .java files. You can specify a different location for .class and .ser files using the SQLJ -d option. This option setting is passed to the Java compiler so that .class files and .ser files will be in the same location. For both the -d and -dir option, you must specify a directory that already exists. See Also:

"Options for Output Files and Directories" on page 8-21

SQLJ Run-Time Processing This section discusses run-time processing during program execution. When you translate with the default -codegen=oracle setting, your program performs the following at run time: ■



Executes Oracle-specific application programming interfaces (APIs) that ensure batching support and proper creation and closing of Oracle JDBC statements Directly calls Oracle JDBC APIs for registering, passing, and retrieving parameters and result sets See Also: "Oracle-Specific Code Generation (No Profiles)" on page 3-28

SQLJ Sample Code This section presents a side-by-side comparison of two versions of the same sample code, where one version is written in SQLJ and the other in JDBC. The objective of this section is to point out the differences in coding requirements between SQLJ and JDBC. This section covers: ■

SQLJ Version of the Sample Code



JDBC Version of the Sample Code The particulars of SQLJ statements and features used here are described later in this manual, but this example is still useful here to give you a general idea in comparing and contrasting SQLJ and JDBC. You can look at it again when you are more familiar with SQLJ concepts and features.

Note:

In the sample, two methods are defined: getEmployeeAddress(), which selects and returns an employee’s address from a table based on the employee’s number, and updateAddress(), which takes the retrieved address, calls a stored procedure, and returns the updated address to the database. In both versions of the sample code, the following assumptions are made:

2-8 Oracle Database SQLJ Developer’s Guide and Reference

SQLJ Sample Code







■ ■

A SQL script has been run to create the schema in the database and populate the tables. Both versions of the sample code refer to objects and tables created by this script. The UPDATE_ADDRESS() PL/SQL stored function exists, and it updates a given address. The Connection object (for JDBC) and default connection context (for SQLJ) have been created previously by the caller. Exceptions are handled by the caller. The value of the address argument, addr, passed to the updateAddress() method can be null. The JDBC and SQLJ versions of the sample code are only partial samples and cannot run independently. There is no main() method in either.

Note:

SQLJ Version of the Sample Code The SQLJ version of the sample code that defines methods to retrieve an employee’s address from the database, update the address, and return it to the database is as follows: import java.sql.*; /** This is what you have to do in SQLJ **/ public class SimpleDemoSQLJ { //TO DO: make a main that calls this public Address getEmployeeAddress(int empno) throws SQLException { Address addr; #sql { SELECT office_addr INTO :addr FROM employees WHERE empnumber = :empno }; return addr; }

// line 6

// line 10

// line 13

// line 18 public Address updateAddress(Address addr) throws SQLException { #sql addr = { VALUES(UPDATE_ADDRESS(:addr)) }; return addr; }

// line 22

}

Line 10 The getEmployeeAddress() method does not require an explicit Connection object. SQLJ can use a default connection context instance, which should be initialized somewhere earlier in the application.

Introduction to SQLJ

2-9

SQLJ Sample Code

Lines 13-15 The getEmployeeAddress() method retrieves an employee address according to the employee number. Use standard SQLJ SELECT INTO syntax to select an employee's address from the employee table if the employee number matches the one (empno) passed in to getEmployeeAddress(). This requires a declaration of the Address object (addr) that will receive the data. The empno and addr variables are used as input host variables. Line 16 The getEmployeeAddress() method returns the addr object. Line 19 The updateAddress() method also uses the default connection context instance. Lines 19-22 The address is passed to the updateAddress() method, which passes it to the database. The database updates the address and passes it back. The actual updating of the address is performed by the UPDATE_ADDRESS() stored function. Use standard SQLJ function-call syntax to receive the addr address object returned by UPDATE_ADDRESS(). Line 23 The updateAddress() method returns the addr object. Specific Features of the SQLJ Version of the Code Note the following features of the SQLJ version of the sample code: ■

An explicit connection is not required. SQLJ can use a default connection context that has been initialized previously in the application.



No data type casting is required.



SQLJ does not require knowledge of _SQL_TYPECODE, _SQL_NAME, or factories.



NULL value data is processed implicitly.



No explicit code for resource management (for example, closing statements or results sets) is required.



SQLJ embeds host variables, in contrast to JDBC, which uses parameter markers.



String concatenation for long SQL statements is not required.



You do not have to register output parameters.





SQLJ syntax is simpler. For example, SELECT INTO statements are supported and ODBC-style escapes are not used. You do not have to implement your own statement cache. By default, SQLJ will automatically cache #sql statements. This results in improved performance, for example, if you repeatedly call getEmployeeAddress() and updateAddress().

JDBC Version of the Sample Code If you are familiar with JDBC, then you can check the following the JDBC version of the sample code, which defines methods to retrieve an employee’s address from the database, update the address, and return it to the database.

2-10 Oracle Database SQLJ Developer’s Guide and Reference

Alternative Deployment Scenarios

Note: The TO DO items in the comment lines indicate where you might want to add additional code to increase the usefulness of the code sample. import java.sql.*; import oracle.jdbc.*; /** This is what you have to do in JDBC **/ public class SimpleDemoJDBC {

// line 7

//TO DO: make a main that calls this public Address getEmployeeAddress(int empno, Connection conn) throws SQLException // line { Address addr; PreparedStatement pstmt = // line conn.prepareStatement("SELECT office_addr FROM employees" + " WHERE empnumber = ?"); pstmt.setInt(1, empno); OracleResultSet rs = (OracleResultSet)pstmt.executeQuery(); rs.next(); // line //TO DO: what if false (result set contains no data)? addr = (Address)rs.getORAData(1, Address.getORADataFactory()); //TO DO: what if additional rows? rs.close(); // line pstmt.close(); return addr; // line } public Address updateAddress(Address addr, Connection conn) throws SQLException // line

13

16

21

25 27

30

{ OracleCallableStatement cstmt = (OracleCallableStatement) conn.prepareCall("{ ? = call UPDATE_ADDRESS(?) }"); //line 34 cstmt.registerOutParameter(1, Address._SQL_TYPECODE, Address._SQL_NAME); // line 36 if (addr == null) { cstmt.setNull(2, Address._SQL_TYPECODE, Address._SQL_NAME); } else { cstmt.setORAData(2, addr); } cstmt.executeUpdate(); // line 43 addr = (Address)cstmt.getORAData(1, Address.getORADataFactory()); cstmt.close(); // line 45 return addr; } }

Alternative Deployment Scenarios Although this manual mainly discusses writing for client-side SQLJ applications, you may find it useful to run SQLJ code in the following scenarios:

Introduction to SQLJ 2-11

Alternative Deployment Scenarios



From an applet



In the server (optionally running the SQLJ translator in the server as well)

This section covers the following topics: ■

Running SQLJ in Applets



Overview of SQLJ in the Server

Running SQLJ in Applets Because the SQLJ run time is pure Java, you can use SQLJ source code in applets as well as applications. However, there are a few considerations. Oracle Database JDBC Developer's Guide and Reference for applet issues that apply to Oracle JDBC drivers.

See Also:

This section covers the following topics: ■

General Development and Deployment Considerations



General End User Considerations



Java Environment and the Java Plug-In

General Development and Deployment Considerations The following general considerations apply to the use of SQLJ in applets: ■

You must package all the SQLJ run time packages with your applet. The packages are: sqlj.runtime sqlj.runtime.ref sqlj.runtime.error

Also package the following if you used Oracle customization: oracle.sqlj.runtime oracle.sqlj.runtime.error

These packages are included with your Oracle installation in one of several run time libraries in the ORACLE_HOME/lib directory. See Also: "Requirements for Using the Oracle SQLJ Implementation" on page 1-2 ■



You must specify a pure Java JDBC driver, such as Oracle JDBC Thin driver, for your database connection. You must explicitly specify a connection context instance for each SQLJ executable statement in an applet. This is a requirement because you could conceivably run two SQLJ applets in a single browser and, thus, in the same JVM. See Also:



"Connection Considerations" on page 3-4

The default translator setting -codegen=oracle generates Oracle-specific code. This will eliminate the use of Java reflection at run time and, thus, increase portability across different browser environments.

2-12 Oracle Database SQLJ Developer’s Guide and Reference

Alternative Deployment Scenarios

See Also: "Code Generation (-codegen)" on page 8-41 and "Oracle-Specific Code Generation (No Profiles)" on page 3-28

General End User Considerations When end users run your SQLJ applet, classes in their CLASSPATH may conflict with classes that are downloaded with the applet. Therefore, Oracle recommends that end users clear their CLASSPATH before running the applet.

Java Environment and the Java Plug-In The following are some additional considerations regarding the Java environment and use of Oracle-specific features: ■

SQLJ requires the run-time environment of JDK 1.5. Users cannot run SQLJ applets in browsers using earlier JDK versions, without a plug-in. One option is to use a Java plug-in offered by Sun Microsystems. For information, refer to the following: http://java.sun.com/products/plugin/



Applets using Oracle-specific features require Oracle SQLJ run time to work. Oracle SQLJ run time consists of the classes in the SQLJ run time library file under oracle.sqlj.*. Oracle SQLJ runtime.jar library requires the Java Reflection API, java.lang.reflect.*. Most browsers do not support the Reflection API or impose security restrictions, but the Sun Microsystems Java plug-in provides support for the Reflection API.

The term "Oracle-specific features" refers to the use of Oracle type extensions (discussed in Chapter 5, "Type Support") and the use of SQLJ features that require Oracle-specific code generation or, for ISO code generation, require your application to be customized to work against Oracle Database instance. (For example, this is true of the SET statement, discussed in Chapter 4, "Basic Language Features".)

Note:

The preceding issues can be summarized as follows, focusing on users with Internet Explorer and Netscape browsers: ■

The SQLJ and JDBC versions should match. For example, to use the SQLJ 9.0.0 run time, you must have an Oracle 9.0.0 or earlier JDBC driver. See Also: "Requirements for Using the Oracle SQLJ Implementation" on page 1-2



If you use object types, JDBC 2.0 types, REF CURSORs, or the CAST statement in your SQLJ statements, then you must adhere to your choice of the following: –

Use the default -codegen=oracle setting when you translate your applet.



Ensure that the browser in which you run supports JDK 1.5.x and permits reflection.



Run your applet through a browser Java plug-in.

Overview of SQLJ in the Server In addition to its use in client applications, SQLJ code can run within a target Oracle Database in stored procedures, stored functions, or triggers. Server-side access occurs Introduction to SQLJ 2-13

Alternative Deployment Scenarios

through an Oracle JDBC driver that runs inside the server itself. Additionally, Oracle Database 11g (and preceding versions) has an embedded SQLJ translator so that SQLJ source files for server-side use can optionally be translated directly in the server. The two main areas to consider are the following: ■

Creating SQLJ code for use within the server Coding a SQLJ application for use within the target Oracle Database is similar to coding for client-side use. The issues that exist are due to general JDBC characteristics, as opposed to SQLJ-specific characteristics. The main differences involve connections: –

You have only one connection.



The connection is to the database in which the code is running.



The connection is implicit (does not have to be explicitly initialized, unlike on a client).



The connection cannot be closed. Any attempt to close it will be ignored.

Additionally, the JDBC server-side driver used for connections within the server does not support auto-commit mode. There is also a server-side Thin driver for connecting to one server from code that runs in another. This case is effectively the same as using a Thin driver from a client and is coded in the same way. Refer "Overview of Oracle JDBC Drivers" on page 3-1 for further information. Note:



Translating and loading SQLJ code for server-side use You can translate and compile your code either on a client or in the server. If you do this on a client, then you can load the class and resource files into the server from your client, either by pushing them from the client using the Oracle loadjava utility or pulling them in from the server using SQL commands. Alternatively, you can translate and load in one step using the embedded server-side SQLJ translator. If you load a SQLJ source file instead of class or resource files, then translation and compilation are done automatically. In general, loadjava or SQL commands can be used for class and resource files or for source files. From a user perspective, .sqlj files are treated the same as .java files, with translation taking place implicitly. "Loading SQLJ Source Code into the Server" on page 11-11 for information about using the embedded server-side translator

See Also:

The server-side translator does not support the SQLJ -codegen option and generates Oracle-specific code. To use ISO standard code in the server, you must translate on a client and load the individual components into the server. Also note restrictions on interoperability when running code generated with different settings. For more information, refer to "Translating SQLJ Source on a Client and Loading Components" on page 11-5 and "Oracle-Specific Code Generation (No Profiles)" on page 3-28.

Note:

2-14 Oracle Database SQLJ Developer’s Guide and Reference

Alternative Development Scenarios

Alternative Development Scenarios The discussion in this book assumes that you are coding manually on a UNIX environment for English-language deployment. However, you can use SQLJ on other platforms and with integrated development environments (IDEs). There is also globalization support for deployment to other languages. This section covers the following topics: ■

SQLJ Globalization Support



SQLJ in Oracle JDeveloper 10g and Other IDEs



Windows Considerations

SQLJ Globalization Support Support for native languages and character encodings by the Oracle SQLJ implementation is based on Java built-in globalization support capabilities. The standard user.language and file.encoding properties of the JVM determine appropriate language and encoding for translator and run-time messages. The SQLJ -encoding option determines encoding for interpreting and generating source files during translation. See Also: "Globalization Support in the Translator and Run Time" on page 9-13

SQLJ in Oracle JDeveloper 10g and Other IDEs The Oracle SQLJ implementation includes a programmatic API so that it can be embedded in IDEs, such as Oracle JDeveloper 10g. The IDE takes on a role similar to that of the front-end sqlj script, invoking the translator, semantics-checker, compiler, and customizer (as applicable). JDeveloper is a Windows-based visual development environment for Java programming. The JDeveloper Suite enables developers to build multitier, scalable Internet applications using Java across the Oracle Internet Platform. The core product of the suite, the JDeveloper IDE, excels in creating, debugging, and deploying component-based applications. Oracle JDBC OCI and Thin drivers are included with JDeveloper. The compilation functionality of JDeveloper includes an integrated SQLJ translator so that your SQLJ application is translated automatically as it is compiled. Information about JDeveloper is available at the following URL: http://www.oracle.com/technology/products/jdev/index.html

Windows Considerations Note the following if you are using a Microsoft Windows environment instead of a UNIX environment: ■



This manual uses UNIX syntax. Use platform-specific file names and directory separators, such as "\" on Microsoft Windows, that are appropriate for your platform, because your JVM expects file names and paths in the platform-specific format. This is true even if you are using a shell, such as ksh, that permits a different file name syntax. For UNIX, the Oracle SQLJ implementation provides a front-end script, sqlj, that you use to invoke the SQLJ translator. On Microsoft Windows, Oracle instead Introduction to SQLJ 2-15

Alternative Development Scenarios

provides an executable file, sqlj.exe. Using a script is not feasible on Microsoft Windows because .bat files on these platforms do not support embedded equals signs (=) in arguments, string operations on arguments, or wildcard characters in file name arguments. ■



How to set environment variables is specific to the operating system. There may also be OS-specific restrictions. In Windows 95, use the Environment tab in the System control panel. Additionally, because Windows 95 does not support the "=" character in variable settings, SQLJ supports the use of "#" instead of "=" in setting SQLJ_OPTIONS, an environment variable that SQLJ can use for option settings. Consult your operating system documentation regarding settings and syntax for environment variables, and be aware of any size limitations. As with any operating system and environment you use, be aware of specific limitations. In particular, the complete, expanded SQLJ command line must not exceed the maximum command-line size, which is 250 characters for Windows 95 and 4000 characters for Windows NT. Consult your operating system documentation.

Refer to the release notes for Windows for additional information.

2-16 Oracle Database SQLJ Developer’s Guide and Reference

3 Key Programming Considerations This chapter discusses key issues to consider before developing and running your SQLJ application, and also provides a summary and sample applications. The following topics are discussed: ■

Selection of the JDBC Driver



Connection Considerations



NULL-Handling



Exception-Handling Basics



Basic Transaction Control



Summary: First Steps in SQLJ Code



Oracle-Specific Code Generation (No Profiles)



ISO Standard Code Generation



Requirements and Restrictions for Naming



Considerations for SQLJ in the Middle Tier

Selection of the JDBC Driver You must consider which Java Database Connectivity (JDBC) driver will be appropriate for your situation and whether it may be advantageous to use different drivers for translation and run time. You must choose or register the appropriate driver class for each and then specify the driver in your connection URL. Your application will require an Oracle JDBC driver if you use Oracle-specific code generation or if you use ISO code generation with Oracle customizer, even if your code does not actually use Oracle-specific features.

Note:

This section covers the following topics: ■

Overview of Oracle JDBC Drivers



Driver Selection for Translation



Driver Selection and Registration for Run Time

Overview of Oracle JDBC Drivers Oracle provides the following JDBC drivers: Key Programming Considerations

3-1

Selection of the JDBC Driver









Oracle Call Interface (OCI) driver: For client-side use with an Oracle client installation. Thin driver: A pure Java driver for client-side use, particularly with applets. It does not require an Oracle client installation. Server-side Thin driver: Is functionally the same as the client-side Thin driver, but is for code that runs inside Oracle Database instance and needs to access a remote server. Server-side internal driver: For code that runs inside the target server, that is, inside Oracle Database instance that it must access.

Oracle Database 11g provides client-side drivers compatible with Java Development Kit (JDK) 1.5. See Also:

Oracle Database JDBC Developer's Guide and Reference

Remember that your choices may differ between translation time and run time. For example, you may want to use Oracle JDBC OCI driver at translation time for semantics-checking, but Oracle JDBC Thin driver at run time.

Note:

Core JDBC Functionality The core functionality of all Oracle JDBC drivers is the same. They support the same feature set, syntax, programming interfaces, and Oracle extensions. All Oracle JDBC drivers are supported by the oracle.jdbc.OracleDriver class. JDBC OCI Driver Oracle JDBC OCI driver accesses the database by calling the OCI directly from Java, providing the highest compatibility with the different Oracle Database versions. These drivers support installed Oracle Net adapters, including interprocess communication (IPC), named pipes, TCP/IP, and IPX/SPX. The use of native methods to call C entry points makes the OCI driver dependent on the Oracle platform, requiring an Oracle client installation that includes Oracle Net. Therefore it is not suitable for applets. Connection strings for the OCI driver are of the following form, where tns is an optional TNS alias or full TNS specification: jdbc:oracle:oci:@

Note: For backward compatibility, oci8 is still acceptable instead of oci.

JDBC Thin Driver Oracle JDBC Thin driver is a platform-independent, pure Java implementation that uses Java sockets to connect directly to Oracle Database from any Oracle or non-Oracle client. It can be downloaded into a browser simultaneously with the Java applet being run. The JDBC Thin driver supports only TCP/IP protocol and requires a TNS listener to be listening on TCP/IP sockets from the database server. When the JDBC Thin driver is

3-2 Oracle Database SQLJ Developer’s Guide and Reference

Selection of the JDBC Driver

used with an applet, the client browser must have the capability to support Java sockets. Connection strings for the JDBC Thin driver are typically of the following form: jdbc:oracle:thin:@host:port/servicename

Oracle Database JDBC Developer's Guide and Reference for information about database service names

See Also:

In Oracle Database 11g, connection strings using SIDs are deprecated, but are still supported for backward compatibility: jdbc:oracle:thin:@host:port:sid

JDBC Server-Side Thin Driver Oracle JDBC server-side Thin driver offers the same functionality as the client-side JDBC Thin driver, but runs inside the database and accesses a remote server. This is useful in accessing one Oracle Database instance from inside another, such as from a Java stored procedure. Connection strings for the server-side Thin driver are the same as for the client-side Thin driver. In order to leave the originating database when using the server-side Thin driver, the user account must have SocketPermission assigned. Refer to the Oracle Database JDBC Developer's Guide and Reference for more information. Also, refer to the Oracle Database Java Developer's Guide for general information about SocketPermission and other permissions.

Note:

JDBC Server-Side Internal Driver Oracle JDBC server-side internal driver provides support for any Java code that runs inside the target Oracle Database instance where the SQL operations are to be performed. The server-side internal driver enables Oracle Java virtual machine (JVM) to communicate directly with the SQL engine. This driver is the default JDBC driver for SQLJ code running as a stored procedure, stored function, or trigger in Oracle Database 11g. Connection strings for the server-side internal driver are of the following form: jdbc:oracle:kprb:

If your SQLJ code uses the default connection context, then SQLJ automatically uses this driver for code running in Oracle JVM.

Driver Selection for Translation Use SQLJ option settings, either on the command line or in a properties file, to choose the driver manager class and specify a driver for translation. Use the SQLJ -driver option to choose any driver manager class other than OracleDriver, which is the default. Specify the particular JDBC driver to choose, such as JDBC Thin or JDBC OCI for Oracle Database, as part of the connection URL you specify in the SQLJ -url option.

Key Programming Considerations

3-3

Connection Considerations

See Also:

"Connection Options" on page 8-25

You will typically, but not necessarily, use the same driver that you use in your source code for the run time connection. Remember that the -driver option does not choose a particular driver. It registers a driver class with the driver manager. One driver class might be used for multiple driver protocols, such as OracleDriver, which is used for all of Oracle JDBC protocols.

Note:

Driver Selection and Registration for Run Time To connect to the database at run time, you must register one or more drivers that will understand the URLs you specify for any of your connection instances, whether they are instances of the sqlj.runtime.ref.DefaultContext class or of any connection context classes that you declare. If you are using an Oracle JDBC driver and create a default connection using the Oracle.connect() method, then SQLJ handles this automatically. The Oracle.connect() method registers the oracle.jdbc.OracleDriver class. If you are using an Oracle JDBC driver, but do not use Oracle.connect(), then you must manually register the OracleDriver class, as follows: DriverManager.registerDriver(new oracle.jdbc.OracleDriver());

If you are not using an Oracle JDBC driver, then you must register some appropriate driver class, as follows: DriverManager.registerDriver(new mydriver.jdbc.driver.MyDriver());

In any case, you must also set your connection URL, user name, and password. See Also: "Single Connection or Multiple Connections Using DefaultContext" on page 3-5

As an alternative to using the JDBC driver manager in establishing JDBC connections, you can use data sources. You can specify a data source in a with clause, as described in "Declaration WITH Clause" on page 4-4. For general information about data sources, refer to the Oracle Database JDBC Developer's Guide and Reference. Note:

Connection Considerations When deciding what database connection or connections you will need for your SQLJ application, consider the following: ■ ■



Will you need just one database connection or multiple connections? If using multiple connections (possibly to multiple schemas), then will each connection use SQL entities of the same name: tables of the same name, columns of the same name and data types, stored procedures of the same name and signature, and so on? Will you need different connections for translation and run time or will the same suffice for both?

3-4 Oracle Database SQLJ Developer’s Guide and Reference

Connection Considerations

A SQLJ executable statement can specify a particular connection context instance, either of DefaultContext or of a declared connection context class, for its database connection. Alternatively, it can omit the connection context specification and use the default connection, which is an instance of DefaultContext that was previously set as the default. If your operations will use different sets of SQL entities, then you will typically want to declare and use additional connection context classes.

Note:

This section covers the following topics: ■

Single Connection or Multiple Connections Using DefaultContext



Closing Connections



Multiple Connections Using Declared Connection Context Classes



More About the Oracle Class



More About the DefaultContext Class



Connection for Translation



Connection for Customization

Single Connection or Multiple Connections Using DefaultContext This section discusses scenarios where you will use connection instances of only the DefaultContext class. This is typical if you are using a single connection, or multiple connections that use SQL entities with the same names and data types. Single Connection For a single connection, use one instance of the DefaultContext class specifying the database URL, user name, and password, when you construct your DefaultContext object. You can use the connect() method of the oracle.sqlj.runtime.Oracle class to accomplish this. Calling this method automatically initializes the default connection context instance. This method has several signatures, including ones that allow you to specify user name, password, and URL, either directly or using a properties file. In the following example, the properties file connect.properties is used: Oracle.connect(MyClass.class, "connect.properties");

Note: The connect.properties file is searched for relative to the specified class. In the example, if MyClass is located in my-package, then connect.properties must be found in the same package location, my-package.

If you use connect.properties, then you must edit it appropriately and package it with your application. In this example, you must also import the oracle.sqlj.runtime.Oracle class. Alternatively, you can specify user name, password, and URL directly:

Key Programming Considerations

3-5

Connection Considerations

Oracle.connect("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger");

In this example, the connection will use the JDBC Thin driver to connect the scott user with the password, tiger, to a database on the computer, localhost, through port 1521, where myservice is the name of the database service for the connection. Either of these examples creates a special static instance of the DefaultContext class and installs it as your default connection. It is not necessary to do anything with this DefaultContext instance directly. Once you have completed these steps, you do not need to specify the connection for any of the SQLJ executable statements in your application, if you want them all to use the default connection. Note that in using a JDBC Thin driver, the URL must include the host name, port number, and service name (or SID, which is deprecated in Oracle Database 11g), as in the preceding example. Also, the database must have a listener running at the specified port. In using the JDBC OCI driver, no service name (or SID) is required if you intend to use the default account of the client, as will be the case in examples in this document. Alternatively, you can use name-value pairs. Oracle Database JDBC Developer's Guide and Reference for more information

See Also:

The following URL will connect to the default account of the client: jdbc:oracle:oci:@

Note: ■







Oracle.connect() will not set your default connection if one had already been set. In that case, it returns null. This enables you to use the same code on a client or in the server. If you do want to override your default connection, then use the static setDefaultContext() method of DefaultContext. The Oracle.connect() method defaults to a false setting of the auto-commit flag. However, it also has signatures to set it explicitly. In the Oracle JDBC implementation, the auto-commit flag defaults to true. You can optionally specify getClass() instead of MyClass.class in the Oracle.connect() call, as long as you are not calling getClass() from a static method. The getClass() method is used in some of the SQLJ demo applications. You can access the static DefaultContext instance, which corresponds to your default connection, as follows: DefaultContext.getDefaultContext();

Multiple Connections For multiple connections, you can create and use additional instances of the DefaultContext class, while optionally still using the default connection.

3-6 Oracle Database SQLJ Developer’s Guide and Reference

Connection Considerations

You can use the Oracle.getConnection() method to instantiate DefaultContext, as in the following examples. First, consider a case where you want most statements to use the default connection, but other statements to use a different connection. You must create one additional instance of DefaultContext: DefaultContext ctx = Oracle.getConnection ( "jdbc:oracle:thin:@localhost2:1521/myservice2", "bill", "lion");

Note: ctx could also use the scott/tiger schema, if you want to perform multiple sets of operations on the same schema.

When you want to use the default connection, it is not necessary to specify a connection context: #sql { SQL operation };

This is actually a shortcut for the following: #sql [DefaultContext.getDefaultContext()] { SQL operation };

When you want to use the additional connection, specify ctx as the connection: #sql [ctx] { SQL operation };

Next, consider situations where you want to use multiple connections, where each of them is a named DefaultContext instance. This enables you to switch your connection back and forth. The following statements establish multiple connections to the same schema (in case you want to use multiple Oracle Database sessions or transactions, for example). Instantiate the DefaultContext class for each connection you will need: DefaultContext ctx1 = Oracle.getConnection ("jdbc:oracle:thin:@localhost1:1521/myservice1", "scott", "tiger"); DefaultContext ctx2 = Oracle.getConnection ("jdbc:oracle:thin:@localhost1:1521/myservice1", "scott", "tiger");

This creates two connection context instances that would use the same schema, connecting to scott/tiger using service myservice1 on the computer localhost1, using Oracle JDBC Thin driver. Now, consider a case where you would want multiple connections to different schemas. Again, instantiate the DefaultContext class for each connection you will need: DefaultContext ctx1 = Oracle.getConnection ("jdbc:oracle:thin:@localhost1:1521/myservice1", "scott", "tiger"); DefaultContext ctx2 = Oracle.getConnection ("jdbc:oracle:thin:@localhost2:1521/myservice2", "bill", "lion");

This creates two connection context instances that use Oracle JDBC Thin driver but use different schemas. The ctx1 object connects to scott/tiger using service myservice1 on the computer localhost1, while the ctx2 object connects to bill/lion using service myservice2 on the computer localhost2. There are two ways to switch back and forth between these connections for the SQLJ executable statements in your application:

Key Programming Considerations

3-7

Connection Considerations



If you switch back and forth frequently, then you can specify the connection for each statement in your application: #sql [ctx1] { SQL operation }; ... #sql [ctx2] { SQL operation };

Include the square brackets around the connection context instance name; they are part of the syntax.

Note:



If you use either of the connections several times in a row within your code flow, then you can periodically use the static setDefaultContext() method of the DefaultContext class to reset the default connection. This method initializes the default connection context instance. This way, you can avoid specifying connections in your SQLJ statements. DefaultContext.setDefaultContext(ctx1); #sql { SQL operation }; // These three statements all use ctx1 #sql { SQL operation }; #sql { SQL operation }; ... DefaultContext.setDefaultContext(ctx2); #sql { SQL operation }; // These three statements all use ctx2 #sql { SQL operation }; #sql { SQL operation };

Because the preceding statements do not specify connection contexts, at translation time they will all be checked against the default connection context.

Note:

Closing Connections It is advisable to close your connection context instances when you are done, preferably in a finally clause of a try block (in case your application terminates with an exception). The DefaultContext class, as well as any connection context classes that you declare, includes a close() method. Calling this method closes the SQLJ connection context instance and, by default, also closes the underlying JDBC connection instance and the physical connection. In addition, the oracle.sqlj.runtime.Oracle class has a static close() method to close the default connection only. In the following example, presume ctx is an instance of any connection context class: ... finally { ctx.close(); } ...

Alternatively, if the finally clause is not within a try block in case a SQL exception is encountered: ...

3-8 Oracle Database SQLJ Developer’s Guide and Reference

Connection Considerations

finally { try { ctx.close(); } catch(SQLException ex) {...} } ...

Or, to close the default connection, the Oracle class also provides a close() method: ... finally { Oracle.close(); } ...

Always commit or roll back any pending changes before closing the connection. Whether there would be an implicit COMMIT operation as the connection is closed is not specified in the JDBC standard and may vary from vendor to vendor. For Oracle, there is an implicit COMMIT when a connection is closed, and an implicit ROLLBACK when a connection is garbage-collected without being closed, but it is not advisable to rely on these mechanisms. It is also possible to close a connection context instance without closing the underlying connection (in case the underlying connection is shared). Refer to "Closing Shared Connections" on page 7-47 for more information.

Note:

Multiple Connections Using Declared Connection Context Classes For multiple connections that use different sets of SQL entities, it is advantageous to use connection context declarations to define additional connection context classes. Having a separate connection context class for each set of SQL entities that you use enables SQLJ to do more rigorous semantics-checking of your code. See Also:

"Connection Contexts" on page 7-1

More About the Oracle Class The Oracle SQLJ implementation provides the oracle.sqlj.runtime.Oracle class to simplify the process of creating and using instances of the DefaultContext class. The static connect() method initializes the default connection context instance, instantiating a DefaultContext object and installing it as your default connection. You do not need to assign or use the DefaultContext instance returned by connect(). If you had already established a default connection, then connect() returns null. The static getConnection() method simply instantiates a DefaultContext object and returns it. You can use the returned instance as desired. Both methods register Oracle JDBC driver manager automatically if the oracle.jdbc.OracleDriver class is found in the CLASSPATH. The static close() method closes the default connection. Signatures of the Oracle.connect() and Oracle.getConnection() Methods Both the method have signatures that take the following parameter sets as input:

Key Programming Considerations

3-9

Connection Considerations

■ ■



URL (String), user name (String), password (String) URL (String), user name (String), password (String), auto-commit flag (boolean) URL (String), java.util.Properties object containing properties for the connection



URL (String), java.util.Properties object, auto-commit flag (boolean)



URL (String) fully specifying the connection, including user name and password The following is an example of the format of a URL string specifying user name (scott) and password (tiger) when using Oracle JDBC drivers, in this case the JDBC Thin driver: "jdbc:oracle:thin:scott/tiger@localhost:1521/myservice"

■ ■







URL (String), auto-commit flag (boolean) A java.lang.Class object for the class relative to which the properties file is loaded, name of properties file (String) A java.lang.Class object, name of properties file (String), auto-commit flag (boolean) A java.lang.Class object, name of properties file (String), user name (String), password (String) A java.lang.Class object, name of properties file (String), user name (String), password (String), auto-commit flag (boolean)



JDBC connection object (Connection)



SQLJ connection context object

These last two signatures inherit an existing database connection. When you inherit a connection, you will also inherit the auto-commit setting of that connection. The auto-commit flag specifies whether SQL operations are automatically committed. For the Oracle.connect() and Oracle.getConnection() methods only, the default is false. If that is the setting you want, then you can use one of the signatures that does not take auto-commit as input. However, anytime you use a constructor to create an instance of a connection context class, including DefaultContext, you must specify the auto-commit setting. In the Oracle JDBC implementation, the default for the auto-commit flag is true. See Also: "Basic Transaction Control" on page 3-18 and "Single Connection or Multiple Connections Using DefaultContext" on page 3-5

Optional Oracle.close() Method Parameters In using the Oracle.close() method to close the default connection, you have the option of specifying whether or not to close the underlying physical database connection. By default it is closed. This is relevant if you are sharing this physical connection between multiple connection objects, either SQLJ connection context instances or JDBC connection instances. You can keep the underlying physical connection open as follows: Oracle.close(ConnectionContext.KEEP_CONNECTION);

You can close the underlying physical connection (default behavior) as follows:

3-10 Oracle Database SQLJ Developer’s Guide and Reference

Connection Considerations

Oracle.close(ConnectionContext.CLOSE_CONNECTION);

KEEP_CONNECTION and CLOSE_CONNECTION are static constants of the ConnectionContext interface. See Also:

"Closing Shared Connections" on page 7-47

More About the DefaultContext Class The sqlj.runtime.ref.DefaultContext class provides a complete default implementation of a connection context class. As with classes created using a connection context declaration, the DefaultContext class implements the sqlj.runtime.ConnectionContext interface. The DefaultContext class has the same class definition that would have been generated by the SQLJ translator from the declaration: #sql public context DefaultContext;

DefaultContext Methods The following are the key methods of the DefaultContext class: ■

getConnection() Gets the underlying JDBC connection object. This is useful if you want to have JDBC code in your application, which is one way to use dynamic SQL operations. You can also use the setAutoCommit() method of the underlying JDBC connection object to set the auto-commit flag for the connection.



setDefaultContext() Sets the default connection your application uses. This is a static method and takes a DefaultContext instance as input. SQLJ executable statements that do not specify a connection context instance will use the default connection that you define using this method or the Oracle.connect() method.



getDefaultContext() Returns the DefaultContext instance currently defined as the default connection for your application. This is a static method.



close() Closes the connection context instance.

The getConnection() and close() methods are specified in the sqlj.runtime.ConnectionContext interface. On a client, getDefaultContext() returns null if setDefaultContext() was not previously called. However, if a data source object has been bound under "jdbc/defaultDataSource" in JNDI, then the client will use this data source object as its default connection.

Note:

In the server, getDefaultContext() returns the default connection, which is the connection to the server itself. DefaultContext Constructors It is typical to instantiate DefaultContext using the Oracle.connect() or Oracle.getConnection() method. However, if you want to create an instance Key Programming Considerations 3-11

Connection Considerations

directly, then there are five constructors for DefaultContext. The different input parameter sets for these constructors are: ■

■ ■

URL (String), user name (String), password (String), auto-commit (boolean) URL (String), java.util.Properties object, auto-commit (boolean) URL (String fully specifying connection and including user name and password), auto-commit setting (boolean) The following is an example of the format of a URL specifying user name and password when using Oracle JDBC drivers, in this case the JDBC Thin driver: "jdbc:oracle:thin:scott/tiger@localhost:1521/myservice"



JDBC connection object (Connection)



SQLJ connection context object

The last two signatures inherit an existing database connection. When you inherit a connection, you will also inherit the auto-commit setting of that connection. Following is an example of constructing a DefaultContext instance: DefaultContext defctx = new DefaultContext ("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger", false);

Notes About Connection Context Constructors: You must keep the following in mind when using connection context constructors:

Note: ■









It is important to note that connection context class constructors, unlike the Oracle.connect() method, require an auto-commit setting. To use any of the first three constructors listed, you must first register your JDBC driver. This happens automatically if you are using an Oracle JDBC driver and call Oracle.connect(). Refer to "Driver Selection and Registration for Run Time" on page 3-4. Connection context classes that you declare generally have the same constructor signatures as the DefaultContext class. However, if you declare a connection context class to be associated with a data source, a different set of constructors is provided. Refer to "Standard Data Source Support" on page 7-9 for more information. When using the constructor that takes a JDBC connection object, do not initialize the connection context instance with a null JDBC connection. The auto-commit setting determines whether SQL operations are automatically committed. Refer to "Basic Transaction Control" on page 3-18 for more information.

Optional DefaultContext close() Method Parameters When you close a connection context instance, you have the option of specifying whether or not to close the underlying physical connection. By default it is closed. This is relevant if you are sharing the physical connection between multiple connection 3-12 Oracle Database SQLJ Developer’s Guide and Reference

Connection Considerations

objects, either SQLJ connection context instances or JDBC connection instances. The following examples presume a DefaultContext instance defctx. To keep the underlying physical connection open, use the following: defctx.close(ConnectionContext.KEEP_CONNECTION);

To close the underlying physical connection, which is the default behavior, use the following: defctx.close(ConnectionContext.CLOSE_CONNECTION);

KEEP_CONNECTION and CLOSE_CONNECTION are static constants of the ConnectionContext interface. "Closing Shared Connections" on page 7-47 for more information about using these parameters and about shared connections

See Also:

Connection for Translation If you want to use online semantics-checking during translation, then you must specify a database connection for SQLJ to use. These are referred to as exemplar schemas. See Also:

"Connection Context Concepts" on page 7-2

You can use different connections for translation and run time. In fact, it is often necessary or preferable to do so. It might be necessary if you are not developing the application in the same kind of environment that it will run in. But even if the run time connection is available during translation, it might be preferable to create an account with a narrower set of resources so that your online checking will be tighter. This would be true if your application uses only a small subset of the SQL entities available in the run time connection. Your online checking would be tighter and more meaningful if you create an exemplar schema consisting only of SQL entities that your application actually uses. Use the SQLJ translator connection options, either on the command line or in a properties file, to specify a connection for translation. See Also:

"Connection Options" on page 8-25

Connection for Customization Generally, Oracle customization does not require a database connection. However, the Oracle SQLJ implementation does support customizer connections. This is useful in two circumstances: ■



If you are using Oracle customizer with the optcols option enabled, then a connection is required. This option allows iterator column type and size definitions for performance optimization. If you are using SQLCheckerCustomizer, a specialized customizer that performs semantics-checking on profiles, then a connection is required if you are using an online checker, which is true by default.

For Oracle-specific code generation, the SQLJ translator has an -optcols option with the same functionality. The SQLCheckerCustomizer is invoked through Oracle customizer harness verify option. Use the customizer harness user, password,

Key Programming Considerations 3-13

NULL-Handling

url, and driver options to specify connection parameters for whatever customizer you are using, as appropriate. See Also: ■





"Oracle Customizer Column Definition Option (optcols)" on page A-20. "SQLCheckerCustomizer for Profile Semantics-Checking" on page A-30 "Customizer Harness Options for Connections" on page A-12

NULL-Handling Java primitive types, such as int, double, or float, cannot have null values. You must consider this in choosing your result expression and host expression types. This section covers the following topics: ■

Wrapper Classes for NULL-Handling



Examples of NULL-Handling

Wrapper Classes for NULL-Handling SQLJ consistently enforces retrieving SQL NULL as Java null, in contrast to JDBC, which retrieves NULL as 0 or false for certain data types. Therefore, do not use Java primitive types in SQLJ for output variables in situations where a SQL NULL may be received, because Java primitive types cannot take null values. This pertains to result expressions, output or input-output host expressions, and iterator column types. If the receiving Java type is primitive and an attempt is made to retrieve a SQL NULL, then a sqlj.runtime.SQLNullException is thrown and no assignment is made. To avoid the possibility of NULL being assigned to Java primitives, use the following wrapper classes instead of primitive types: ■

java.lang.Boolean



java.lang.Byte



java.lang.Short



java.lang.Integer



java.lang.Long



java.lang.Double



java.lang.Float

In case you must convert back to a primitive value, each of these wrapper classes has an xxxValue() method. For example, intValue() returns an int value from an Integer object and floatValue() returns a float value from a Float object. For example, presuming intobj is an Integer object: int j = intobj.intValue();

3-14 Oracle Database SQLJ Developer’s Guide and Reference

Exception-Handling Basics

Note: ■



SQLNullException is a subclass of the standard java.sql.SQLException class. Because Java objects can have null values, there is no need for indicator variables in SQLJ, such as those used in other host languages like C, C++, and COBOL.

Examples of NULL-Handling The following examples show the use of the java.lang wrapper classes to handle NULL. Example: Null Input Host Variable In the following example, a Float object is used to pass a null value to the database: int empno = 7499; Float commission = null; #sql { UPDATE emp SET comm = :commission WHERE empno = :empno };

You cannot use the Java primitive type float to accomplish this. Example: Null Iterator Rows In the following example, a Double column type is used in an iterator to allow for the possibility of null data. For each employee in the emp table whose salary is at least $50,000, the employee name (ENAME) and commission (COMM) are selected into the iterator. Then each row is tested to determine if the COMM field is, in fact, null. If so, then it is processed accordingly. #sql iterator EmployeeIter (String ename, Double comm); EmployeeIter ei; #sql ei = { SELECT ename, comm FROM emp WHERE sal >= 50000 }; while (ei.next()) { if (ei.comm() == null) System.out.println(ei.ename() + " is not on commission."); } ei.close(); ...

Note: To execute a WHERE clause comparison against NULL, use the following SQL syntax: ...WHERE :x IS NULL

Exception-Handling Basics This section covers the basics of handling exceptions in SQLJ application, including requirements for error-checking. This section covers the following topics:

Key Programming Considerations 3-15

Exception-Handling Basics



SQLJ and JDBC Exception-Handling Requirements



Processing Exceptions



Using SQLException Subclasses

SQLJ and JDBC Exception-Handling Requirements Because SQLJ executable statements result in JDBC calls through sqlj.runtime, and JDBC requires SQL exceptions to be caught or thrown, SQLJ also requires SQL exceptions to be caught or thrown in any block containing SQLJ executable statements. Your source code will generate errors during compilation if you do not include appropriate exception-handling. Handling SQL exceptions requires the SQLException class, which is included in the standard JDBC java.sql.* package. Example: Exception Handling This example demonstrates the basic exception-handling required in SQLJ applications. The code declares a main method with a try/catch block and another method, which throws SQLException when an exception is encountered. The code is as follows: /* Import SQLExceptions class. The SQLException comes from JDBC. Executable #sql clauses result in calls to JDBC, so methods containing executable #sql clauses must either catch or throw SQLException. */ import java.sql.* ; import oracle.sqlj.runtime.Oracle; // iterator for the select #sql iterator MyIter (String ITEM_NAME); public class TestInstallSQLJ { //Main method public static void main (String args[]) { try { // Set the default connection to the URL, user, and password // specified in your connect.properties file Oracle.connect(TestInstallSQLJ.class, "connect.properties"); TestInstallSQLJ ti = new TestInstallSQLJ(); // This method throws SQLException. Therefore, it ic called within a try block ti.runExample(); } catch (SQLException e) { System.err.println("Error running the example: " + e); } } //End of method main //Method that runs the example void runExample() throws SQLException {

3-16 Oracle Database SQLJ Developer’s Guide and Reference

Exception-Handling Basics

//Issue SQL command to clear the SALES table #sql { DELETE FROM SALES }; #sql { INSERT INTO SALES(ITEM_NAME) VALUES ('Hello, SQLJ!')}; MyIter iter; #sql iter = { SELECT ITEM_NAME FROM SALES }; while (iter.next()) { System.out.println(iter.ITEM_NAME()); } } }

Processing Exceptions This section discusses ways to process and interpret exceptions in your SQLJ application. During run time, exceptions may be raised from any of the following: ■

SQLJ run time



JDBC driver



RDBMS

Printing Error Text The example in the previous section showed how to catch SQL exceptions and output the error messages. Part of that code is as follows: ... try { ... } catch (SQLException e) { System.err.println("Error running the example: " + e); } ...

This will print the error text from the SQLException object. You can also retrieve error information using the getMessage(), getErrorCode(), and getSQLState() methods the SQLException class. Printing the error text, as in this example, prints the error message with some additional text, such as SQLException. Retrieving SQL States and Error Codes The java.sql.SQLException class and subclasses include the getMessage(), getErrorCode(), and getSQLState() methods. Depending on where the exception or error originated and how they are implemented there, the following methods provide additional information: ■

String getMessage() If the error originates in the SQLJ run time or JDBC driver, then this method returns the error message with no prefix. If the error originates in the RDBMS, then it returns the error message prefixed by the ORA number.



int getErrorCode()

Key Programming Considerations 3-17

Basic Transaction Control

If the error originates in the SQLJ run time, then this method returns no meaningful information. If the error originates in the JDBC driver or RDBMS, then it returns the five-digit ORA number as an integer. ■

String getSQLState() If the error originates in the SQLJ run time, then this method returns a string with a five-digit code indicating the SQL state. If the error originates in the JDBC driver, then it returns no meaningful information. If the error originates in the RDBMS, then it returns the five-digit SQL state. Your application should have appropriate code to handle null values returned.

The following example prints the error message and also checks the SQL state: ... try { ... } catch (SQLException e) { System.err.println("Error running the example: " + e); String sqlState = e.getSQLState(); System.err.println("SQL state = " + sqlState); } ...

Using SQLException Subclasses For more specific error-checking, use any available and appropriate subclasses of the java.sql.SQLException class. SQLJ provides the sqlj.runtime.NullException class, which is a subclass of java.sql.SQLException. You can use this exception in situations where a NULL might be returned into a Java primitive variable. For batch-enabled environments, there is also the standard java.sql.BatchUpdateException subclass. Refer to "Error Conditions During Batch Execution" on page 10-16 for further information. When you use a subclass of SQLException, catch the subclass exception before catching SQLException, as in the following example: ... try { ... } catch (SQLNullException ne) { System.err.println("Null value encountered: " + ne); } catch (SQLException e) { System.err.println("Error running the example: " + e); } ...

This is because a subclass exception can also be caught as a SQLException. If you catch SQLException first, then execution will not proceed to the part where you have coded special processing for the subclass exception.

Basic Transaction Control This section discusses how to manage data updates. It covers the following topics: ■

Overview of Transactions



Automatic Commits Versus Manual Commits

3-18 Oracle Database SQLJ Developer’s Guide and Reference

Basic Transaction Control



Specifying Auto-Commit as You Define a Connection



Modifying Auto-Commit in an Existing Connection



Using Manual COMMIT and ROLLBACK



Effect of Commits and Rollbacks on Iterators and Result Sets



Using Savepoints See Also:

"Advanced Transaction Control" on page 7-41

Overview of Transactions A transaction is a sequence of SQL operations that Oracle treats as a single unit. A transaction begins with the first executable SQL statement after any of the following: ■

Connection to the database



COMMIT (committing data updates, either automatically or manually)



ROLLBACK (canceling data updates)

A transaction ends with a COMMIT or ROLLBACK operation. Note: In Oracle Database 11g, all data definition language (DDL) statements, such as CREATE and ALTER, include an implicit COMMIT. This will commit not only the DDL statement, but all the preceding data manipulation language (DML) statements, such as INSERT, DELETE, and UPDATE, that have not yet been committed or rolled back.

Automatic Commits Versus Manual Commits In using SQLJ or JDBC, you can either have your data updates automatically committed or commit them manually. In either case, each COMMIT operation starts a new transaction. You can specify that changes be committed automatically by enabling the auto-commit flag. This can be done either when you define a SQLJ connection or by using the setAutoCommit() method of the underlying JDBC connection object of an existing connection. You can use manual control by disabling the auto-commit flag and using SQLJ COMMIT and ROLLBACK statements. Enabling auto-commit may be more convenient, but gives you less control. For example, you have no option to roll back changes. In addition, some SQLJ or JDBC features are incompatible with auto-commit mode. For example, you must disable the auto-commit flag for update batching or SELECT FOR UPDATE syntax to work properly.

Specifying Auto-Commit as You Define a Connection When you use the Oracle.connect() or Oracle.getConnection() method to create a DefaultContext instance and define a connection, the auto-commit flag is set to false by default. However, there are signatures of these methods that enable you to set this flag explicitly. The auto-commit flag is always the last parameter. The following is an example of instantiating DefaultContext and using the default false setting for auto-commit mode: Oracle.getConnection ("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger");

Key Programming Considerations 3-19

Basic Transaction Control

Alternatively, you can specify a true setting as follows: Oracle.getConnection ("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger", true);

See Also:

"More About the Oracle Class" on page 3-9

If you use a constructor to create a connection context instance, either of DefaultContext or of a declared connection context class, then you must specify the auto-commit setting. Again, it is the last parameter, as in the following example: DefaultContext ctx = new DefaultContext ("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger", false);

See Also:

"More About the DefaultContext Class" on page 3-11

If you have reason to create a JDBC Connection instance directly, then the auto-commit flag is set to true by default if your program runs on a client, or false by default if it runs in the server. You cannot specify an auto-commit setting when you create a JDBC Connection instance directly, but you can use the setAutoCommit() method to alter the setting. Note: Auto-commit functionality is not supported by the JDBC server-side internal driver.

Modifying Auto-Commit in an Existing Connection There is typically no reason to change the auto-commit flag setting for an existing connection, but you can if you desire. You can do this by using the setAutoCommit() method of the underlying JDBC connection object. You can retrieve the underlying JDBC connection object by using the getConnection() method of any SQLJ connection context instance, whether it is an instance of the DefaultContext class or of a connection context class that you declared. You can accomplish these two steps at once, as follows: ctx.getConnection().setAutoCommit(false);

or: ctx.getConnection().setAutoCommit(true);

In these examples, ctx is a SQLJ connection context instance. Do not alter the auto-commit setting in the middle of a transaction.

Note:

Using Manual COMMIT and ROLLBACK If you disable the auto-commit flag, then you must manually commit any data updates. To commit any changes that have been executed since the last COMMIT operation, use the SQLJ COMMIT statement, as follows: #sql { COMMIT };

3-20 Oracle Database SQLJ Developer’s Guide and Reference

Basic Transaction Control

To roll back any changes that have been executed since the last COMMIT operation, use the SQLJ ROLLBACK statement, as follows: #sql { ROLLBACK };

Note: ■







Do not use the COMMIT and ROLLBACK commands when auto-commit is enabled. This will result in unspecified behavior, or even SQL exceptions could be raised. You can also roll back to a specified savepoint. Refer to "Using Savepoints" on page 3-21. All DDL statements in Oracle SQL syntax include an implicit COMMIT operation. There is no special SQLJ functionality in this regard. Such statements follow standard Oracle SQL rules. If auto-commit mode is off and you close a connection context instance from a client application, then any changes since your last COMMIT will be committed, unless you close the connection context instance with KEEP_CONNECTION. Refer to "Closing Shared Connections" on page 7-47 for more information.

Effect of Commits and Rollbacks on Iterators and Result Sets COMMIT and ROLLBACK operations do not affect open result sets and iterators. The result sets and iterators will still be open. Usually, all that is relevant to their content is the state of the database at the time of execution of the SELECT statements that populated them. An exception to this is if you declared an iterator class with sensitivity=SENSITIVE. In this case, changes to the underlying result set may be seen whenever the iterator is scrolled outside of its window size. For more information about scrollable iterators, refer to "Scrollable Iterators" on page 7-36. For more information about the underlying scrollable result sets, refer to the Oracle Database JDBC Developer's Guide and Reference.

Note:

This also applies to UPDATE, INSERT, and DELETE statements that are executed after the SELECT statements. Execution of these statements does not affect the contents of open result sets and iterators. Consider a situation where you SELECT, then UPDATE, and then COMMIT. A nonsensitive result set or iterator populated by the SELECT statement will be unaffected by the UPDATE and COMMIT. As a further example, consider a situation where you UPDATE, then SELECT, and then ROLLBACK. A nonsensitive result set or iterator populated by the SELECT will still contain the updated data, regardless of the subsequent ROLLBACK.

Using Savepoints The JDBC 3.0 specification added support for savepoints. A savepoint is a defined point in a transaction that you can roll back to, if desired, instead of rolling back the

Key Programming Considerations 3-21

Basic Transaction Control

entire transaction. The savepoint is the point in the transaction where the SAVEPOINT statement appears. In Oracle9i Database Release 2 (9.2), SQLJ first included Oracle-specific syntax to support savepoints. In Oracle Database 11g, SQLJ adds support for ISO savepoint syntax. Support for ISO SQLJ Savepoint Syntax In ISO syntax, use a string literal in a SAVEPOINT statement to designate a name for a savepoint. This can be done as follows: #sql { SAVEPOINT savepoint1 };

If you want to roll back changes to that savepoint, then you can refer to the specified name later in a ROLLBACK TO statement, as follows: #sql { ROLLBACK TO savepoint1 };

Use a RELEASE SAVEPOINT statement if you no longer need the savepoint: #sql { RELEASE SAVEPOINT savepoint1 };

Savepoints are saved in the SQLJ execution context, which has methods that parallel the functionality of these three statements. See Also:

"Savepoint Methods" on page 7-29

Because any COMMIT operation ends the transaction, this also releases all savepoints of the transaction. Oracle SQLJ Savepoint Syntax In addition to the ISO syntax, the following Oracle-specific syntax for savepoints is supported. Note that the Oracle syntax uses string host expressions, rather than string literals. You can set a savepoint as follows: #sql { SET SAVEPOINT :savepoint };

The host expression, savepoint in this example, is a variable that specifies the name of the savepoint as a Java String. You can roll back to a savepoint as follows: #sql { ROLLBACK TO :savepoint };

To release a savepoint, use the following SQLJ statement: #sql { RELEASE :savepoint };

Note: Oracle-specific syntax will continue to be supported for backward compatibility. Note the following differences between Oracle syntax and ISO syntax: ■

Oracle syntax takes string variables rather than string literals.



Oracle syntax uses SET SAVEPOINT instead of SAVEPOINT.



Oracle syntax uses RELEASE instead of RELEASE SAVEPOINT.

3-22 Oracle Database SQLJ Developer’s Guide and Reference

Summary: First Steps in SQLJ Code

Summary: First Steps in SQLJ Code The best way to summarize the SQLJ executable statement features and functionality discussed to this point is by examining short but complete programs. This section presents two such examples. The first example, presented one step at a time and then again in its entirety, uses a SELECT INTO statement to perform a single-row query of two columns from a table of employees. If you want to run the example, ensure that you change the parameters in the connect.properties file to settings that will let you connect to an appropriate database. The second example, slightly more complicated, will make use of a SQLJ iterator for a multi-row query. Import Required Classes Import any JDBC or SQLJ packages you will need. You will need at least some of the classes in the java.sql package: import java.sql.*;

You may not need all the java.sql package. Key classes are java.sql.SQLException and any classes that you refer to explicitly. For example, java.sql.Date and java.sql.ResultSet. You will need the following package for the Oracle class, which you typically use to instantiate DefaultContext objects and establish your default connection: import oracle.sqlj.runtime.*;

If you will be using any SQLJ run time classes directly in your code, then import the following packages: import sqlj.runtime.*; import sqlj.runtime.ref.*;

However, even if your code does not use any SQLJ run time classes directly, it will be sufficient to have them in the CLASSPATH. Key run time classes include ResultSetIterator and ExecutionContext in the sqlj.runtime package and DefaultContext in the sqlj.runtime.ref package. Register JDBC Drivers and Set Default Connection Declare the SimpleExample class with a constructor that uses the static Oracle.connect() method to set the default connection. This also registers Oracle JDBC drivers. This uses a signature of connect() that takes the URL, user name, and password from the connect.properties file. An example of this file is in the directory ORACLE_HOME/sqlj/demo and also in "Set Up the Run Time Connection" on page 1-6. public class SimpleExample { public SimpleExample() throws SQLException { // Set default connection (as defined in connect.properties). Oracle.connect(getClass(), "connect.properties"); }

Key Programming Considerations 3-23

Summary: First Steps in SQLJ Code

Set Up Exception Handling Create a main() that calls the SimpleExample constructor and then sets up a try/catch block to handle any SQL exceptions thrown by the runExample() method, which performs the real work of this application: ... public static void main (String [] args) { try { SimpleExample o1 = new SimpleExample(); o1.runExample(); } catch (SQLException ex) { System.err.println("Error running the example: " + ex); } } ...

You can also use a try/catch block inside a finally clause when you close the connection, presuming the finally clause is not already inside a try/catch block in case of SQL exceptions: finally { try { Oracle.close(); } catch(SQLException ex) {...} }

Set Up Host Variables, Execute SQLJ Clause, Process Results Create a runExample() method that performs the following: 1.

Throws any SQL exceptions to the main() method for processing.

2.

Declares Java host variables.

3.

Executes a SQLJ clause that binds the Java host variables into an embedded SELECT statement and selects the data into the host variables.

4.

Prints the results.

The code for this method is as follows: void runExample() throws SQLException { System.out.println( "Running the example--" ); // Declare two Java host variables-Float salary; String empname; // Use SELECT INTO statement to execute query and retrieve values. #sql { SELECT ename, sal INTO :empname, :salary FROM emp WHERE empno = 7499 }; // Print the results-System.out.println("Name is " + empname + ", and Salary is " + salary); } }

// Closing brace of SimpleExample class

This example declares salary and empname as Java host variables. The SQLJ clause then selects data from the ename and sal columns of the emp table and places the data into the host variables. Finally, the values of salary and empname are printed.

3-24 Oracle Database SQLJ Developer’s Guide and Reference

Summary: First Steps in SQLJ Code

Note that this SELECT statement could select only one row of the emp table, because the empno column in the WHERE clause is the primary key of the table. Example of Single-Row Query using SELECT INTO This section presents the entire SimpleExample class from the previous step-by-step sections. Because this is a single-row query, no iterator is required. // Import SQLJ classes: import sqlj.runtime.*; import sqlj.runtime.ref.*; import oracle.sqlj.runtime.*; // Import standard java.sql package: import java.sql.*; public class SimpleExample { public SimpleExample() throws SQLException { // Set default connection (as defined in connect.properties). Oracle.connect(getClass(), "connect.properties"); } public static void main (String [] args) throws SQLException { try { SimpleExample o1 = new SimpleExample(); o1.runExample(); } catch (SQLException ex) { System.err.println("Error running the example: " + ex); } } finally { try { Oracle.close(); } catch(SQLException ex) {...} } void runExample() throws SQLException { System.out.println( "Running the example--" ); // Declare two Java host variables-Float salary; String empname; // Use SELECT INTO statement to execute query and retrieve values. #sql { SELECT ename, sal INTO :empname, :salary FROM emp WHERE empno = 7499 }; // Print the results-System.out.println("Name is " + empname + ", and Salary is " + salary); } }

Set Up a Named Iterator This example builds on the previous example by adding a named iterator and using it for a multiple-row query.

Key Programming Considerations 3-25

Summary: First Steps in SQLJ Code

First, declare the iterator class. Use object types Integer and Float, instead of primitive types int and float, wherever there is the possibility of NULL values. #sql iterator EmpRecs( int empno, // This column cannot be null, so int is OK. // (If null is possible, use Integer.) String ename, String job, Integer mgr, Date hiredate, Float sal, Float comm, int deptno);

Next, instantiate the EmpRecs class and populate it with query results. EmpRecs employees; #sql employees = { SELECT empno, ename, job, mgr, hiredate, sal, comm, deptno FROM emp };

Then, use the next() method of the iterator to print the results. while (employees.next()) { System.out.println( "Name: System.out.println( "EMPNO: System.out.println( "Job: System.out.println( "Manager: System.out.println( "Date hired: System.out.println( "Salary: System.out.println( "Commission: System.out.println( "Department: System.out.println(); }

" " " " " " " "

+ + + + + + + +

employees.ename() ); employees.empno() ); employees.job() ); employees.mgr() ); employees.hiredate() ); employees.sal() ); employees.comm() ); employees.deptno() );

Finally, close the iterator. employees.close();

Example of Multiple-Row Query Using Named Iterator This example uses a named iterator for a multiple-row query that selects several columns of data from a table of employees. Apart from use of the named iterator, this example is conceptually similar to the previous single-row query example. // Import SQLJ classes: import sqlj.runtime.*; import sqlj.runtime.ref.*; import oracle.sqlj.runtime.*; // Import standard java.sql package: import java.sql.*; // Declare a SQLJ iterator. // Use object types (Integer, Float) for mgr, sal, And comm rather // than primitive types to allow for possible null selection. #sql iterator EmpRecs( int empno, // This column cannot be null, so int is OK. // (If null is possible, Integer is required.) String ename, 3-26 Oracle Database SQLJ Developer’s Guide and Reference

Summary: First Steps in SQLJ Code

String job, Integer mgr, Date hiredate, Float sal, Float comm, int deptno); // This is the application class. public class EmpDemo1App { public EmpDemo1App() throws SQLException { // Set default connection (as defined in connect.properties). Oracle.connect(getClass(), "connect.properties"); } public static void main(String[] args) { try { EmpDemo1App app = new EmpDemo1App(); app.runExample(); } catch( SQLException exception ) { System.err.println( "Error running the example: " + exception ); } } finally { try { Oracle.close(); } catch(SQLException ex) {...} } void runExample() throws SQLException { System.out.println("\nRunning the example.\n" ); // // // //

The query creates a new instance of the iterator and stores it in the variable 'employees' of type 'EmpRecs'. SQLJ translator has automatically declared the iterator so that it has methods for accessing the rows and columns of the result set.

EmpRecs employees; #sql employees = { SELECT empno, ename, job, mgr, hiredate, sal, comm, deptno FROM emp }; // Print the result using the iterator. // Note how the next row is accessed using method 'next()', and how // the columns can be accessed with methods that are named after the // actual database column names. while (employees.next()) { System.out.println( "Name: System.out.println( "EMPNO: System.out.println( "Job: System.out.println( "Manager: System.out.println( "Date hired: System.out.println( "Salary: System.out.println( "Commission: System.out.println( "Department: System.out.println();

" " " " " " " "

+ + + + + + + +

employees.ename() ); employees.empno() ); employees.job() ); employees.mgr() ); employees.hiredate() ); employees.sal() ); employees.comm() ); employees.deptno() );

Key Programming Considerations 3-27

Oracle-Specific Code Generation (No Profiles)

} // You must close the iterator when it’s no longer needed. employees.close() ; } }

Oracle-Specific Code Generation (No Profiles) Throughout this manual there is general and standard discussion of the SQLJ run time layer and SQLJ profiles. However, the Oracle SQLJ implementation, by default, generates Oracle-specific code with direct calls to Oracle JDBC driver instead of generating ISO standard code that calls the SQLJ run time. With Oracle-specific code generation, there are no profile files, and the role of the SQLJ run time layer is greatly reduced during program execution. Oracle-specific code supports all Oracle-specific extended features. Code generation is determined through the SQLJ translator -codegen option. The default setting for Oracle-specific code generation is -codegen=oracle. Alternatively, you can set -codegen=iso for code generation according to the ISO standard. See Also:

"Code Generation (-codegen)" on page 8-41.

This section covers the following topics: ■

Code Considerations and Limitations with Oracle-Specific Code Generation



SQLJ Usage Changes with Oracle-Specific Code Generation



Server-Side Considerations with Oracle-Specific Code Generation



Advantages and Disadvantages of Oracle-Specific Code Generation

Code Considerations and Limitations with Oracle-Specific Code Generation When coding a SQLJ application where Oracle-specific code generation will be used, be aware of the following programming considerations and restrictions: ■



To use a nondefault statement cache size, you must include appropriate method calls in your code, because Oracle customizer stmtcache option is unavailable. Refer to "SQLJ Usage Changes with Oracle-Specific Code Generation" on page 3-30. Do not mix Oracle-specific generated code with ISO standard generated code in the same application. However, if Oracle-specific code and ISO standard code must share the same connection, do one of the following: –

Ensure that the Oracle-specific code and ISO standard code use different SQLJ execution context instances. Refer to "Execution Contexts" on page 7-24 for information about SQLJ execution contexts.



Place a transaction boundary, that is, as a manual COMMIT or ROLLBACK statement, between the two kinds of code.

This limitation regarding mixing code is especially significant for server-side code, because all Java code running in a given session uses the same JDBC connection and SQLJ connection context.

3-28 Oracle Database SQLJ Developer’s Guide and Reference

Oracle-Specific Code Generation (No Profiles)

See Also: "Server-Side Considerations with Oracle-Specific Code Generation" on page 3-31 ■

Do not rely on side effects in parameter expressions when values are returned from the database. Oracle-specific code generation does not create temporary variables for evaluation of OUT parameters, IN OUT parameters, SELECT INTO variables, or return arguments on SQL statements. For example, avoid statements such as the following: #sql { SELECT * FROM EMP INTO :(x[i++]), :(f_with_sideffect()[i++]), :(a.b[i]) };

or: #sql x[i++] = { VALUES f(:INOUT (x[i++]), :OUT (f_with_sideffect())) };

Evaluation of arguments is performed in place in the generated code. This may result in different behavior than when evaluation is according to ISO SQLJ standards. "Evaluation of Java Expressions at Run Time" on page 4-17 and "Examples of Evaluation of Java Expressions at Run Time (ISO Code Generation)" on page 4-18

See Also:



Type maps for Oracle object functionality assumes that the corresponding Java classes implement the java.sql.SQLData interface, given that JPublisher-generated Java classes do not otherwise require a type map. If you use type maps for Oracle object functionality, then your iterator declarations and connection context declarations must specify the same type maps. Specify this through the with clause. For example, if you declare a connection context class as follows: #sql context TypeMapContext with (typeMap="MyTypeMap");

and you populate an iterator instance from a SQLJ statement that uses an instance of this connection context class, as follows: TypeMapContext tmc = new TypeMapContext(...); ... MyIterator it; #sql [tmc] it = ( SELECT pers, addr FROM tab WHERE ...);

then the iterator declaration is required to have specified the same type map, as follows: #sql iterator MyIterator with (typeMap="MyTypeMap") (Person pers, Address addr);

See Also: "Custom Java Class Requirements" on page 6-8 and "Declaration WITH Clause" on page 4-4

Key Programming Considerations 3-29

Oracle-Specific Code Generation (No Profiles)

The reason for this restriction is that with Oracle-specific code generation, all iterator getter methods are fully generated as Oracle JDBC calls during translation. To generate the proper calls, the SQLJ translator must know whether an iterator will be used with a particular type map.

Note:

SQLJ Usage Changes with Oracle-Specific Code Generation Some options that were previously available only as Oracle customizer options are useful with Oracle-specific code generation as well. Because profile customization is not applicable with Oracle-specific code generation, these options have been made available through other means. To alter the statement cache size or disable statement caching when generating Oracle-specific code, use method calls in your code instead of using the customizer stmtcache option. The sqlj.runtime.ref.DefaultContext class, as well as any connection context class you declare, now has the following static methods: ■

setDefaultStmtCacheSize(int)



int getDefaultStmtCacheSize()

It also has the following instance methods: ■

setStmtCacheSize(int)



int getStmtCacheSize()

By default, statement caching is enabled. See Also:

"Statement Caching" on page 10-3

In addition, the following options are available as front-end Oracle SQLJ translator options as well as Oracle customizer options: ■







-optcols: Enable iterator column type and size definitions to optimize performance. -optparams: Enable parameter size definitions to optimize JDBC resource allocation. This option is used in conjunction with optparamdefaults. -optparamdefaults: Set parameter size defaults for particular data types. This option is used in conjunction with optparams. -fixedchar: Enable CHAR comparisons with blank padding for WHERE clauses. See Also: "Options for Code Generation, Optimizations, and CHAR Comparisons" on page 8-40

Be aware of the following: ■



Use the -optcols option only if you are using online semantics-checking, where you have used the SQLJ translator -user, -password, and -url options appropriately to request a database connection during translation. The functionality of the -optcols, -optparams, and -optparamdefaults options, including default values, is the same as for the corresponding customizer options.

3-30 Oracle Database SQLJ Developer’s Guide and Reference

Oracle-Specific Code Generation (No Profiles)

Server-Side Considerations with Oracle-Specific Code Generation Consider the following if your SQLJ code will run in the server: ■

The server-side SQLJ translator no longer supports ISO standard generated code. SQLJ source code that is loaded into the server and compiled there will always be translated with the default -codegen=oracle setting. Therefore, to use ISO standard generated code in the server, you must translate and compile the SQLJ code on a client and then load the individual components into the server. See Also: "Translating SQLJ Source on a Client and Loading Components" on page 11-5



The caution against mixing Oracle-specific generated code with ISO standard generated code applies to server-side Java code that calls a Java stored procedure or stored function, even if the stored procedure is invoked through a PL/SQL wrapper. This constitutes a recursive call-in. By default, the ExecutionContext object is shared by both the calling module and the called module. Therefore, both modules should be translated with the same -codegen setting. If you want to ensure interoperability with code that has been translated with ISO standard code generation, then it is advisable to explicitly instantiate execution context instances, as in the following example: public static method() throws SQLException { Execution Context ec = new ExecutionContext(); ... try { ... #sql [ec] { SQL operation }; ... } finally { ec.close(); } }

To avoid resource leakage when using an explicit ExecutionContext instance, ensure that you use the close() method, as shown in this example. Note:

See Also: "Code Considerations and Limitations with Oracle-Specific Code Generation" on page 3-28

Advantages and Disadvantages of Oracle-Specific Code Generation Oracle-specific code generation offers following advantages over ISO standard code generation: ■



Applications run more efficiently. The code calls JDBC application programming interfaces (APIs) directly, placing run-time performance directly at the JDBC level. The role of the intermediate SQLJ run time layer is greatly reduced during program execution. Applications are smaller in size.

Key Programming Considerations 3-31

ISO Standard Code Generation



■ ■







No profile files (.ser) are produced. This is especially convenient if you are loading a translated application into the database or porting it to another system, because there are fewer components. Translation is faster, because there is no profile customization step. During execution, Oracle SQLJ run time and Oracle JDBC driver use the same statement cache resources, so partitioning resources between the two is unnecessary. Having the SQL-specific information appear in the Java class files instead of in separate profile files avoids potential security issues. You need not have to rewrite your code to take advantage of possible future Oracle JDBC performance enhancements, such as enhancements being considered for execution of static SQL code. Future releases of Oracle SQLJ translator will handle this automatically. The use of Java reflection at run time is eliminated, and thus, provides full portability to browser environments.

However. there are a few disadvantages: ■ ■

Oracle-specific generated code may not be portable to generic JDBC platforms. Profile-specific functionality is not available. For example, you cannot perform customizations at a later date to use Oracle customizer harness -debug, -verify, and -print options. See Also: "Customizer Harness Options for Connections" on page A-12 and "AuditorInstaller Customizer for Debugging" on page A-33

ISO Standard Code Generation This section covers the following topics: ■

Environment Requirements for ISO Standard Code Generation



SQLJ Translator and SQLJ Run Time



SQLJ Profiles



SQLJ Translation Steps



Summary of Translator Input and Output



SQLJ Run-Time Processing



Deployment Scenarios

Environment Requirements for ISO Standard Code Generation The Oracle SQLJ implementation, by default, generates Oracle-specific code with direct calls to Oracle JDBC driver instead of generating ISO standard code that calls the SQLJ run time. The following is a typical environment setup for ISO standard code generation: ■

SQLJ code generation: -codegen=iso



SQLJ translation library: translator.jar



SQLJ run time library: runtime12.jar with JDK 1.5.x and Oracle JDBC driver 11g release 1 (11.1).

3-32 Oracle Database SQLJ Developer’s Guide and Reference

ISO Standard Code Generation



JDBC drivers: Oracle 11g release 1 (11.1)



JDK version: 1.5.x

SQLJ Translator and SQLJ Run Time The following section describes the differences in Oracle SQLJ implementation in case of ISO standard code generation: ■

SQLJ translator: Along with the .java file, the translator also produces one or more SQLJ profiles for ISO standard code generation. These profiles contain information about the embedded SQL operations. SQLJ then automatically invokes a Java compiler to produce .class files from the .java file. See Also:



"SQLJ Translator" on page 2-2

SQLJ run time: For ISO standard code generation, the SQLJ run time implements the desired actions of the SQL operations by accessing the database using a JDBC driver. The generic ISO SQLJ standard does not require that a SQLJ run time use a JDBC driver to access the database. See Also:

"SQLJ Run Time" on page 9-11

In addition to the translator and run time, there is a component known as the customizer that plays a role. A customizer tailors SQLJ profiles for a particular database implementation and vendor-specific features and data types. By default, for ISO standard code, the SQLJ front end invokes an Oracle customizer to tailor your profiles for Oracle Database instance and Oracle-specific features and data types. When you use Oracle customizer during translation, your application will require the SQLJ run time and an Oracle JDBC driver when it runs. From Oracle Database 10g release 1 (10.1), only Oracle JDBC drivers are supported with SQLJ.

Note:

SQLJ Profiles With ISO standard code generation, SQLJ profiles are serialized Java resources or classes generated by the SQLJ translator, which contain details about the embedded SQL statements. The translator creates these profiles. Then, depending on the translator option settings, it either serializes the profiles and puts them into binary resource files or puts them into .class files. This section covers the following topics: ■

Overview of Profiles



Binary Portability

Overview of Profiles SQLJ profiles are used in ISO standard code for implementing the embedded SQL operations in SQLJ executable statements. Profiles contain information about the SQL operations and the types and modes of data being accessed. A profile consists of a collection of entries, where each entry maps to one SQL operation. Each entry fully specifies the corresponding SQL operation, describing each of the parameters used in processing this instruction.

Key Programming Considerations 3-33

ISO Standard Code Generation

SQLJ generates a profile for each connection context class in your application, where each connection context class corresponds to a particular set of SQL entities you use in your database operations. There is one default connection context class, and you can declare additional classes. The ISO SQLJ standard requires that the profiles be of standard format and content. Therefore, for your application to use vendor-specific extended features, your profiles must be customized. By default, this occurs automatically, with your profiles being customized to use Oracle-specific extended features. Profile customization enables vendors to add value in the following ways: ■



Vendors can support their own specific data types and SQL syntax. For example, Oracle customizer maps standard JDBC PreparedStatement method calls in translated SQLJ code to OraclePreparedStatement method calls, which provide support for Oracle type extensions. Vendors can improve performance through specific optimizations. Note: ■



By default, SQLJ profile file names have the .ser extension, but this does not mean that all .ser files are profiles. Other serialized objects can use this extension, and a SQLJ program unit can use serialized objects other than its profiles. Optionally, profiles can be converted to .class files instead of .ser files. A SQLJ profile is not produced if there are no SQLJ executable statements in the source code.

Binary Portability SQLJ-generated profile files support binary portability. That is, you can port them as is and use them with other kinds of databases or in other environments, if you have not used vendor-specific data types or features. This is true for generated .class files as well.

SQLJ Translation Steps For ISO standard code generation (-codegen=iso), the translator processes the SQLJ source code, converts SQL operations to SQLJ run-time calls, and generates Java output code and one or more SQLJ profiles. A separate profile is generated for each connection context class in the source code, where a different connection context class is typically used for each interrelated set of SQL entities that is used in the operations. Generated Java code is put into a .java output file containing the following: ■ ■

Any class definitions and Java code from the .sqlj source file Class definitions created as a result of the SQLJ iterator and connection context declarations See Also:





"Overview of SQLJ Declarations" on page 4-1

A class definition for a specialized class known as the profile-keys class that SQLJ generates and uses in conjunction with the profiles (for ISO standard SQLJ code generation only) Calls to the SQLJ run time to implement the actions of the embedded SQL operations

3-34 Oracle Database SQLJ Developer’s Guide and Reference

ISO Standard Code Generation

Generated profiles contain information about all the embedded SQL statements in the SQLJ source code, such as actions to take, data types being manipulated, and tables being accessed. When the application is run, the SQLJ run time accesses the profiles to retrieve the SQL operations and passes them to the JDBC driver. By default, profiles are put into .ser serialized resource files, but SQLJ can optionally convert the .ser files to .class files as part of the translation. The compiler compiles the generated Java source file and produces Java .class files as appropriate. This includes a .class file for each class that is defined, each of the SQLJ declarations, and the profile-keys class. The JVM then invokes Oracle customizer or other specified customizer to customize the profiles generated. See Also:

"Internal Translator Operations" on page 9-1

General SQLJ Notes Consider the following when translating and running SQLJ applications for ISO specific code generation: ■

Along with compiling existing .java files on the command line and making them available for type resolution, as for Oracle-specific code generation, you need to: –

Customize the existing profiles



Customize the Java Archive (JAR) files containing profiles See Also:

"Translator Command Line and Properties Files" on

page 8-1 ■



SQLJ generates profiles and the profile-keys class only if your source code includes SQLJ executable statements. If you use Oracle customizer during translation, then your application requires Oracle SQLJ run time and an Oracle JDBC driver when it runs, even if your code does not use Oracle-specific features. You can avoid this by specifying -profile=false when you translate, to bypass Oracle-specific customization.

Summary of Translator Input and Output We have seen what the SQLJ translator takes as input, what it produces as output, and where it places its output in case of Oracle-specific code generation. This section covers the same topics for ISO standard code generation: ■

Translator Input



Translator Output



Output File Locations See Also:

"Summary of Translator Input and Output" on page 2-7

Translator Input Similar to Oracle -specific code generation, the SQLJ translator takes one or more .sqlj source files as input, which can be specified on the command line. The name of the main .sqlj file is based on the public class it defines, if any, else on the first class it defines. See Also:

"Translator Input" on page 2-7

Key Programming Considerations 3-35

ISO Standard Code Generation

Translator Output The translation step produces a Java source file for each .sqlj file in the application and at least one application profile for ISO standard code generation, presuming the source code uses SQLJ executable statements. SQLJ generates Java source files and application profiles as follows: See Also: ■



"Translator Output" on page 2-7

Similar to Oracle-specific code generation, Java source files are .java files with the same base names as the .sqlj files. The application profile files, if applicable, contain information about the SQL operations of the SQLJ application. There is one profile for each connection class that is used in the application. The profiles have names with the same base name as the main .sqlj file and the following extensions: _SJProfile0.ser _SJProfile1.ser _SJProfile2.ser ...

For example, for MyClass.sqlj the translator produces: MyClass_SJProfile0.ser

The .ser file extension indicates that the profiles are serialized. The .ser files are binary files. The -ser2class translator option instructs the translator to generate profiles as .class files instead of .ser files. Other than the file name extension, the naming is the same.

Note:

Similar to the compilation step of Oracle-specific code generation, compiling the Java source file into multiple class files generates one .class file for each class defined in the .sqlj source file. But in case of ISO code generation, a .class file is also generated for a class known as the profile-keys class that the translator generates and uses with the profiles to implement the SQL operations. Additional .class files are produced if you declare any SQLJ iterators or connection contexts. Also, like Oracle-specific code generation, separate .class files are produced for any inner classes or anonymous classes in the code. See Also:

"Overview of SQLJ Declarations" on page 4-1

The .class files are named as follows: ■



Like Oracle-specific code generation, the class file for each class defined consists of the name of the class with the .class extension. The profile-keys class that the translator generates is named according to the base name of the main .sqlj file, plus the following: _SJProfileKeys

So, the class file has the following extension: _SJProfileKeys.class

3-36 Oracle Database SQLJ Developer’s Guide and Reference

ISO Standard Code Generation

For example, for MyClass.sqlj, the translator together with the compiler produces: MyClass_SJProfileKeys.class ■

Like Oracle-specific code generation, the translator names iterator classes and connection context classes according to how you declare them.

The customization step alters the profiles but produces no additional output. See Also: "Profile Customization (ISO Code Generation)" on page 9-7

It is not necessary to reference SQLJ profiles or the profile-keys class directly. This is all handled automatically.

Note:

Output File Locations The output file locations are the same for both Oracle-specific code generation and ISO standard code generation. See Also:

"Output File Locations" on page 2-8

SQLJ Run-Time Processing This section discusses run-time processing for ISO standard code during program execution. For ISO standard SQLJ applications, the SQLJ run time reads the profiles and creates connected profiles, which incorporate database connections. Then the following occurs each time the application must access the database: 1.

SQLJ-generated application code uses methods in a SQLJ-generated profile-keys class to access the connected profile and read the relevant SQL operations. There is a mapping between SQLJ executable statements in the application and SQL operations in the profile.

2.

The SQLJ-generated application code calls the SQLJ run time, which reads the SQL operations from the profile.

3.

The SQLJ run time calls the JDBC driver and passes the SQL operations to the driver.

4.

The SQLJ run time passes any input parameters to the JDBC driver.

5.

The JDBC driver executes the SQL operations.

6.

If any data is to be returned, then the database sends it to the JDBC driver, which sends it to the SQLJ run time for use by your application. Passing input parameters can also be referred to as binding input parameters or binding host expressions. The terms host variables, host expressions, bind variables, and bind expressions are all used to describe Java variables or expressions that are used as input or output for SQL operations.

Note:

Deployment Scenarios We have discussed how to run Oracle-specific SQLJ code in the following scenarios: Key Programming Considerations 3-37

ISO Standard Code Generation



From an applet



In the server (optionally running the SQLJ translator in the server as well)

There are a few considerations that you need to make while running your ISO standard code from an applet: See Also: ■

"Alternative Deployment Scenarios" on page 2-11

You must package all the SQLJ run time packages with your applet. The packages are: sqlj.runtime sqlj.runtime.ref sqlj.runtime.profile sqlj.runtime.profile.ref sqlj.runtime.error

Also package the following if you used Oracle customization: oracle.sqlj.runtime oracle.sqlj.runtime.error

These packages are included with your Oracle installation in one of several run time libraries in the ORACLE_HOME/lib directory. See Also: "Requirements for Using the Oracle SQLJ Implementation" on page 1-2 ■

Some browsers, such as Netscape Navigator 4.x, do not support resource files with a .ser extension, which is the extension used by the SQLJ serialized object files that are used for profiles. However, the Sun Microsystems Java plug-in supports .ser files. Alternatively, if you do not want to use the plug-in, then the Oracle SQLJ implementation offers the -ser2class option to convert .ser files to .class files during translation. See Also: "Conversion of .ser File to .class File (-ser2class)" on page 8-53

This consideration does not apply to the default Oracle-specific code generation, where no profiles are produced.

Note:



Applets using Oracle-specific features require Oracle SQLJ run time to work. Oracle SQLJ run time consists of the classes in the SQLJ run time library file under oracle.sqlj.*. Oracle SQLJ runtime.jar library requires the Java Reflection API, java.lang.reflect.*. Most browsers do not support the Reflection API or impose security restrictions, but the Sun Microsystems Java plug-in provides support for the Reflection API. With ISO standard code generation, the following SQLJ language features always require the Java Reflection API, regardless of the version of the SQLJ run time you are using: –

The CAST statement

3-38 Oracle Database SQLJ Developer’s Guide and Reference

Requirements and Restrictions for Naming



REF CURSOR parameters or REF CURSOR columns being retrieved from the database as instances of a SQLJ iterator



Retrieval of java.sql.Ref, Struct, Array, Blob, or Clob objects



Retrieval of SQL objects as instances of Java classes implementing the oracle.sql.ORAData or java.sql.SQLData interfaces ■An exception to the preceding is if you use SQLJ in a mode that is fully compatible with ISO. That is, if you use SQLJ in an environment that complies with J2EE and you translate and run your program with the SQLJ runtime12ee.jar library, and you employ connection context type maps as specified by ISO. In this case, instances of java.sql.Ref, Struct, Array, Blob, Clob, and SQLData are being retrieved without the use of reflection.

Note:



If you use Oracle-specific code generation, then you will eliminate the use of reflection in all of the instances listed.

Oracle-Specific Code Generation Versus ISO Standard Code Generation The Oracle SQLJ implementation provides the option of Oracle-specific code generation, where Oracle JDBC calls are generated directly in the code. This is the default behavior. In the case of Oracle-specific code generation, you must be aware of the following: ■



There are no profile files, and therefore, there is no customization step during translation. At run time, SQL operations do not have to go through the SQLJ run time layer, because JDBC calls, instead of the SQLJ run time calls, are directly generated in the translated code.

Requirements and Restrictions for Naming There are four areas to consider in discussing naming requirements, naming restrictions, and reserved words: ■

The Java namespace, including additional restrictions imposed by SQLJ on the naming of local variables and classes



The SQLJ namespace



The SQL namespace



Source file names

This section covers the following topics: ■

Java Namespace: Local Variable and Class Naming Restrictions



SQLJ Namespace



SQL Namespace



File Name Requirements and Restrictions

Key Programming Considerations 3-39

Requirements and Restrictions for Naming

Java Namespace: Local Variable and Class Naming Restrictions The Java namespace applies to all standard Java statements and declarations, including the naming of Java classes and local variables. All standard Java naming restrictions apply, and you should avoid the use of Java reserved words. In addition, SQLJ places minor restrictions on the naming of local variables and classes. Note: Naming restrictions particular to host variables are discussed in "Restrictions on Host Expressions" on page 4-24.

Local Variable Naming Restrictions Some of the functionality of the SQLJ translator results in minor restrictions in naming local variables. The SQLJ translator replaces each SQLJ executable statement with a statement block, where the SQLJ executable statement is of the standard syntax: #sql { SQL operation };

SQLJ may use temporary variable declarations within a generated statement block. The name of any such temporary variables will include the following prefix: __sJT_

Note:

There are two underscores at the beginning and one at the end.

The following declarations are examples of those that might occur in a SQLJ-generated statement block: int __sJT_index; Object __sJT_key; java.sql.PreparedStatement __sJT_stmt;

The string __sJT_ is a reserved prefix for SQLJ-generated variable names. SQLJ programmers must not use this string as a prefix for the following: ■

Names of variables declared in blocks that include executable SQL statements



Names of parameters to methods that contain executable SQL statements



Names of fields in classes that contain executable SQL statements, or whose subclasses or enclosed classes contain executable SQL statements

Class Naming Restrictions Be aware of the following minor restrictions in naming classes in SQLJ applications: ■

You must not declare class names that may conflict with SQLJ internal classes. In particular, a top-level class cannot have a name of the following form, where a is the name of an existing class in the SQLJ application: a_SJb

where, a and b are legal Java identifiers. For example, if your application class is Foo in file Foo.sqlj, then SQLJ generates a profile-keys class called Foo_SJProfileKeys. Do not declare a class name that conflicts with this.

3-40 Oracle Database SQLJ Developer’s Guide and Reference

Requirements and Restrictions for Naming



A class containing SQLJ executable statements must not have a name that is the same as the first component of the name of any package that includes a Java type used in the application. Examples of class names to avoid are java, sqlj, and oracle (case-sensitive). As another example, if your SQLJ statements use host variables whose type is abc.def.MyClass, then you cannot use abc as the name of the class that uses these host variables. To avoid this restriction, follow Java naming conventions recommending that package names start in lowercase and class names start in uppercase.

SQLJ Namespace The SQLJ namespace refers to #sql class declarations and the portion of #sql executable statements outside the curly braces. Restrictions particular to the naming of iterator columns are discussed in "Using Named Iterators" on page 4-31.

Note:

Avoid using the following SQLJ reserved words as class names for declared connection context classes or iterator classes, in with or implements clauses, or in iterator column type declaration lists: ■

iterator



context



with

For example, do not have an iterator class or instance called iterator or a connection context class or instance called context. However, note that it is permissible to have a stored function return variable whose name is any of these words.

SQL Namespace The SQL namespace refers to the portion of a SQLJ executable statement inside the curly braces. Standard SQL naming restrictions apply here. See Also:

Oracle Database SQL Language Reference

However, note that host expressions follow rules of the Java namespace, not the SQL namespace. This applies to the name of a host variable and to everything between the outer parentheses of a host expression.

File Name Requirements and Restrictions SQLJ source files have the .sqlj file name extension. If the source file declares a public class (maximum of one), then the base name of the file must match the name of this class (case-sensitive). If the source file does not declare a public class, then the file name must still be a legal Java identifier, and it is recommended that the file name match the name of the first defined class. For example, if you define the public class MySource in your source file, then your file name must be: MySource.sqlj

Key Programming Considerations 3-41

Considerations for SQLJ in the Middle Tier

These file naming requirements follow the Java Language Specification (JLS) and are not SQLJ-specific. These requirements do not directly apply in Oracle Database 11g, but it is still advisable to adhere to them.

Note:

Considerations for SQLJ in the Middle Tier There are special considerations if you run SQLJ in the middle tier, such as in an Oracle9i Application Server Containers for J2EE (OC4J) environment. Oracle JDBC drivers provide Oracle-specific interfaces in the oracle.jdbc package. The Oracle SQLJ libraries runtime12.jar and runtime12ee.jar make full use of these interfaces, but these libraries are not compatible with Oracle JDBC implementations prior to Oracle9i Application Server. In Oracle9i Application Server, connections are established through data sources, which typically return instances of the oracle.jdbc.OracleConnection interface instead of the older oracle.jdbc.driver.OracleConnection class. This is necessary for certain connection functionality, such as distributed transactions (XA). To support such features, connection objects must implement the new interface. This has the following consequences, relevant in an Oracle9i Application Server middle-tier environment, or any situation where data sources are used: ■



For maximum portability and flexibility of your code, use oracle.jdbc.OracleXXX types instead of oracle.jdbc.driver.OracleXXX types. For custom Java types (typically for SQL objects and collections), implement oracle.sql.ORAData instead of the deprecated oracle.sql.CustomDatum interface.

For general information about SQLJ support for data sources and connection JavaBeans, refer to the following sections: ■

"Standard Data Source Support" on page 7-9



"SQLJ-Specific Data Sources" on page 7-11



"SQLJ-Specific Connection JavaBeans for JavaServer Pages" on page 7-14

3-42 Oracle Database SQLJ Developer’s Guide and Reference

4 Basic Language Features SQLJ statements always begin with a #sql token and can be broken into two main categories: ■



Declarations: Used for creating Java classes for iterators, which is similar to Java Database Connectivity (JDBC) result sets, or connection contexts, which is designed to help you create strongly typed connections according to the sets of SQL entities being used. Executable statements: Used to execute embedded SQL operations.

This chapter discusses the following topics: ■

Overview of SQLJ Declarations



Overview of SQLJ Executable Statements



Java Host, Context, and Result Expressions



Single-Row Query Results: SELECT INTO Statements



Multirow Query Results: SQLJ Iterators



Assignment Statements (SET)



Stored Procedure and Function Calls

Overview of SQLJ Declarations A SQLJ declaration consists of the #sql token followed by the declaration of a class. SQLJ declarations introduce specialized Java types into your application. There are currently two kinds of SQLJ declarations, iterator declarations and connection context declarations, defining Java classes as follows: ■



Iterator declarations define iterator classes. Iterators are conceptually similar to JDBC result sets and are used to receive multi-row query data. An iterator is implemented as an instance of an iterator class. Connection context declarations define connection context classes. Each connection context class is typically used for connections whose operations use a particular set of SQL entities, such as tables, views, and stored procedures. That is to say, instances of a particular connection context class are used to connect to schemas that include SQL entities with the same names and characteristics. SQLJ implements each database connection as an instance of a connection context class. SQLJ includes the predefined sqlj.runtime.DefaultContext connection context class. If you only require one connection context class, then you can use DefaultContext, which does not require a connection context declaration.

Basic Language Features

4-1

Overview of SQLJ Declarations

In any iterator or connection context declaration, you may optionally include the following clauses: ■



The implements clause: Specifies one or more interfaces that the generated class will implement. The with clause: Specifies one or more initialized constants to be included in the generated class.

This section covers the following topics: ■

Rules for SQLJ Declarations



Iterator Declarations



Connection Context Declarations



Declaration IMPLEMENTS Clause



Declaration WITH Clause

Rules for SQLJ Declarations SQLJ declarations are allowed in your SQLJ source code anywhere that a class definition would be allowed in standard Java. For example: SQLJ declaration;

// OK (top level scope)

class Outer { SQLJ declaration; // OK (class level scope) class Inner { SQLJ declaration; // OK (nested class scope) } void func() { SQLJ declaration; // OK (method block) } }

As with standard Java, any public class should be declared in one of the following ways:

Note: ■



Declare it in a separate source file. The base name of the file should be the same as the class name. Declare it at class-level scope or nested-class-level scope. In this case, it may be advisable to use public static modifiers.

This is a requirement if you are using the standard javac compiler provided with the Sun Microsystems JDK.

Iterator Declarations An iterator declaration creates a class that defines a kind of iterator for receiving query data. The declaration will specify the column types of the iterator instances, which must match the column types being selected from the database table.

4-2 Oracle Database SQLJ Developer’s Guide and Reference

Overview of SQLJ Declarations

Basic iterator declarations use the following syntax: #sql iterator iterator_classname (type declarations);

Modifiers are optional and can be any standard Java class modifiers, such as public, static, and so on. Type declarations are separated by commas. There are two categories of iterators, named iterators and positional iterators. For named iterators, you must specify column names and types. For positional iterators, you need to specify only types. The following is an example of a named iterator declaration: #sql public iterator EmpIter (String ename, double sal);

This statement results in the SQLJ translator creating a public EmpIter class with a String attribute ename and a double attribute sal. You can use this iterator to select data from a database table with corresponding employee name and salary columns of matching names (ENAME and SAL) and data types (CHAR and NUMBER). Declaring EmpIter as a positional iterator, instead of a named iterator, can be done as follows: #sql public iterator EmpIter (String, double);

See Also:

"Multirow Query Results: SQLJ Iterators" on page 4-26

Connection Context Declarations A connection context declaration creates a connection context class, whose instances are typically used for database connections that use a particular set of SQL entities. Basic connection context declarations use the following syntax: #sql context context_classname;

As for iterator declarations, modifiers are optional and can be any standard Java class modifiers. For example: #sql public context MyContext;

As a result of this statement, the SQLJ translator creates a public MyContext class. In your SQLJ code you can use instances of this class to create database connections to schemas that include a desired set of entities, such as tables, views, and stored procedures. Different instances of MyContext might be used to connect to different schemas, but each schema might be expected, for example, to include an EMP table, a DEPT table, and a TRANSFER_EMPLOYEE stored procedure. Declared connection context classes are an advanced topic and are not necessary for basic SQLJ applications that use only one interrelated set of SQL entities. In basic scenarios, you can use multiple connections by creating multiple instances of the sqlj.runtime.ref.DefaultContext class, which does not require any connection context declarations. See Also: "Connection Considerations" on page 3-4 and "Connection Contexts" on page 7-1

Declaration IMPLEMENTS Clause When you declare any iterator class or connection context class, you can specify one or more interfaces to be implemented by the generated class.

Basic Language Features

4-3

Overview of SQLJ Declarations

Use the following syntax for an iterator class: #sql iterator iterator_classname implements intfc1,..., intfcN (type declarations);

The portion implements intfc1,..., intfcN is known as the implements clause. Note that in an iterator declaration, the implements clause precedes the iterator type declarations. Here is the syntax for a connection context declaration: #sql context context_classname implements intfc1,..., intfcN;

The implements clause is potentially useful in either an iterator declaration or a connection context declaration, but is more likely to be useful in iterator declarations, particularly in implementing the sqlj.runtime.Scrollable or sqlj.runtime.ForUpdate interface. Scrollable iterators are supported in the Oracle SQLJ implementation. The SQLJ implements clause corresponds to the Java implements clause.

Note:

The following example uses an implements clause in declaring a named iterator class. Presume you have created a package, mypackage, that includes an iterator interface, MyIterIntfc. #sql public iterator MyIter implements mypackage.MyIterIntfc (String ename, int empno);

The declared class MyIter will implement the mypackage.MyIterIntfc interface. The following example declares a connection context class that implements an interface named MyConnCtxtIntfc. Presume that it is in the package mypackage. #sql public context MyContext implements mypackage.MyConnCtxtIntfc;

"Using the IMPLEMENTS Clause in Iterator Declarations" on page 7-35 and "Using the IMPLEMENTS Clause in Connection Context Declarations" on page 7-8

See Also:

Declaration WITH Clause In declaring a connection context class or iterator class, you can use a with clause to specify and initialize one or more constants to be included in the definition of the generated class. Most of this usage is standard, although Oracle implementation adds some extended functionality for iterator declarations. This section covers the following topics: ■

Standard WITH Clause Usage



Oracle-Specific WITH Clause Usage



Example: Returnability

Standard WITH Clause Usage In using a with clause, the constants that are produced are always public static final. Use the following syntax for an iterator class:

4-4 Oracle Database SQLJ Developer’s Guide and Reference

Overview of SQLJ Declarations

#sql iterator iterator_classname with (var1=value1,..., varN=valueN) (type declarations);

The portion with (var1=value1,..., varN=valueN) is the with clause. Note that in an iterator declaration, the with clause precedes the iterator type declarations. Where there is both a with clause and an implements clause, the implements clause must come first. Note that parentheses are used to enclose with lists, but not implements lists. Here is the syntax for a connection context declaration that uses a with clause: #sql context context_classname with (var1=value1,..., varN=valueN);

A predefined set of standard SQLJ constants can be defined in a with clause. However, not all of these constants are meaningful to Oracle Database 11g or to Oracle SQLJ run time. Note:

Attempts to define constants other than the standard constants is legal with Oracle Database 11g, but might not be portable to other SQLJ implementations and will generate a warning if you have the -warn=portable flag enabled. For information about this flag, refer to "Translator Warnings (-warn)" on page 8-33. Supported WITH Clause Constants The Oracle SQLJ implementation supports the following standard constants in connection context declarations: ■

typeMap: a String literal defining the name of a type map properties resource Oracle also supports the use of typeMap in iterator declarations. See Also:



"Oracle-Specific WITH Clause Usage" on page 4-6

dataSource: a String literal defining the name under which a data source is looked up in the InitialContext See Also:

"Standard Data Source Support" on page 7-9

The Oracle SQLJ implementation supports the following standard constants in iterator declarations: ■

sensitivity: SENSITIVE/ASENSITIVE/INSENSITIVE, to define the sensitivity of a scrollable iterator See Also:



"Scrollable Iterator Sensitivity" on page 7-37

returnability: true/false, to define whether an iterator can be returned from a Java stored procedure or function See Also:

"Example: Returnability" on page 4-7

Unsupported WITH Clause Constants If you have SQLJ code that uses these constants, then they will not cause an error but will result in no operation. The Oracle SQLJ implementation does not support the following standard constants in connection context declarations:

Basic Language Features

4-5

Overview of SQLJ Declarations





path: a String literal defining the name of a path to be prepended for resolution of Java stored procedures and functions transformGroup: a String literal defining the name of a SQL transformation group that can be applied to SQL types

The Oracle SQLJ implementation does not support the following standard constants, involving cursor states, in iterator declarations: ■

holdability: true/false, determining cursor holdability The concept of holdability is defined in the SQL specification. A cursor that is holdable can, subject to application request, be kept open and positioned on the current row even when a transaction is completed. Use of the cursor can then be continued in the next transaction of the same SQL session, however, subject to some limitations.



updateColumns: a String literal containing a comma-delimited list of column names An iterator declaration having a with clause that specifies updateColumns must also have an implements clause that specifies the sqlj.runtime.ForUpdate interface. The Oracle SQLJ implementation enforces this, even though updateColumns is currently unsupported.

The following is a sample connection context declaration using typeMap: #sql public context MyContext with (typeMap="MyPack.MyClass");

The declared class MyContext will define a String attribute typeMap that will be public static final and initialized to the value MyPack.MyClass. This value is the fully qualified class name of a ListResourceBundle implementation that provides the mapping between SQL and Java types for statements executed on instances of the MyContext class. The following is a sample iterator declaration using sensitivity: #sql public iterator MyAsensitiveIter with (sensitivity=ASENSITIVE) (String ename, int empno);

This declaration sets the cursor sensitivity to ASENSITIVE for the MyAsensitiveIter named iterator class. The following example uses both an implements clause and a with clause: #sql public iterator MyScrollableIterator implements sqlj.runtime.Scrollable with (holdability=true) (String ename, int empno);

This declaration implements the interface sqlj.runtime.Scrollable and enables the cursor holdability for a named iterator class. Note:

holdability is currently not supported.

Oracle-Specific WITH Clause Usage In addition to the standard with clause usage in a connection context declaration to associate a type map with the connection context class, the Oracle SQLJ implementation enables you to use a with clause to associate a type map with the iterator class in an iterator declaration. For example: #sql iterator MyIterator with (typeMap="MyTypeMap") (Person pers, Address addr);

4-6 Oracle Database SQLJ Developer’s Guide and Reference

Overview of SQLJ Declarations

If you use Oracle-specific code generation and use type maps in your application, then your iterator and connection context declarations must use the same type maps. See Also: "Code Considerations and Limitations with Oracle-Specific Code Generation" on page 3-28

Example: Returnability Use returnability=true in the with clause of a SQLJ iterator declaration to specify that the iterator can be returned from a Java stored procedure to a SQL or PL/SQL statement as a REF CURSOR. With the default returnability=false setting, the iterator cannot be returned in this manner, and an attempt to do so will result in a SQL exception at run time. Create the following database table: create table sqljRetTab(str varchar2(30)); insert into sqljRetTab values ('sqljRetTabCol');

Define the RefCursorSQLJ class in the RefCursorSQLJ.sqlj source file as follows. Note that the iterator type MyIter uses returnability=true. public class RefCursorSQLJ { #sql static public iterator MyIter with (returnability=true) (String str); static public MyIter sqljUserRet() throws java.sql.SQLException { MyIter iter=null; try { #sql iter = {select str from sqljRetTab}; } catch (java.sql.SQLException e) { e.printStackTrace(); throw e; } System.err.println("iter is " + iter); return iter; } }

Load RefCursorSQLJ.sqlj into Oracle Java virtual machine (JVM) inside the database as follows: % loadjava -u scott -r -f -v RefCursorSQLJ.sqlj Password: password

Invoke the Java stored procedure defined for the sqljUserRet() method: create or replace package refcur_pkg as type refcur_t is ref cursor; end; / create or replace function sqljUserRet return refcur_pkg.refcur_t as language java name 'RefCursorSQLJ.sqljUserRet() return RefCursorSQLJ.MyIter'; / select scott.sqljUserRet from dual;

Basic Language Features

4-7

Overview of SQLJ Executable Statements

Here is the result of the SELECT statement: SQLJRET1 -------------------CURSOR STATEMENT : 1 STR -----------------------------sqljRetTabCol

Overview of SQLJ Executable Statements A SQLJ executable statement consists of the #sql token followed by a SQLJ clause, which uses syntax that follows a specified standard for embedding executable SQL statements in Java code. The embedded SQL operation of a SQLJ executable statement can be any SQL operation supported by the JDBC driver. This section covers the following topics: ■

Rules for SQLJ Executable Statements



SQLJ Clauses



Specifying Connection Context Instances and Execution Context Instances



Executable Statement Examples



PL/SQL Blocks in Executable Statements

Rules for SQLJ Executable Statements A SQLJ executable statement must adhere to the following rules: ■

It is permitted in Java code wherever Java block statements are permitted. That is, it is permitted inside method definitions and static initialization blocks.



Its embedded SQL operation must be enclosed in curly braces: {...}.



It must be terminated with a semi-colon (;). Note: ■





It is recommended that you do not close the SQL operation with a semi-colon. The parser will detect the end of the operation when it encounters the closing curly brace of the SQLJ clause. Everything inside the curly braces of a SQLJ executable statement is treated as SQL syntax and must follow SQL rules, with the exception of Java host expressions. During offline parsing of SQL operations, all SQL syntax is checked. However, during online semantics-checking only data manipulation language (DML) operations can be parsed and checked. Data definition language (DDL) operations, transaction-control operations, or any other kinds of SQL operations cannot be parsed and checked.

4-8 Oracle Database SQLJ Developer’s Guide and Reference

Overview of SQLJ Executable Statements

SQLJ Clauses A SQLJ clause is the executable part of a statement, consisting of everything to the right of the #sql token. This consists of embedded SQL inside curly braces, preceded by a Java result expression if appropriate, such as result in the following example: #sql { SQL operation }; // For a statement with no output, like INSERT ... #sql result = { SQL operation }; // For a statement with output, like SELECT

A clause without a result expression, such as in the first SQLJ statement in the example, is known as a statement clause. A clause that does have a result expression, such as in the second SQLJ statement in the example, is known as an assignment clause. A result expression can be anything from a simple variable that takes a stored-function return value to an iterator that takes several columns of data from a multi-row SELECT, where the iterator can be an instance of an iterator class or subclass. A SQL operation in a SQLJ statement can use standard SQL syntax only or can use a clause with syntax specific to SQLJ. Table 4–1 lists supported SQLJ statement clauses and Table 4–2 lists supported SQLJ assignment clauses. The last two entries in Table 4–1 are general categories for statement clauses that use standard SQL syntax or Oracle PL/SQL syntax, as opposed to SQLJ-specific syntax. Table 4–1

SQLJ Statement Clauses

Category

Functionality

More Information

SELECT INTO clause

Select data into Java host expressions.

"Single-Row Query Results: SELECT INTO Statements" on page 4-24

FETCH clause

Fetch data from a positional iterator.

"Using Positional Iterators" on page 4-34

COMMIT clause

Commit changes to the data.

"Using Manual COMMIT and ROLLBACK" on page 3-20

ROLLBACK clause

Cancel changes to the data.

"Using Manual COMMIT and ROLLBACK" on page 3-20

SAVEPOINT RELEASE SAVEPOINT ROLLBACK TO clauses

Set a savepoint for future rollbacks, release a specified savepoint, roll back to a savepoint.

"Using Savepoints" on page 3-21

SET TRANSACTION clause

Use advanced transaction control for access mode and isolation level.

"Advanced Transaction Control" on page 7-41

Procedure clause

Call a stored procedure.

"Calling Stored Procedures" on page 4-43

Assignment clause

Assign values to Java host expressions.

"Assignment Statements (SET)" on page 4-41

SQL clause

Use standard SQL syntax Oracle Database SQL Language Reference and functionality: UPDATE, INSERT, DELETE.

PL/SQL block

Use BEGIN..END or DECLARE..BEGIN..END anonymous block inside SQLJ statement.

"PL/SQL Blocks in Executable Statements" on page 4-11 Oracle Database PL/SQL Language Reference

Basic Language Features

4-9

Overview of SQLJ Executable Statements

Table 4–2

SQLJ Assignment Clauses

Category

Functionality

More Information

Query clause

Select data into a SQLJ iterator.

"Multirow Query Results: SQLJ Iterators" on page 4-26

Function clause

Call a stored function.

"Calling Stored Functions" on page 4-44

Iterator conversion clause

Convert a JDBC result set "Converting from Result Sets to Named to a SQLJ iterator. or Positional Iterators" on page 7-48

A SQLJ statement is referred to by the same name as the clause that makes up the body of that statement. For example, an executable statement consisting of #sql followed by a SELECT INTO clause is referred to as a SELECT INTO statement.

Note:

Specifying Connection Context Instances and Execution Context Instances If you have defined multiple database connections and want to specify a particular connection context instance for an executable statement, then use the following syntax: #sql [conn_context_instance] { SQL operation };

See Also:

"Connection Considerations" on page 3-4

If you have defined one or more execution context instances of the sqlj.runtime.ExecutionContext class and want to specify one of them for use with an executable statement, then use the following syntax: #sql [exec_context_instance] { SQL operation };

You can use an execution context instance to provide status or control of the SQL operation of a SQLJ executable statement. For example, you can use execution context instances in multithreading situations where multiple operations are occurring on the same connection. See Also:

"Execution Contexts" on page 7-24

You can also specify both a connection context instance and an execution context instance: #sql [conn_context_instance, exec_context_instance] { SQL operation };

Note: ■



Include the square brackets around connection context instances and execution context instances. They are part of the syntax. If you specify both a connection context instance and an execution context instance, then the connection context instance must come first.

4-10 Oracle Database SQLJ Developer’s Guide and Reference

Overview of SQLJ Executable Statements

Executable Statement Examples This section provides examples of elementary SQLJ executable statements. Elementary INSERT The following example demonstrates a basic INSERT. The statement clause does not require any syntax specific to SQLJ. Consider an employee table EMP with the following rows: CREATE TABLE EMP ( ENAME VARCHAR2(10), SAL NUMBER(7,2) );

Use the following SQLJ executable statement, which uses only standard SQL syntax, to insert Joe as a new employee into the EMP table, specifying his name and salary: #sql { INSERT INTO emp (ename, sal) VALUES (’Joe’, 43000) };

Elementary INSERT with Connection Context or Execution Context Instances The following examples use ctx as a connection context instance, which is an instance of either the default sqlj.runtime.ref.DefaultContext or a class that you have previously declared in a connection context declaration, and execctx as an execution context instance: #sql [ctx] { INSERT INTO emp (ename, sal) VALUES (’Joe’, 43000) }; #sql [execctx] { INSERT INTO emp (ename, sal) VALUES (’Joe’, 43000) }; #sql [ctx, execctx] { INSERT INTO emp (ename, sal) VALUES (’Joe’, 43000) };

A Simple SQLJ Method This example demonstrates a simple method using SQLJ code, demonstrating how SQLJ statements interrelate with and are interspersed with Java statements. The SQLJ statement uses standard INSERT INTO table VALUES syntax supported by the Oracle SQL implementation. The statement also uses Java host expressions, marked by colons (:), to define the values. Host expressions are used to pass data between the Java code and SQL instructions. public static void writeSalesData (int[] itemNums, String[] itemNames) throws SQLException { for (int i =0; i < itemNums.length; i++) #sql { INSERT INTO sales VALUES(:(itemNums[i]), :(itemNames[i]), SYSDATE) }; }

Note: ■ ■

The throws SQLException is required. SQLJ function calls also use a VALUES token, but these situations are not related semantically.

PL/SQL Blocks in Executable Statements PL/SQL blocks can be used within the curly braces of a SQLJ executable statement just as SQL operations can, as in the following example:

Basic Language Features 4-11

Java Host, Context, and Result Expressions

#sql { DECLARE n NUMBER; BEGIN n := 1; WHILE n = sysdate }; // Process the results while (projsIter.next()) { System.out.println("Project name is " + projsIter.projname()); System.out.println("Project ID is " + projsIter.id()); System.out.println("Project deadline is " + projsIter.deadline()); } // Close the iterator projsIter.close(); ...

Basic Language Features 4-33

Multirow Query Results: SQLJ Iterators

Note the convenient use of the projname(), id(), and deadline() accessor methods to retrieve the data. Note also that the order of the SELECT items does not matter, nor does the order in which the accessor methods are used. However, remember that accessor method names are created with the case exactly as in your declaration of the iterator class. The following will generate compilation errors. Consider the following declaration of the iterator: #sql iterator Cursor1 (String NAME);

The code for using the iterator is as follows: ... Cursor1 c1; #sql c1 = { SELECT NAME FROM TABLE }; while (c1.next()) { System.out.println("The name is " + c1.name()); } ...

The Cursor1 class has a method called NAME(), and not name(). You will have to use c1.NAME() in the System.out.println statement.

Using Positional Iterators When you declare a positional iterator class, you declare the data type of each column but not the column name. The Java types into which the columns of the SQL query results are selected must be compatible with the data types of the SQL data. The names of the database columns or data items in the SELECT statement are irrelevant. Because names are not used, the order in which you declare your positional iterator Java types must exactly match the order in which the data is selected. To retrieve data from a positional iterator once data has been selected into it, use a FETCH INTO statement followed by an endFetch() method call to determine if you have reached the end of the data. Declaring Positional Iterator Classes Use the following syntax to declare a positional iterator class: #sql iterator classname ( position-list );

In this syntax, modifiers is an optional sequence of legal Java class modifiers and the position-list is a list of Java types compatible with the column types in a database table. The implements clause and with clause are optional, specifying interfaces to implement and variables to define and initialize, respectively. "Declaration IMPLEMENTS Clause" on page 4-3 and "Declaration WITH Clause" on page 4-4

See Also:

Now consider an employee table EMP with the following rows: CREATE TABLE EMP ( EMPNO NUMBER(4), ENAME VARCHAR2(10), SAL NUMBER(7,2) );

4-34 Oracle Database SQLJ Developer’s Guide and Reference

Multirow Query Results: SQLJ Iterators

And consider the following positional iterator declaration: #sql public iterator EmpIter (String, int, float);

This example defines the EmpIter Java class with unnamed String, int, and float columns. Note that the table columns and iterator columns are in a different order, with the String corresponding to ENAME and the int corresponding to EMPNO. The order of the iterator columns determines the order in which you must select the data. As with standard Java, any public class should be declared in one of the following ways:

Note: ■



Declare it in a separate source file. The base name of the file should be the same as the class name. Declare it at class-level scope or nested-class-level scope, with public static modifiers.

This is a requirement if you are using the standard javac compiler provided with the Sun Microsystems JDK. Instantiating and Populating Positional Iterators Instantiating and populating a positional iterator is no different than doing so for a named iterator, except that you must be certain that the data items in the SELECT statement are in the proper order. The three data types in the EmpIter iterator class are compatible with the types of the EMP table, but be careful how you select the data, because the order is different. The following will work, because the data items in the SELECT statement are in the same order as the iterator columns: EmpIter empsIter; #sql empsIter = { SELECT ename, empno, sal FROM emp };

Remember that in populating a positional iterator, the number of columns you select from the database must equal the number of columns in the iterator. Accessing Positional Iterators Access the columns defined by a positional iterator using SQL FETCH INTO syntax. The INTO part of the command specifies Java host variables that receive the results columns. The host variables must be in the same order as the corresponding iterator columns. Use the endFetch() method provided with all positional iterator classes to determine whether the last fetch reached the end of the data.

Basic Language Features 4-35

Multirow Query Results: SQLJ Iterators

Note: ■





The endFetch() method initially returns true before any rows have been fetched, then returns false once a row has been successfully retrieved, and then returns true again when a FETCH finds no more rows to retrieve. Therefore, you must perform the endFetch() test after the FETCH INTO statement. If your endFetch() test precedes the FETCH INTO statement, then you will never retrieve any rows, because endFetch() would be true before your first FETCH and you would immediately break out of the while loop. The endFetch() test must be before the results are processed, however, because the FETCH does not throw a SQL exception when it reaches the end of the data, it just triggers the next endFetch() call to return true. If there is no endFetch() test before results are processed, then your code will try to process NULL or invalid data from the first FETCH attempt after the end of the data had been reached. Each iterator has a close() method that you must always call once you finish retrieving data from it. This is necessary to close the iterator and free its resources.

The following is an example, repeating the declaration, instantiation, and population code illustrated in the preceding section. Note that the Java host variables in the SELECT statement are in the same order as the columns of the positional iterator, which is mandatory. First, presume the following iterator class declaration: #sql public iterator EmpIter (String, int, float);

Populate and then access an instance of this iterator class as follows: // Declare and initialize host variables int empnum=0; String empname=null; float salary=0.0f; // Declare an iterator instance EmpIter empsIter; #sql empsIter = { SELECT ename, empno, sal FROM emp }; while (true) { #sql { FETCH :empsIter INTO :empnum, :empname, :salary }; if (empsIter.endFetch()) break; // This test must be AFTER fetch, // but before results are processed. System.out.println("Name is " + empname); System.out.println("Employee number is " + empnum); System.out.println("Salary is " + salary); } // Close the iterator empsIter.close(); ...

4-36 Oracle Database SQLJ Developer’s Guide and Reference

Multirow Query Results: SQLJ Iterators

The empname, empnum, and salary variables are Java host variables whose types must match the types of the iterator columns. Do not use the next() method for a positional iterator. A FETCH operation calls it implicitly to move to the next row. Note: Host variables in a FETCH INTO statement must always be initialized because they are assigned in one branch of a conditional statement. Otherwise, you will get a compiler error indicating they may never be assigned. FETCH can assign the variables only if there was a row to be fetched.

Positional Iterator Navigation with the next() Method The positional iterator FETCH clause discussed in the preceding section performs a movement, an implicit next() call, before it populates the host variables, if any. As an alternative, the Oracle SQLJ implementation supports a special FETCH syntax in conjunction with explicit next() calls in order to use the same movement logic as with JDBC result sets and SQLJ named iterators. Using this special FETCH syntax, the semantics differ. There is no implicit next() call before the INTO-list is populated. See Also: "FETCH CURRENT Syntax: from JDBC Result Sets to SQLJ Iterators" on page 7-40

Using Iterators and Result Sets as Host Variables SQLJ supports SQLJ iterators and JDBC result sets as host variables. Using iterators and result sets is fundamentally the same, with differences in declarations and in accessor methods to retrieve the data. Note: ■



Additionally, SQLJ supports iterators and result sets as return variables for stored functions. Oracle JDBC drivers currently do not support result sets as input host variables. There is a setCursor() method in the OraclePreparedStatement class, but it raises an exception at run time if called.

For the examples in this section, consider the following department and employee tables: CREATE TABLE DEPT ( DEPTNO NUMBER(2), DNAME VARCHAR2(14) ); CREATE TABLE EMP ( EMPNO NUMBER(4), ENAME VARCHAR2(10), SAL NUMBER(7,2), DEPTNO NUMBER(2) );

Example: Use of Result Set as OUT Host Variable This example uses a JDBC result set as an output host variable.

Basic Language Features 4-37

Multirow Query Results: SQLJ Iterators

... ResultSet rs; ... #sql { BEGIN OPEN :OUT rs FOR SELECT ename, empno FROM emp; END }; while (rs.next()) { String empname = rs.getString(1); int empnum = rs.getInt(2); } rs.close(); ...

This example opens the result set rs in a PL/SQL block to receive data from a SELECT statement, selects data from the ENAME and EMPNO columns of the EMP table, and then loops through the result set to retrieve data into local variables. Example: Use of Iterator as OUT Host Variable This example uses a named iterator as an output host variable. The iterator can be declared as follows: #sql public iterator EmpIter (String ename, int empno);

The public modifier is required, and the static modifier may be advisable if your declaration is at class level or nested-class level. This iterator can be used as follows: ... EmpIter iter; ... #sql { BEGIN OPEN :OUT iter FOR SELECT ename, empno FROM emp; END }; while (iter.next()) { String empname = iter.ename(); int empnum = iter.empno(); ...process/output empname and empnum... } iter.close(); ...

This example opens the iterator iter in a PL/SQL block to receive data from a SELECT statement, selects data from the ENAME and EMPNO columns of the EMP table, and then loops through the iterator to retrieve data into local variables. Example: Use of Iterator as OUT Host Variable for SELECT INTO This example uses a named iterator as an output host variable, taking data through a SELECT INTO statement. OUT is the default for host variables in an INTO-list. The iterator can be declared as follows: #sql public iterator ENameIter (String ename);

4-38 Oracle Database SQLJ Developer’s Guide and Reference

Multirow Query Results: SQLJ Iterators

The public modifier is required, and the static modifier may be advisable if your declaration is at class level or nested-class level. This iterator can be used as follows: ... ENameIter enamesIter; String deptname; ... #sql { SELECT dname, cursor (SELECT ename FROM emp WHERE deptno = dept.deptno) INTO :deptname, :enamesIter FROM dept WHERE deptno = 20 }; System.out.println(deptname); while (enamesIter.next()) { System.out.println(enamesIter.ename()); } enamesIter.close(); ...

This example uses nested SELECT statements to accomplish the following: ■



■ ■

Select the name of department number 20 from the DEPT table, selecting it into the deptname output host variable. Query the EMP table to select all employees whose department number is 20, selecting the resulting cursor into the enamesIter output host variable, which is a named iterator. Print the department name. Loop through the named iterator printing employee names. This prints the names of all employees in the department.

In most cases, using SELECT INTO is more convenient than using nested iterators if you are retrieving a single row in the outer SELECT, although that option is also available. Also, with nested iterators, you would have to process the data to determine how many rows there are in the outer SELECT. With SELECT INTO you are assured of just one row.

Using Iterators and Result Sets as Iterator Columns The Oracle SQLJ implementation includes extensions that allow iterator declarations to specify columns of ResultSet type or columns of other iterator types declared within the current scope. In other words, iterators and result sets can exist within iterators. These column types are used to retrieve a column in the form of a cursor. This is useful for nested SELECT statements that return nested table information. The following examples are functionally identical. Each uses a nested result set or iterator, that is, result sets or iterators in a column within an iterator, to print all the employees in each department in the DEPT table. The first example uses result sets within a named iterator, the second example uses named iterators within a named iterator, and the third example uses named iterators within a positional iterator. Following are the steps: 1.

Select each department name (DNAME) from the DEPT table.

2.

Do a nested SELECT into a cursor to get all employees from the EMP table for each department.

Basic Language Features 4-39

Multirow Query Results: SQLJ Iterators

3.

Put the department names and sets of employees into the outer iterator (iter), which has a name column and an iterator column. The cursor with the employee information for any given department goes into the iterator column of the row of the outer iterator corresponding to the department.

4.

Go through a nested loop that, for each department, prints the department name and then loops through the inner iterator to print all employee names for that department.

Example: Result Set Column in a Named Iterator This example uses a column of type ResultSet in a named iterator. The iterator can be declared as follows: #sql iterator DeptIter (String dname, ResultSet emps);

The code that uses the iterator is as follows: ... DeptIter iter; ... #sql iter = { SELECT dname, cursor (SELECT ename FROM emp WHERE deptno = dept.deptno) AS emps FROM dept }; while (iter.next()) { System.out.println(iter.dname()); ResultSet enamesRs = iter.emps(); while (enamesRs.next()) { String empname = enamesRs.getString(1); System.out.println(empname); } enamesRs.close(); } iter.close(); ...

Example: Named Iterator Column in a Named Iterator This example uses a named iterator that has a column whose type is that of a previously defined named iterator (nested iterators). The iterator declaration is as follows: #sql iterator ENameIter (String ename); #sql iterator DeptIter (String dname, ENameIter emps);

The code that uses this iterator is as follows: ... DeptIter iter; ... #sql iter = { SELECT dname, cursor (SELECT ename FROM emp WHERE deptno = dept.deptno) AS emps FROM dept }; while (iter.next()) { System.out.println(iter.dname()); ENameIter enamesIter = iter.emps();

4-40 Oracle Database SQLJ Developer’s Guide and Reference

Assignment Statements (SET)

while (enamesIter.next()) { System.out.println(enamesIter.ename()); } enamesIter.close(); } iter.close(); ...

Example: Named Iterator Column in a Positional Iterator This example uses a positional iterator that has a column whose type is that of a previously defined named iterator (nested iterators). This uses the FETCH INTO syntax of positional iterators. This example is functionally equivalent to the previous two. Note that because the outer iterator is a positional iterator, there does not have to be an alias to match a column name, as was required when the outer iterator was a named iterator in the previous example. The iterator declaration is as follows: #sql iterator ENameIter (String ename); #sql iterator DeptIter (String, ENameIter);

The code that uses this iterator is as follows: ... DeptIter iter; ... #sql iter = { SELECT dname, cursor (SELECT ename FROM emp WHERE deptno = dept.deptno) FROM dept }; while (true) { String dname = null; ENameIter enamesIter = null; #sql { FETCH :iter INTO :dname, :enamesIter }; if (iter.endFetch()) break; System.out.println(dname); while (enamesIter.next()) { System.out.println(enamesIter.ename()); } enamesIter.close(); } iter.close(); ...

Assignment Statements (SET) SQLJ enables you to assign a value to a Java host expression inside a SQL operation. This is known as an assignment statement and is accomplished using the following syntax: #sql { SET :host_exp = expression };

The host_exp is the target host expression, such as a variable or array index. The expression could be a number, host expression, arithmetic expression, function call, or other construct that yields a valid result into the target host expression. Basic Language Features 4-41

Stored Procedure and Function Calls

The default is OUT for a target host expression in an assignment statement, but you can optionally state this explicitly: #sql { SET :OUT host_exp = expression };

Trying to use an IN or INOUT token in an assignment statement will result in an error at translation time. The preceding statements are functionally equivalent to the following PL/SQL code: #sql { BEGIN :OUT host_exp := expression; END };

Here is a simple example of an assignment statement: #sql { SET :x = foo1() + foo2() };

This statement assigns to x the sum of the return values of foo1() and foo2() and assumes that the type of x is compatible with the type of the sum of the outputs of these functions. Consider the following additional examples: int i2; java.sql.Date dat; ... #sql { SET :i2 = TO_NUMBER(substr(’750 etc.’, 1, 3)) + TO_NUMBER(substr(’250 etc.’, 1, 3)) }; ... #sql { SET :dat = sysdate }; ...

The first statement will assign to i2 the value 1000. The substr() calls takes the first three characters of the strings, that is, "750" and "250". The TO_NUMBER() calls convert the strings to the numbers 750 and 250. The second statement will read the database system date and assign it to dat. An assignment statement is especially useful when you are performing operations on return variables from functions stored in the database. You do not need an assignment statement to simply assign a function result to a variable, because you can accomplish this using standard function call syntax. You also do not need an assignment statement to manipulate output from Java functions, because you can accomplish that in a typical Java statement. So you can presume that foo1() and foo2() are stored functions in the database, not Java functions.

Stored Procedure and Function Calls SQLJ provides convenient syntax for calling stored procedures and stored functions in the database. These procedures and functions could be written in Java, PL/SQL, or any other language supported by the database. A stored function requires a result expression in your SQLJ executable statement to accept the return value and, optionally, can take input, output, or input-output parameters as well. A stored procedure does not have a return value. Optionally, it can take input, output, or input-output parameters. A stored procedure can return output through any output or input-output parameter.

4-42 Oracle Database SQLJ Developer’s Guide and Reference

Stored Procedure and Function Calls

Remember that instead of using the following procedure-call and function-call syntax, you can optionally use JPublisher to create Java wrappers for PL/SQL stored procedures and functions, and then call the Java wrappers as you would call any other Java methods. JPublisher is discussed in "JPublisher and the Creation of Custom Java Classes" on page 6-20. For additional information, refer to the Oracle Database JPublisher User's Guide.

Note:

This section covers the following topics: ■

Calling Stored Procedures



Calling Stored Functions



Using Iterators and Result Sets as Stored Function Returns

Calling Stored Procedures Stored procedures do not have a return value but can take a list with input, output, and input-output parameters. Stored procedure calls use the CALL token. The CALL token is followed by white space and then the procedure name. There must be a space after the CALL token to differentiate it from the procedure name. There cannot be a set of outer parentheses around the procedure call. This differs from the syntax for function calls. The syntax for the CALL token is as follows: #sql { CALL PROC() };

PROC is the name of the stored procedure, which can optionally take a list of input, output, and input-output parameters. PROC can include a schema or package name as well, such as SCOTT.MYPROC(). Presume that you have defined the following PL/SQL stored procedure: CREATE OR REPLACE PROCEDURE MAX_DEADLINE (deadline OUT DATE) IS BEGIN SELECT MAX(start_date + duration) INTO deadline FROM projects; END;

This reads the PROJECTS table, looks at the START_DATE and DURATION columns, calculates start_date + duration in each row, then takes the maximum START_DATE + DURATION total, and assigns it to DEADLINE, which is an output parameter of type DATE. In SQLJ, you can call this MAX_DEADLINE procedure as follows: java.sql.Date maxDeadline; ... #sql { CALL MAX_DEADLINE(:out maxDeadline) };

For any parameters, you must use the host expression tokens IN, OUT, and INOUT appropriately, to match the input, output, and input-output designations of the stored procedure. Additionally, the types of the host variables you use in the parameter list must be compatible with the parameter types of the stored procedure.

Basic Language Features 4-43

Stored Procedure and Function Calls

If you want your application to be compatible with Oracle7 Database, then do not include empty parentheses for the parameter list if the procedure takes no parameters. For example: Note:

#sql { CALL MAX_DEADLINE };

not: #sql { CALL MAX_DEADLINE() };

Calling Stored Functions Stored functions have a return value and can also take a list of input, output, and input-output parameters. Stored function calls use the VALUES token. The VALUES token is followed by the function call. In standard SQLJ, the function call must be enclosed in a set of outer parentheses. In the Oracle SQLJ implementation, the outer parentheses are optional. When using the outer parentheses, it does not matter if there is white space between the VALUES token and the begin-parenthesis. The syntax for the VALUES token is as follows: #sql result = { VALUES(FUNC(PARAM_LIST)) };

In this syntax, result is the result expression, which takes the function return value. FUNC is the name of the stored function, which can optionally take a list of input, output, and input-output parameters. FUNC can include a schema or package name, such as SCOTT.MYFUNC(). A VALUES token can also be used in INSERT INTO table VALUES syntax supported by the Oracle SQL implementation, but these situations are unrelated semantically and syntactically.

Note:

Referring back to the example in "Calling Stored Procedures" on page 4-43, consider defining the stored procedure as a stored function instead, as follows: CREATE OR REPLACE FUNCTION GET_MAX_DEADLINE RETURN DATE IS deadline DATE; BEGIN SELECT MAX(start_date + duration) INTO deadline FROM projects; RETURN deadline; END;

In SQLJ, you can call this GET_MAX_DEADLINE function as follows: java.sql.Date maxDeadline; ... #sql maxDeadline = { VALUES(GET_MAX_DEADLINE) };

The result expression must have a type compatible with the return type of the function. In the Oracle SQLJ implementation, the following syntax is also allowed: #sql maxDeadline = { VALUES GET_MAX_DEADLINE };

Note that the outer parentheses is omitted. For stored function calls, as with stored procedures, you must use the host expression tokens IN, OUT, and INOUT appropriately, to match the input, output, and input-output parameters of the stored function. Additionally, the types of the host

4-44 Oracle Database SQLJ Developer’s Guide and Reference

Stored Procedure and Function Calls

variables you use in the parameter list must be compatible with the parameter types of the stored function. If you want your stored function to be portable to non-Oracle environments, then you should use only input parameters in the calling sequence, not output or input-output parameters.

Note:

Using Iterators and Result Sets as Stored Function Returns SQLJ supports assigning the return value of a stored function to an iterator or result set variable, if the function returns a REF CURSOR type. The following example uses an iterator to take a stored function return. Using a result set is similar. Example: Iterator as Stored Function Return This example uses an iterator as a return type for a stored function, using a REF CURSOR type in the process. Presume the following function definition: CREATE OR REPLACE PACKAGE sqlj_refcursor AS TYPE EMP_CURTYPE IS REF CURSOR; FUNCTION job_listing (j varchar2) RETURN EMP_CURTYPE; END sqlj_refcursor; CREATE OR REPLACE PACKAGE BODY sqlj_refcursor AS FUNCTION job_listing (j varchar) RETURN EMP_CURTYPE IS DECLARE rc EMP_CURTYPE; BEGIN OPEN rc FOR SELECT ename, empno FROM emp WHERE job = j; RETURN rc; END; END sqlj_refcursor;

Declare the iterator as follows: #sql public iterator EmpIter (String ename, int empno);

The public modifier is required, and the static modifier may be advisable if your declaration is at class level or nested-class level. The code that uses the iterator and the function is as follows: EmpIter iter; ... #sql iter = { VALUES(sqlj_refcursor.job_listing(’SALES’)) }; while (iter.next()) { String empname = iter.ename(); int empnum = iter.empno(); ... process empname and empnum ... } iter.close(); ...

Basic Language Features 4-45

Stored Procedure and Function Calls

This example calls the job_listing() function to return an iterator that contains the name and employee number of each employee whose job title is SALES. It then retrieves this data from the iterator.

4-46 Oracle Database SQLJ Developer’s Guide and Reference

5 Type Support This chapter documents data types supported by the Oracle SQLJ implementation, listing supported SQL types and the Java types that correspond to them. This is followed by details about support for streams and Oracle type extensions. SQLJ support of Java types refers to types that can be used in host expressions. This chapter covers the following topics: ■

Supported Types for Host Expressions



Support for Streams



Support for JDBC 2.0 LOB Types and Oracle Type Extensions See Also:

Chapter 6, "Objects, Collections, and OPAQUE Types"

Supported Types for Host Expressions This section summarizes the types supported by the Oracle SQLJ implementation, including information about new support for Java Database Connectivity (JDBC) 2.0 types. Oracle Database JDBC Developer's Guide and Reference for a complete list of legal Java mappings for each Oracle SQL type

See Also:

SQLJ performs implicit conversions between SQL and Java types. Although this is generally useful and helpful, it can produce unexpected results. Do not rely on translation-time type-checking alone to ensure the correctness of your code.

Note:

This section covers the following topics: ■

Summary of Supported Types



Supported Types and Requirements for JDBC 2.0



Using PL/SQL BOOLEAN, RECORD Types, and TABLE Types

Summary of Supported Types Table 5–1 lists the Java types that you can use in host expressions when employing Oracle JDBC drivers. This table also documents the correlation between Java types, SQL types whose type codes are defined in the oracle.jdbc.OracleTypes class, and data types in Oracle Database 11g.

Type Support

5-1

Supported Types for Host Expressions

Note: The OracleTypes class simply defines a type code, which is an integer constant, for each Oracle data type. For standard JDBC types, the OracleTypes value is identical to the standard java.sql.Types value.

SQL data output to a Java variable is converted to the corresponding Java type. A Java variable input to SQL is converted to the corresponding Oracle data type. Table 5–1

Type Mappings for Supported Host Expression Types

Java Type

OracleTypes Definition

Oracle SQL Data Type

boolean

BIT

NUMBER

byte

TINYINT

NUMBER

short

SMALLINT

NUMBER

int

INTEGER

NUMBER

long

BIGINT

NUMBER

float

REAL

NUMBER

double

FLOAT, DOUBLE

NUMBER

java.lang.String

CHAR VARCHAR LONGVARCHAR

CHAR VARCHAR2 LONG

byte[]

BINARY VARBINARY LONGVARBINARY

RAW RAW LONGRAW

java.sql.Date

DATE

DATE

java.sql.Time

TIME

DATE

java.sql.Timestamp

TIMESTAMP TIMESTAMP

DATE TIMESTAMP

java.math.BigDecimal

NUMERIC DECIMAL

NUMBER NUMBER

java.sql.Blob

BLOB

BLOB

java.sql.Clob

CLOB

CLOB

java.sql.Struct

STRUCT

Object types

java.sql.Ref

REF

Reference types

java.sql.Array

ARRAY

Collection types

Custom object classes implementing java.sql.SQLData

STRUCT

Object types

java.lang.Boolean

BIT

NUMBER

java.lang.Byte

TINYINT

NUMBER

java.lang.Short

SMALLINT

NUMBER

java.lang.Integer

INTEGER

NUMBER

STANDARD JDBC 1.x TYPES

STANDARD JDBC 2.0 TYPES

JAVA WRAPPER CLASSES

5-2 Oracle Database SQLJ Developer’s Guide and Reference

Supported Types for Host Expressions

Table 5–1 (Cont.) Type Mappings for Supported Host Expression Types Java Type

OracleTypes Definition

Oracle SQL Data Type

java.lang.Long

BIGINT

NUMBER

java.lang.Float

REAL

NUMBER

java.lang.Double

FLOAT, DOUBLE

NUMBER

sqlj.runtime.BinaryStream

LONGVARBINARY

LONG RAW

sqlj.runtime.CharacterStream

LONGVARCHAR

LONG

sqlj.runtime.AsciiStream (Deprecated; use CharacterStream.)

LONGVARCHAR

LONG

sqlj.runtime.UnicodeStream (Deprecated; use CharacterStream.)

LONGVARCHAR

LONG

oracle.sql.NUMBER

NUMBER

NUMBER

oracle.sql.CHAR

CHAR

CHAR

oracle.sql.RAW

RAW

RAW

oracle.sql.DATE

DATE

DATE

oracle.sql.TIMESTAMP

TIMESTAMP

TIMESTAMP

oracle.sql.TIMESTAMPTZ

TIMESTAMPTZ

TIMESTAMP-WITHTIMEZONE

oracle.sql.TIMESTAMPLTZ

TIMESTAMPLTZ

TIMESTAMP-WITHLOCAL-TIMEZONE

oracle.sql.ROWID

ROWID

ROWID

oracle.sql.BLOB

BLOB

BLOB

oracle.sql.CLOB

CLOB

CLOB

oracle.sql.BFILE

BFILE

BFILE

oracle.sql.STRUCT

STRUCT

Object types

oracle.sql.REF

REF

Reference types

oracle.sql.ARRAY

ARRAY

Collection types

oracle.sql.OPAQUE

OPAQUE

OPAQUE types

Custom object classes implementing oracle.sql.ORAData

STRUCT

Object types

Custom reference classes implementing oracle.sql.ORAData

REF

Reference types

Custom collection classes implementing oracle.sql.ORAData

ARRAY

Collection types

Custom classes implementing oracle.sql.ORAData for OPAQUE types (for example, oracle.xdb.XMLType)

OPAQUE

OPAQUE types

Other custom Java classes implementing oracle.sql.ORAData (to wrap any oracle.sql type)

Any

Any

SQLJ STREAM CLASSES

ORACLE EXTENSIONS

Type Support

5-3

Supported Types for Host Expressions

Table 5–1 (Cont.) Type Mappings for Supported Host Expression Types Java Type

OracleTypes Definition

Oracle SQL Data Type

SQLJ object Java types (can implement either SQLData or ORAData)

JAVA_STRUCT

SQLJ object SQL types (JAVA_STRUCT behind the scenes; automatic conversion to an appropriate Java class)

NA

NA

JAVA TYPES FOR PL/SQL TYPES Scalar indexed-by table represented by a Java numeric array or an array of String, oracle.sql.CHAR, or oracle.sql.NUMBER

Note: There is a PLSQL_INDEX_TABLE type, but it does not appear to be used externally.

GLOBALIZATION SUPPORT oracle.sql.NCHAR

CHAR

CHAR

oracle.sql.NString

CHAR VARCHAR LONGVARCHAR

CHAR VARCHAR2 LONG

oracle.sql.NCLOB

CLOB

CLOB

oracle.sqlj.runtime.NcharCharac LONGVARCHAR terStream

LONG

oracle.sqlj.runtime. NcharAsciiStream (Deprecated; use NcharCharacterStream.)

LONGVARCHAR

LONG

LONGVARCHAR oracle.sqlj.runtime. NcharUnicodeStream (Deprecated; use NcharCharacterStream.)

LONG

QUERY RESULT OBJECTS java.sql.ResultSet

CURSOR

CURSOR

SQLJ iterator objects

CURSOR

CURSOR

Oracle Database JDBC Developer's Guide and Reference for more information about Oracle type support.

See Also:

The following points relate to type support for standard features: ■





JDBC and SQLJ do not support Java char and Character types. Instead, use the Java String type to represent character data. Do not confuse the supported java.sql.Date type with java.util.Date, which is not directly supported. The java.sql.Date class is a wrapper for java.util.Date that enables JDBC to identify the data as a SQL DATE and adds formatting and parsing operations to support JDBC escape syntax for date values. Remember that all numeric types in Oracle Database 11g are stored as NUMBER. Although you can specify additional precision when you declare a NUMBER during table creation, this precision may be lost when retrieving the data through Oracle JDBC drivers, depending on the Java type that you use to receive the data. An oracle.sql.NUMBER instance would preserve full information.

5-4 Oracle Database SQLJ Developer’s Guide and Reference

Supported Types for Host Expressions



The Java wrapper classes, such as Integer and Float, are useful in cases where NULL may be returned by the SQL statement. Primitive types, such as int and float, cannot contain null values. See Also:



The SQLJ stream classes are required in using streams as host variables. See Also:





"Support for Streams" on page 5-8

Weak types cannot be used for OUT or INOUT parameters. This applies to the Struct, Ref, and Array standard JDBC 2.0 types, as well as to corresponding Oracle extended types. A new set of interfaces, in the oracle.jdbc package, was first added in the Oracle9i JDBC implementation in place of classes of the oracle.jdbc.driver package. These interfaces provide a more generic way for users to access Oracle-specific features using Oracle JDBC drivers. Specifically, when creating programs for the middle tier, you should use the oracle.jdbc application programming interface (API). However, SQLJ programmers will not typically use these interfaces directly. They are used transparently by the SQLJ run time or in Oracle-specific generated code. See Also:



"NULL-Handling" on page 3-14

"Custom Java Class Interface Specifications" on page 6-5

For information about SQLJ support for result set and iterator host variables, refer to "Using Iterators and Result Sets as Host Variables" on page 4-45.

The following points relate to Oracle extensions: ■

The Oracle SQLJ implementation requires any class that implements oracle.sql.ORAData to set the static _SQL_TYPECODE parameter according to values defined in the OracleTypes class. In some cases, an additional parameter must be set as well, such as _SQL_NAME for objects and _SQL_BASETYPE for object references. This occurs automatically if you use Oracle JPublisher utility to generate the class. See Also: "Oracle Requirements for Classes Implementing ORAData" on page 6-10



The oracle.sql classes are wrappers for SQL data for each of the Oracle data types. The ARRAY, STRUCT, REF, BLOB, and CLOB classes correspond to standard JDBC 2.0 interfaces. Oracle Database JDBC Developer's Guide and Reference for information about these classes and Oracle extensions

See Also:



Custom Java classes can map to Oracle objects, which implement ORAData or SQLData, references, which implement ORAData only, collections, which implement ORAData only, OPAQUE types, which implement ORAData only, or other SQL types for customized handling, which implement ORAData only. You can use Oracle JPublisher utility to automatically generate custom Java classes. See Also: "Custom Java Classes" on page 6-4 and "JPublisher and the Creation of Custom Java Classes" on page 6-20

Type Support

5-5

Supported Types for Host Expressions



The Oracle SQLJ implementation has functionality for automatic blank padding when comparing a string to a CHAR column value for a WHERE clause. Otherwise the string would have to be padded to match the number of characters in the database column. This is available as a SQLJ translator option for Oracle-specific code generation, or as an Oracle customizer option for ISO standard code generation. See Also: "CHAR Comparisons with Blank Padding (-fixedchar)" on page 8-46 and "Oracle Customizer CHAR Comparisons with Blank Padding (fixedchar)" on page A-24





Weak types cannot be used for OUT or INOUT parameters. This applies to the STRUCT, REF, and ARRAY Oracle extended types and corresponding standard JDBC 2.0 types, as well as to Oracle OPAQUE types. Using any of the Oracle extensions requires the following: –

Oracle JDBC driver



Oracle-specific code generation or Oracle customization during translation



Oracle SQLJ run time when your application runs

Supported Types and Requirements for JDBC 2.0 As indicated in Table 5–1, the Oracle JDBC and SQLJ implementations support JDBC 2.0 types in the standard java.sql package. This section lists JDBC 2.0 supported types and related Oracle extensions. Table 5–2 lists the JDBC 2.0 types supported by the Oracle SQLJ implementation. You can use them wherever you can use the corresponding Oracle extensions, summarized in the table. The Oracle extensions have been available in prior releases and are still available as well. These oracle.sql.* classes provide functionality to wrap raw SQL data. See Also: Table 5–2

Oracle Database JDBC Developer's Guide and Reference

Correlation between Oracle Extensions and JDBC 2.0 Types

JDBC 2.0 Type

Oracle Extension

java.sql.Blob

oracle.sql.BLOB

java.sql.Clob

oracle.sql.CLOB

java.sql.Struct

oracle.sql.STRUCT

java.sql.Ref

oracle.sql.REF

java.sql.Array

oracle.sql.ARRAY

java.sql.SQLData

NA

NA

oracle.sql.ORAData (_SQL_TYPECODE = OracleTypes.STRUCT)

ORAData functionality is an Oracle-specific alternative to standard SQLData functionality for Java support of user-defined types.

5-6 Oracle Database SQLJ Developer’s Guide and Reference

Supported Types for Host Expressions

"Custom Java Classes" on page 6-4, "Support for BLOB, CLOB, and BFILE" on page 5-21, and "Support for Weakly Typed Objects, References, and Collections" on page 6-57

See Also:

The following JDBC 2.0 types are currently not supported in the Oracle JDBC and SQLJ implementations: ■ ■

JAVA_OBJECT: Represents an instance of a Java type in a SQL column. DISTINCT: A distinct SQL type represented in or retrievable from a basic SQL type. For example, SHOESIZE --> NUMBER. Beginning with Oracle Database 11g, the Oracle SQLJ implementation supports the ISO SQLJ feature of allowing array types for iterator columns. You can declare an iterator that uses java.sql.Array or oracle.sql.ARRAY columns. For example, suppose the following database table is defined:

Note:

CREATE OR REPLACE TYPE arr_type IS VARRAY(20) OF NUMBER; CREATE TABLE arr_type (arr_col1 arr_type, arr_col2 arr_type);

You could define a corresponding iterator type as follows: #sql static iterator MyIter (oracle.sql.ARRAY arr_col1, java.sql.Array arr_col2);

Using PL/SQL BOOLEAN, RECORD Types, and TABLE Types The Oracle SQLJ and JDBC implementations do not support calling arguments or return values of the PL/SQL BOOLEAN type or RECORD types. Support for TABLE Types Oracle JDBC drivers support scalar PL/SQL indexed-by tables. See Also:

Oracle Database JDBC Developer's Guide and Reference

The Oracle SQLJ implementation simplifies the process of writing and retrieving data in scalar indexed-by tables. The following array types are supported: ■



Numeric types: int[], long[], float[], double[], short[], java.math.BigDecimal[], oracle.sql.NUMBER[] Character types: java.lang.String[], oracle.sql.CHAR[]

The following is an example of writing indexed-by table data to the database: int[] vals = {1,2,3}; #sql { call procin(:vals) };

The following is an example of retrieving indexed-by table data from the database: oracle.sql.CHAR[] outvals; #sql { call procout(:OUT outvals/*[111](22)*/) };

You must specify the maximum length of the output array being retrieved, using the [xxx] syntax inside the /*...*/ syntax, as shown. Also, for character-like binds, you can optionally include the (xx) syntax, as shown, to specify the maximum length of an array element in bytes.

Type Support

5-7

Support for Streams

Note: The oracle.sql.Datum class is not supported directly. You must use an appropriate subclass, such as oracle.sql.CHAR or oracle.sql.NUMBER.

Workarounds for Unsupported Types As a workaround for an unsupported type, you can create wrapper procedures that process the data using supported types. For example, to wrap a stored procedure that uses PL/SQL boolean values, you can create a stored procedure that takes a character or number from JDBC and passes it to the original procedure as BOOLEAN, or for an output parameter, accepts a BOOLEAN argument from the original procedure and passes it as a CHAR or NUMBER to JDBC. Similarly, to wrap a stored procedure that uses PL/SQL records, you can create a stored procedure that handles a record in its individual components, such as CHAR and NUMBER. To wrap a stored procedure that uses PL/SQL TABLE types, you can break the data into components or perhaps use Oracle collection types. The following is an example of a PL/SQL wrapper procedure MY_PROC for a stored procedure PROC that takes a BOOLEAN as input: PROCEDURE MY_PROC (n NUMBER) IS BEGIN IF n=0 THEN proc(false); ELSE proc(true); END IF; END; PROCEDURE PROC (b BOOLEAN) IS BEGIN ... END;

When using these unsupported PL/SQL types in method signatures in PL/SQL packages or SQL objects, consider using the Oracle Database 11g JPublisher utility. This facilitates the creation of Java types to call such methods. Refer to "JPublisher and the Creation of Custom Java Classes" on page 6-20 for an overview of JPublisher, and the Oracle Database JPublisher User's Guide for more information. Note:

Support for Streams Standard SQLJ provides the following specialized classes for convenient processing of long data in streams: ■

sqlj.runtime.BinaryStream



sqlj.runtime.CharacterStream

These stream types can be used for iterator columns to retrieve data from the database or for input host variables to send data to the database. As with Java streams in general, these classes allow the convenience of processing and transferring large data items in manageable chunks.

5-8 Oracle Database SQLJ Developer’s Guide and Reference

Support for Streams

This section discusses general use of these classes, Oracle SQLJ extended functionality, and stream class methods. It covers the following topics: ■

General Use of SQLJ Streams



Key Aspects of Stream Support Classes



Using SQLJ Streams to Send Data



Retrieving Data into Streams: Precautions



Using SQLJ Streams to Retrieve Data



Stream Class Methods



Examples of Retrieving and Processing Stream Data



SQLJ Stream Objects as Output Parameters and Function Return Values Starting from JDBC 2.0, the CharacterStream class replaces the AsciiStream and UnicodeStream classes. CharacterStream shelters users from unnecessary logistics regarding encoding.

Note:

General Use of SQLJ Streams Table 5–1 lists the data types you would typically process using these stream classes. To summarize: ■



BinaryStream is typically used for LONG RAW (Types.LONGVARBINARY), but might also be used for RAW (Types.BINARY or Types.VARBINARY). CharacterStream is typically used for LONG (java.sql.Types.LONGVARCHAR), but might also be used for VARCHAR2 (Types.VARCHAR).

Of course, any use of streams is at your discretion. You can use the SQLJ stream types for host variables to either send or retrieve data. As Table 5–1 documents, LONG and VARCHAR2 data can also be manifested in Java String, while RAW and LONGRAW data can also be manifested in Java byte[] arrays. Also, if your database supports large object types, such as BLOB and CLOB, then you may find these to be preferable to types like LONG and LONG RAW, although streams might still be used in extracting data from large objects. The Oracle SQLJ and JDBC implementations support large object types. See Also:

"Support for BLOB, CLOB, and BFILE" on page 5-21

Both SQLJ stream classes are subclasses of standard Java classes, java.io.InputStream for BinaryStream and java.io.Reader for CharacterStream, and act as wrappers to provide the functionality required by SQLJ. This functionality is to communicate to SQLJ the type and length of the underlying data so that it can be processed and formatted properly.

Key Aspects of Stream Support Classes The following abbreviated code illustrates key aspects of the BinaryStream class, such as what it extends, constructor signatures, and key method signatures: public class sqlj.runtime.BinaryStream extends sqlj.runtime.StreamWrapper { public sqlj.runtime.BinaryStream(java.io.InputStream);

Type Support

5-9

Support for Streams

public public public public

sqlj.runtime.BinaryStream(java.io.InputStream,int); java.io.InputStream getInputStream(); int getLength(); void setLength(int);

}

The following abbreviated code illustrates key aspects of the CharacterStream class: public class sqlj.runtime.CharacterStream extends java.io.FilterReader { public sqlj.runtime.CharacterStream(java.io.Reader); public sqlj.runtime.CharacterStream(java.io.Reader,int); public int getLength(); public java.io.Reader getReader(); public void setLength(int); }

Note: ■





The int parameters in the constructors are for data length, in bytes or characters as applicable. For any method that takes a java.io.InputStream object as input, you can use a BinaryStream object instead. Similarly, for any method that takes a java.io.Reader object as input, you can use a CharacterStream object instead. The deprecated AsciiStream and UnicodeStream classes have the same key aspects and signatures as BinaryStream.

Using SQLJ Streams to Send Data Standard SQLJ enables you to use streams as host variables to update the database. A key point in sending a SQLJ stream to the database is that you must somehow determine the length of the data and specify that length to the constructor of the SQLJ stream. You can use a SQLJ stream to send data to the database as follows: 1.

Determine the length of the data.

2.

Create an appropriate standard Java data object for input. For BinaryStream, this would be an input stream, an instance of java.io.InputStream or some subclass. For CharacterStream, this would be a reader object, an instance of java.io.Reader or some subclass.

3.

Create an instance of the appropriate SQLJ stream class depending on the type of data, passing the data object and length to the constructor.

4.

Use the SQLJ stream instance as a host variable in a suitable SQL operation in a SQLJ executable statement.

5.

Close the stream. Although not required, it is recommended that you close the stream after using it.

Note:

5-10 Oracle Database SQLJ Developer’s Guide and Reference

Support for Streams

Updating LONG or LONG RAW from a File This section illustrates how to create a CharacterStream object or a BinaryStream object from a File object and use it to update the database. The code example at the end uses a CharacterStream for a LONG column. In updating a database column from a file, a step is needed to determine the length. You can do this by creating a java.io.File object before you create your input stream. Following are the steps for updating the database from a file: 1.

Create a java.io.File object from your file. You can specify the file path name to the File class constructor.

2.

Use the length() method of the File object to determine the length of the data. This method returns a long value, which you must cast to an int for input to the SQLJ stream class constructor. Note: Before performing this cast, test the long value to ensure that it is not too big to fit into an int variable. The static constant MAX_VALUE in the class java.lang.Integer indicates the largest possible Java int value.

3.

For character data, create a java.io.FileReader object from the File object. You can pass the File object to the FileReader constructor. For binary data, create a java.io.FileInputStream object from the File object. You can pass the File object to the FileInputStream constructor.

4.

Create an appropriate SQLJ stream object. This would be a CharacterStream object for a character file or a BinaryStream object for a binary file. Pass the FileReader or FileInputStream object, as applicable, and the data length as an int to the SQLJ stream class constructor.

5.

Use the SQLJ stream object as a host variable in an appropriate SQL operation in a SQLJ executable statement.

The following is an example of writing LONG data to the database from a file. Presume you have an HTML file in /private/mydir/myfile.html and want to insert the file contents into a LONG column, chardata, in the filetable database table. import java.io.*; import sqlj.runtime.*; ... File myfile = new File ("/private/mydir/myfile.html"); int length = (int)myfile.length(); // Must cast long output to int. FileReader filereader = new FileReader(myfile); CharacterStream charstream = new CharacterStream(filereader, length); #sql { INSERT INTO filetable (chardata) VALUES (:charstream) }; charstream.close(); ...

Updating LONG RAW from a Byte Array This section illustrates how to create a BinaryStream object from a byte array and uses it to update the database.

Type Support 5-11

Support for Streams

You must determine the length of the data before updating the database from a byte array. This is more trivial for arrays than for files, though, because all Java arrays have functionality to return the length. Following are the steps in updating the database from a byte array: 1.

Use the length functionality of the array to determine the length of the data. This returns an int, which is what you will need for the constructor of any of the SQLJ stream classes.

2.

Create a java.io.ByteArrayInputStream object from your array. You can pass the byte array to the ByteArrayInputStream constructor.

3.

Create a BinaryStream object. Pass the ByteArrayInputStream object and data length as an int to the BinaryStream class constructor. The constructor signature is as follows: BinaryStream (InputStream in, int length)

You can use an instance of java.io.InputStream or of any subclass, such as the ByteArrayInputStream class. 4.

Use the SQLJ stream object as a host variable in an appropriate SQL operation in a SQLJ executable statement.

The following is an example of writing LONG RAW data to the database from a byte array. Presume you have a byte array, bytearray[], and you want to insert its contents into a LONG RAW column, BINDATA, in the BINTABLE database table. import java.io.*; import sqlj.runtime.*; ... byte[] bytearray = new byte[100]; (Populate bytearray somehow.) ... int length = bytearray.length; ByteArrayInputStream arraystream = new ByteArrayInputStream(bytearray); BinaryStream binstream = new BinaryStream(arraystream, length); #sql { INSERT INTO bintable (bindata) VALUES (:binstream) }; binstream.close(); ...

It is not necessary to use a stream as in this example. Alternatively, you can update the database directly from a byte array.

Note:

Retrieving Data into Streams: Precautions You can also use the SQLJ stream classes to retrieve data, but the logistics of using streams make certain precautions necessary with some database products. When reading long data and writing it to a stream using Oracle Database 11g and an Oracle JDBC driver, you must be careful in how you access and process the stream data. As Oracle JDBC drivers access data from an iterator row, they must flush any stream item from the communications pipe before accessing the next data item. Even though the stream data is written to a local stream while the iterator row is processed, this stream data will be lost if you do not read it from the local stream before the JDBC 5-12 Oracle Database SQLJ Developer’s Guide and Reference

Support for Streams

driver accesses the next data item. This is because of the manner in which streams must be processed, which is due to their potentially large size and unknown length. Therefore, as soon as your Oracle JDBC driver has accessed a stream item and written it to a local stream variable, you must read and process the local stream before anything else is accessed from the iterator. This is especially problematic in using positional iterators, with their requisite FETCH INTO syntax. With each fetch, all columns are read before any are processed. Therefore, there can be only one stream item and it must be the last item accessed. The precautions you must take can be summarized as follows: ■



When using a positional iterator, you can have only one stream column and it must be the last column. As soon as you have fetched each row of the iterator, writing the stream item to a local input stream variable in the process, you must read and process the local stream variable before advancing to the next row of the iterator. When using a named iterator, you can have multiple stream columns. However, as you process each iterator row, each time you access a stream field, writing the data to a local stream variable in the process, you must read and process the local stream immediately, before reading anything else from the iterator. Furthermore, in processing each row of a named iterator, you must call the column accessor methods in the same order in which the database columns were selected in the query that populated the iterator. As mentioned in the preceding discussion, this is because stream data remains in the communications pipe after the query. If you try to access columns out of order, then the stream data may be skipped over and lost in the course of accessing other columns. Note: ■



Oracle Database 11g and Oracle JDBC drivers do not support use of streams in SELECT INTO statements. Input streams, by default, do not support mark and reset methods. If you pass any arbitrary input stream to the constructor, then the reset method of InputStream class will throw an IOException. So, always ensure that the input stream is in the proper state when passed to the NcharAsciiStream constructor. For example, reset the stream before passing it to NcharAsciiStream if the stream has no more data or if the stream is closed.

Using SQLJ Streams to Retrieve Data To retrieve data as a stream, standard SQLJ enables you to select data into a named or positional iterator that has a column of the appropriate SQLJ stream type. This section covers the basic steps in retrieving data into a SQLJ stream using a positional iterator or a named iterator, taking into account the precautions documented in the preceding section. "Stream Class Methods" on page 5-15 and "Examples of Retrieving and Processing Stream Data" on page 5-17

See Also:

Using a SQLJ Stream Column in a Positional Iterator Use the following steps to retrieve data into a SQLJ stream using a positional iterator: Type Support 5-13

Support for Streams

1.

Declare a positional iterator class with the last column being of the appropriate SQLJ stream type.

2.

Declare a local variable of your iterator type.

3.

Declare a local variable of the appropriate SQLJ stream type. This will be used as a host variable to receive data from each row of the SQLJ stream column of the iterator.

4.

Execute a query to populate the iterator you declared in Step 2.

5.

Process the iterator as usual. Because the host variables in the INTO-list of the FETCH INTO statement must be in the same order as the columns of the positional iterator, the local input stream variable is the last host variable in the list. See Also:

"Using Positional Iterators" on page 4-34

6.

In the iterator processing loop, after each iterator row is accessed, immediately read and process the local input stream, storing or printing the stream data as desired.

7.

Close the local input stream each time through the iterator processing loop.

8.

Close the iterator.

Using SQLJ Stream Columns in a Named Iterator Use the following steps to retrieve data into one or more SQLJ streams using a named iterator: 1.

Declare a named iterator class with one or more columns of appropriate SQLJ stream type.

2.

Declare a local variable of your iterator type.

3.

Declare a local variable of some input stream or reader type for each SQLJ stream column in the iterator. These will be used to receive data from the stream-column accessor methods. These local stream variables need not be of the SQLJ stream types. They can be standard java.io.InputStream or java.io.Reader, as applicable. The local stream variables need not be of the SQLJ stream types, because the data was already correctly formatted as a result of the iterator columns being of appropriate SQLJ stream types.

Note:

4.

Execute a query to populate the iterator you declared in Step 2.

5.

Process the iterator as usual. In processing each row of the iterator, as each stream-column accessor method returns the stream data, write it to the corresponding local input stream variable you declared in Step 3. To ensure that stream data will not be lost, call the column accessor methods in the same order in which columns were selected in the query in Step 4. See Also:

"Using Positional Iterators" on page 4-34

6.

In the iterator processing loop, immediately after calling the accessor method for any stream column and writing the data to a local input stream variable, read and process the local input stream, storing or printing the stream data as desired.

7.

Close the local input stream each time through the iterator processing loop.

5-14 Oracle Database SQLJ Developer’s Guide and Reference

Support for Streams

8.

Close the iterator.

Note: ■



When you populate a SQLJ stream object with data, the length attribute of the stream will not be meaningful. This attribute is meaningful only when you set it explicitly, either using the setLength() method that each SQLJ stream class provides or specifying the length to the constructor. Although not required, it is recommended that you close the local input stream each time through the iterator processing loop.

Stream Class Methods In processing a SQLJ stream column in a named or positional iterator, the local stream variable used to receive the stream data can be either a SQLJ stream type or the standard java.io.InputStream or java.io.Reader type, as applicable. In either case, standard methods of the input data object are supported. If the local stream variable is a SQLJ stream type, BinaryStream or CharacterStream, you have the option of either reading data directly from the SQLJ stream object or retrieving the underlying InputStream or Reader object and reading data from that. This is just a matter of preference. The former approach is simpler. However, the latter approach involves more direct and efficient data access.

Note:

Binary Stream Methods The BinaryStream class is a subclass of the sqlj.runtime.StreamWrapper class. The StreamWrapper class provides the following key methods: ■



InputStream getInputStream(): You can optionally use this method to get the underlying java.io.InputStream object. However, this is not required, because you can also process SQLJ stream objects directly. void setLength(int length): You can use this to set the length attribute of a SQLJ stream object. This is not necessary if you have already set length in constructing the stream object, unless you want to change it for some reason. The length attribute must be set to an appropriate value before you send a SQLJ stream to the database.



int getLength(): This method returns the value of the length attribute of a SQLJ stream. This value is meaningful only if you explicitly set it using the stream object constructor or the setLength() method. When you retrieve data into a stream, the length attribute is not set automatically.

The sqlj.runtime.StreamWrapper class is a subclass of the java.io.FilterInputStream class, which is a subclass of the java.io.InputStream class. The following important methods of the InputStream class are supported by the SQLJ BinaryStream class as well: ■

int read (): Reads the next byte of data from the input stream. The byte of data is returned as an int value in the range 0 to 255. If the end of the stream has Type Support 5-15

Support for Streams

already been reached, then the value -1 is returned. This method blocks program execution until one of the following:











Input data is available



The end of the stream is detected



An exception is thrown

int read (byte b[]): Reads up to b.length bytes of data from the input stream, writing the data into the specified b[] byte array. It returns an int value indicating how many bytes were read, or -1 if the end of the stream has already been reached. This method blocks program execution until input is available. int read (byte b[], int off, int len): Reads up to len bytes of data from the input stream, starting at the byte specified by the offset, off, and writing the data into the specified b[] byte array. It returns an int value indicating how many bytes were read, or -1 if the end of the stream has already been reached. This method blocks until input is available. long skip (long n): Skips over and discards n bytes of data from the input stream. However, in some circumstances, this method will actually skip a smaller number of bytes. It returns a long value indicating the actual number of bytes skipped. void close(): Closes the stream and releases any associated resources.

Character Stream Methods The CharacterStream class provides the following key methods: ■





Reader getReader(): You can optionally use this method to get the underlying java.io.Reader object. However, this is not required, because you can also process SQLJ stream objects directly. void setLength(int length): You can use this method to set the length of the stream object. int getLength(): You can use this method to get the length of the stream object.

The sqlj.runtime.CharacterStream class is a subclass of the java.io.FilterReader class, which is a subclass of the java.io.Reader class. The following important methods of the Reader class are supported by the SQLJ CharacterStream class as well: ■





int read (): Reads the next character of data from the reader. The data is returned as an int value in the range 0 to 65535. If the end of the data has already been reached, then the value -1 is returned. This method blocks program execution until one of the following: –

Input data is available



The end of the data is detected



An exception is thrown

int read (char cbuf[]): Reads characters into an array, writing the data into the specified cbuf[] char array. It returns an int value indicating how many characters were read, or -1 if the end of the data has already been reached. This method blocks program execution until input is available. int read (char cbuf[], int off, int len): Reads up to len characters of data from the input, starting at the character specified by the offset, off, and

5-16 Oracle Database SQLJ Developer’s Guide and Reference

Support for Streams

writing the data into the specified char[] char array. It returns an int value indicating how many characters were read, or -1 if the end of the data has already been reached. This method blocks until input is available. ■



long skip (long n): Skips over and discards n characters of data from the input. However, in some circumstances, this method will actually skip a smaller number of characters. It returns a long value indicating the actual number of characters skipped. void close(): Closes the stream and releases any associated resources.

Examples of Retrieving and Processing Stream Data This section provides examples of various scenarios of retrieving stream data, as follows: ■



Using a SELECT statement to select data from a LONG column and populate a SQLJ CharacterStream column in a named iterator, as shown in Example 5–1 Using a SELECT statement to select data from a LONG RAW column and populate a SQLJ BinaryStream column in a positional iterator, as shown in Example 5–2

Example 5–1 Selecting LONG Data into CharacterStream Column of Named Iterator

This example selects data from a LONG database column, populating a SQLJ CharacterStream column in a named iterator. Assume there is a table named FILETABLE with a VARCHAR2 column called FILENAME that contains file names and a LONG column called FILECONTENTS that contains file contents in character format. The code is as follows: import sqlj.runtime.*; import java.io.*; ... #sql iterator MyNamedIter (String filename, CharacterStream filecontents); ... MyNamedIter namediter = null; String fname; CharacterStream charstream; #sql namediter = { SELECT filename, filecontents FROM filetable }; while (namediter.next()) { fname = namediter.filename(); charstream = namediter.filecontents(); System.out.println("Contents for file " + fname + ":"); printStream(charstream); charstream.close(); } namediter.close(); ... public void printStream(Reader in) throws IOException { int character; while ((character = in.read()) != -1) { System.out.print((char)character); } }

Remember that you can pass a SQLJ character stream to any method that takes a standard java.io.Reader as an input parameter.

Type Support 5-17

Support for Streams

Example 5–2 : Selecting LONG RAW Data into BinaryStream Column of Positional Iterator

This example selects data from a LONG RAW column, populating a SQLJ BinaryStream column in a positional iterator. As explained in the preceding section, there can be only one stream column in a positional iterator and it must be the last column. Assume there is a table named BINTABLE with a NUMBER column called IDENTIFIER and a LONG RAW column called BINDATA that contains binary data associated with the identifier. The code is as follows: import sqlj.runtime.*; ... #sql iterator MyPosIter (int, BinaryStream); ... MyPosIter positer = null; int id=0; BinaryStream binstream=null; #sql positer = { SELECT identifier, bindata FROM bintable }; while (true) { #sql { FETCH :positer INTO :id, :binstream }; if (positer.endFetch()) break; (...process data as desired...) binstream.close(); } positer.close(); ...

SQLJ Stream Objects as Output Parameters and Function Return Values As described in the preceding sections, standard SQLJ supports the use of the BinaryStream and CharacterStream classes in the sqlj.runtime package for retrieval of stream data into iterator columns. In addition, the Oracle SQLJ implementation enables the following uses of the SQLJ stream types if you use Oracle9i Database or later version, an Oracle JDBC driver, Oracle-specific code generation or Oracle customizer, and Oracle SQLJ run time: ■



They can appear as OUT or INOUT host variables from a stored procedure or function call. They can appear as the return value from a stored function call.

Streams as Stored Procedure Output Parameters You can use the BinaryStream and CharacterStream types as the assignment type for a stored procedure or stored function OUT or INOUT parameter. Assume the following table definition: CREATE TABLE streamexample (name VARCHAR2 (256), data LONG); INSERT INTO streamexample (data, name) VALUES ('0000000000111111111112222222222333333333344444444445555555555', 'StreamExample');

5-18 Oracle Database SQLJ Developer’s Guide and Reference

Support for Streams

Also, presume the following stored procedure definition, which uses the STREAMEXAMPLE table: CREATE OR REPLACE PROCEDURE out_longdata (dataname VARCHAR2, longdata OUT LONG) IS BEGIN SELECT data INTO longdata FROM streamexample WHERE name = dataname; END out_longdata;

The following sample code uses a call to the out_longdata stored procedure to read the long data: import sqlj.runtime.*; ... CharacterStream data; #sql { CALL out_longdata('StreamExample', :OUT data) }; int c; while ((c = data.read ()) != -1) System.out.print((char)c); System.out.flush(); data.close(); ...

Note:

Closing the stream is recommended, but not required.

Streams as Stored Function Results You can use the BinaryStream and CharacterStream types as the assignment type for a stored function return result. Assume the same STREAMEXAMPLE table definition as in the preceding stored procedure example. Also, assume the following stored function definition, which uses the STREAMEXAMPLE table: CREATE OR REPLACE FUNCTION get_longdata (dataname VARCHAR2) RETURN long IS longdata LONG; BEGIN SELECT data INTO longdata FROM streamexample WHERE name = dataname; RETURN longdata; END get_longdata;

The following sample code uses a call to the get_longdata stored function to read the long data: import sqlj.runtime.*; ... CharacterStream data; #sql data = { VALUES(get_longdata('StreamExample')) }; int c; while ((c = data.read ()) != -1) System.out.print((char)c); System.out.flush(); data.close(); ...

Type Support 5-19

Support for JDBC 2.0 LOB Types and Oracle Type Extensions

Note:

Closing the stream is recommended, but not required.

Support for JDBC 2.0 LOB Types and Oracle Type Extensions The Oracle SQLJ implementation offers extended functionality for the following JDBC 2.0 and Oracle-specific data types: ■

JDBC 2.0 large object (LOB) types (BLOB and CLOB)



Oracle BFILE type



Oracle ROWID type



Oracle REF CURSOR types



Other Oracle Database 11g data types, such as NUMBER and RAW

These data types are supported by classes in the oracle.sql package. LOBs and binary files (BFILEs) are handled similarly in many ways, so are discussed together. Additionally, the Oracle SQLJ implementation offers extended support for the standard BigDecimal JDBC type. JDBC 2.0 functionality for user-defined SQL objects, object references, and collections are also supported. See Also:

Chapter 6, "Objects, Collections, and OPAQUE Types"

Note that using Oracle extensions in your code requires the following: ■ ■



Use one of Oracle JDBC drivers. Use Oracle-specific code generation or for ISO code generation, customize the profiles appropriately. The default customizer, oracle.sqlj.runtime.util.OraCustomizer, is recommended. Use Oracle SQLJ run time when your application runs.

Oracle SQLJ run time and an Oracle JDBC driver are required whenever you use Oracle customizer, even if you do not actually use Oracle extensions in your code. For Oracle-specific semantics-checking, you must use an appropriate checker. The default checker, oracle.sqlj.checker.OracleChecker, acts as a front end and will run the appropriate checker based on your environment. This will be one of the Oracle specific checkers if you are using an Oracle JDBC driver. This section covers the following topics: ■

Package oracle.sql



Support for BLOB, CLOB, and BFILE



Support for Oracle ROWID



Support for Oracle REF CURSOR Types



Support for Other Oracle Database 11g Data Types



Extended Support for BigDecimal

Package oracle.sql SQLJ users, as well as JDBC users, should be aware of the oracle.sql package, which includes classes to support all the Oracle Database 11g data types, such as

5-20 Oracle Database SQLJ Developer’s Guide and Reference

Support for JDBC 2.0 LOB Types and Oracle Type Extensions

oracle.sql.ROWID, oracle.sql.CLOB, and oracle.sql.NUMBER. The oracle.sql classes are wrappers for the raw SQL data and provide appropriate mappings and conversion methods to Java formats. An oracle.sql.* object contains a binary representation of the corresponding SQL data in the form of a byte array. Each oracle.sql.* data type class is a subclass of the oracle.sql.Datum class. For Oracle-specific semantics-checking, you must use an appropriate checker. The default checker, oracle.sqlj.checker.OracleChecker, acts as a front end and will run the appropriate checker based on your environment. This will be one of the Oracle specific checkers if you are using an Oracle JDBC driver. See Also: ■

"Connection Options" on page 8-25



"Semantics-Checking and Offline-Parsing Options" on page 8-56



Oracle Database JDBC Developer's Guide and Reference

Support for BLOB, CLOB, and BFILE The Oracle SQLJ and JDBC implementations support JDBC 2.0 LOB types and provide similar support for the Oracle specific BFILE type (read-only binary files stored outside the database). These data types are supported by the following classes: ■

oracle.sql.BLOB



oracle.sql.CLOB



oracle.sql.BFILE

These classes can be used in Oracle-specific SQLJ applications in the following ways: ■

As IN, OUT, or INOUT host variables in executable SQLJ statements and in INTO-lists



As return values from stored function calls



As column types in iterator declarations Oracle Database JDBC Developer's Guide and Reference for more information about LOBs and BFILEs and use of supported stream APIs.

See Also:

You can manipulate LOBs by using methods defined in the BLOB and CLOB classes, which is recommended, or by using the procedures and functions defined in the DBMS_LOB PL/SQL package. All procedures and functions defined in this package can be called by SQLJ programs. You can manipulate BFILEs by using methods defined in the BFILE class, which is recommended, or by using the file-handling routines of the DBMS_LOB package. Using methods of the BLOB, CLOB, and BFILE classes in a Java application is more convenient than using the DBMS_LOB package and may also lead to faster execution in some cases. Note that the type of the chunk being read or written depends on the kind of LOB being manipulated. For example, character large objects (CLOBs) contain character data and, therefore, Java strings are used to hold chunks of data. Binary large objects (BLOBs) contain binary data and, therefore, Java byte arrays are used to hold chunks of data.

Type Support 5-21

Support for JDBC 2.0 LOB Types and Oracle Type Extensions

The DBMS_LOB package requires a round trip to the server. Methods in the BLOB, CLOB, and BFILE classes may also result in a round trip to the server. Note:

BFILE Class versus DBMS_LOB Functionality for BFILEs Example 5–3 and Example 5–4 contrast use of the oracle.sql methods with use of the DBMS_LOB package for BFILEs: Example 5–3 Use of oracle.sql.BFILE File-Handling Methods with BFILE

This example manipulates a BFILE using file-handling methods of the oracle.sql.BFILE class. BFILE openFile (BFILE file) throws SQLException { String dirAlias, name; dirAlias = file.getDirAlias(); name = file.getName(); System.out.println("name: " + dirAlias + "/" + name); if (!file.isFileOpen()) { file.openFile(); } return file; }

The BFILE getDirAlias() and getName() methods construct the full path and file name. The openFile() method opens the file. You cannot manipulate BFILEs until they have been opened. Example 5–4 Use of DBMS_LOB File-Handling Routines with BFILE

This example manipulates a BFILE using file-handling routines of the DBMS_LOB package. BFILE openFile(BFILE file) throws SQLException { String dirAlias, name; #sql { CALL dbms_lob.filegetname(:file, :out dirAlias, :out name) }; System.out.println("name: " + dirAlias + "/" + name); boolean isOpen; #sql isOpen = { VALUES(dbms_lob.fileisopen(:file)) }; if (!isOpen) { #sql { CALL dbms_lob.fileopen(:inout file) }; } return file; }

The openFile() method prints the name of a file object and then returns an opened version of the file. Note that BFILEs can be manipulated only after being opened with a call to DBMS_LOB.FILEOPEN or equivalent method in the BFILE class.

5-22 Oracle Database SQLJ Developer’s Guide and Reference

Support for JDBC 2.0 LOB Types and Oracle Type Extensions

BLOB and CLOB Classes versus DBMS_LOB Functionality for LOBs Example 5–5 and Example 5–6 contrast use of the oracle.sql methods with use of the DBMS_LOB package for BLOBs, and Example 5–7 and Example 5–8 contrast use of the oracle.sql methods with use of the DBMS_LOB package for CLOBs. Example 5–5 Example: Use of oracle.sql.CLOB Read Methods with CLOB

This example reads data from a CLOB using methods of the oracle.sql.CLOB class. void readFromClob(CLOB clob) throws SQLException { long clobLen, readLen; String chunk; clobLen = clob.length(); for (long i = 0; i < clobLen; i+= readLen) { chunk = clob.getSubString(i, 10); readLen = chunk.length(); System.out.println("read " + readLen + " chars: " + chunk); } }

This method contains a loop that reads from the CLOB and returns a 10-character Java string each time. The loop continues until the entire CLOB has been read. Example 5–6 Example: Use of DBMS_LOB Read Routines with CLOB

This example uses routines of the DBMS_LOB package to read from a CLOB. void readFromClob(CLOB clob) throws SQLException { long clobLen, readLen; String chunk; #sql clobLen = { VALUES(dbms_lob.getlength(:clob)) }; for (long i = 1; i

Enter an employee number: 30000 };

You can subsequently use different execution context instances with myConnCtx or different connection context instances with myExecCtx. You can optionally specify an execution context instance while using the default connection context instance, as follows: #sql [myExecCtx] { DELETE FROM emp WHERE sal > 30000 };

Advanced Language Features 7-25

Execution Contexts

Note: ■





If you specify a connection context instance without an execution context instance, then the default execution context instance of that connection context instance is used. If you specify an execution context instance without a connection context instance, then the execution context instance is used with the default connection context instance of your application. If you specify no connection context instance and no execution context instance, then SQLJ uses the default connection and its default execution context instance.

Execution Context Synchronization ExecutionContext methods are all synchronized methods. Therefore, for ISO standard code generation, anytime a statement tries to use an execution context instance already in use, the second statement will be blocked until the first statement completes. In a client application, this typically involves multithreading situations. A thread that tries to use an execution context instance currently in use by another thread will be blocked. To avoid such blockage, you must specify a separate execution context instance for each thread that you use. See Also:

"Multithreading in SQLJ" on page 7-31

The preceding discussion does not apply for default Oracle-specific code generation. For performance reasons, SQLJ performs no additional synchronization against ExecutionContext instances for Oracle-specific generated code. Therefore, you are responsible for ensuring that the same execution context instance will not be used by more than one thread. If multiple threads use the same execution context, then your application, rather than blocking, will experience errors such as incorrect results or NullPointer exceptions. Another exception to the discussion is for recursion, which is encountered only in the server. Multiple SQLJ statements in the same thread are allowed to simultaneously use the same execution context instance if this situation results from recursive calls. An example of this is where a SQLJ stored procedure or function has a call to another SQLJ stored procedure or function. If both use the default execution context instance, as is typical, then the SQLJ statements in the second procedure will use this execution context while the SQLJ call statement from the first procedure is also still using it. This is allowed. See Also:

"Recursive SQLJ Calls in the Server" on page 11-18

Execution Context Methods The following sections list public methods of the ExecutionContext class and provide an example: ■

Status Methods



Control Methods



Cancellation Method

7-26 Oracle Database SQLJ Developer’s Guide and Reference

Execution Contexts



Update Batching Methods



Savepoint Methods



Close Method



Example: Using ExecutionContext Methods

Status Methods Use the following methods of an execution context instance to obtain status information about the most recent SQL operation that completed using that instance: ■



SQLWarning getWarnings(): Returns a java.sql.SQLWarning object containing the first warning reported by the most recent SQL operation that completed using this execution context instance. Warnings are returned in a chain. Use the getWarnings() method of the execution context instance to get the first warning, then use the getNextWarning() method of each SQLWarning object to get the next warning. The chain contains all warnings generated during the execution of the SQL operation. int getUpdateCount(): Except when update batching is enabled, this returns an int value specifying the number of rows updated by the last SQL operation that completed using this execution context instance. Zero (0) is returned if the last SQL operation was not a data manipulation language (DML) statement. The QUERY_COUNT constant is returned, if the last SQL operation produced an iterator or result set. The EXCEPTION_COUNT constant is returned, if the last SQL operation terminated before completing execution or if no operation has yet been attempted using this execution context instance. For batch-enabled applications, the value returned by getUpdateCount() would be one of several batch-related constant values: NEW_BATCH_COUNT, ADD_BATCH_COUNT, or EXEC_BATCH_COUNT. See Also:

"Execution Context Update Counts" on page 10-12

Control Methods Use the following methods of an execution context instance to control the operation of future SQL operations executed using that instance (operations that have not yet started): ■

int getMaxFieldSize(): Returns an int value specifying the maximum amount of data (in bytes) that would be returned from a SQL operation subsequently, using this execution context instance. This applies only to columns of the BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR, or LONGVARCHAR type. By default this parameter is set to 0, meaning there is no size limit.





setMaxFieldSize(int): Takes an int value as input to modify the maximum field-size. int getMaxRows(): Returns an int value specifying the maximum number of rows that can be contained by any SQLJ iterator or JDBC result set created using this execution context instance. If the limit is exceeded, then the excess rows are silently dropped without any error report or warning. By default, this parameter is set to 0, meaning there is no row limit.



setMaxRows(int): Takes an int value as input to modify the maximum row value.

Advanced Language Features 7-27

Execution Contexts



int getQueryTimeout(): Returns an int value specifying the timeout interval, in seconds, for any SQL operation that uses this execution context instance. If a SQL operation exceeds this limit, then a SQL exception is thrown. By default, this parameter is set to 0, meaning there is no query timeout limit.











setQueryTimeout(int): Takes an int value as input to modify the query timeout limit. int getFetchSize(): Retrieves the number of rows that is the current fetch size for iterator objects generated from this ExecutionContext object. If this ExecutionContext object has not set a fetch size by calling setFetchSize(), then the value returned is 0. If this ExecutionContext object has set a non-negative fetch size by calling the method setFetchSize(), then the return value is the fetch size specified on setFetchSize(). setFetchSize(int): Gives the SQLJ run time a hint as to the number of rows that should be fetched when more rows are needed. The number of rows specified affects only iterator objects created using this ExecutionContext object. Specifying zero means that an implementation-dependent default value will be used for the fetch size. int getFetchDirection(): Retrieves the default direction for fetching data, for scrollable iterator objects that are generated from this ExecutionContext object. If this ExecutionContext object has not set a fetch direction by calling the method setFetchDirection(), then the return value is FETCH_FORWARD. setFetchDirection(int): Gives the SQLJ run time a hint as to the direction in which rows of scrollable iterator objects are processed. The hint applies only to scrollable iterator objects that are created using this ExecutionContext object. The default value is: sqlj.runtime.ResultSetIterator.FETCH_FORWARD.

This method throws a SQLException if the given direction is not one of FETCH_FORWARD, FETCH_REVERSE, or FETCH_UNKNOWN (int constants).

Cancellation Method Use the following method to cancel SQL operations in a multithreading environment or to cancel a pending statement batch if update batching is enabled: ■

cancel(): In a multithreading environment, use this method in one thread to cancel a SQL operation currently executing in another thread. It cancels the most recent operation that has started but not completed, using this execution context instance. This method has no effect if no statement is currently being executed using this execution context instance. In a batch-enabled environment, use this to cancel a pending statement batch. The batch is emptied, and none of the statements in the batch are executed. After you cancel a batch, the next batchable statement encountered will be added to a new batch. See Also:

"Canceling a Batch" on page 10-12

Update Batching Methods Use the following methods to control update batching if you want your application to use that performance enhancement feature: ■

int[] executeBatch(): Executes the pending statement batch, returning an array of int update counts.

7-28 Oracle Database SQLJ Developer’s Guide and Reference

Execution Contexts

"Execution Context Update Counts" on page 10-12, "Explicit and Implicit Batch Execution" on page 10-10, and "Error Conditions During Batch Execution" on page 10-16

See Also:



int getBatchLimit(): Returns an int value indicating the current batch limit. If there is a batch limit, then a pending batch is implicitly executed once it contains that number of statements. By default, the batch limit is set to the ExecutionContext static constant value UNLIMITED_BATCH, meaning there is no batch limit. See Also:



int[] getBatchUpdateCounts(): Returns an array of int update counts for the last batch executed. This method is useful in situations where the batch was executed implicitly. See Also:



"Setting a Batch Limit" on page 10-13

"Execution Context Update Counts" on page 10-12

boolean isBatching(): Returns a boolean value indicating whether update batching is enabled. This does not indicate whether there is currently a pending batch, but you can use the getUpdateCount() method to see whether a batch has been newly created, added to, or executed.



setBatching(boolean): Takes a boolean value to enable update batching. Update batching is disabled by default. See Also: "Enabling and Disabling Statement Caching (Oracle-Specific Code)" on page 10-5



setBatchLimit(int): Takes a positive, nonzero int value as input to set the current batch limit. Two special values you can assign are UNLIMITED_BATCH, which means there is no limit, and AUTO_BATCH, which lets the SQLJ run time dynamically determine a batch limit. See Also:

"Update Batching" on page 10-9

Savepoint Methods The Oracle SQLJ implementation supports JDBC 3.0 savepoints. Savepoints are stored in the ExecutionContext instance, and the following public methods exist to support the SQLJ savepoint statements: ■

Object oracleSetSavepoint(ConnectionContextImpl, String) Register a savepoint and return the savepoint as an Object instance. This method takes the connection context as an instance of the sqlj.runtime.ref.ConnectionContextImpl class and a string that specifies the savepoint name. The Oracle SQLJ implementation instantiates a savepoint as an instance of the oracle.jdbc.OracleSavepoint class, which extends the java.sql.Savepoint interface. The Savepoint interface requires Java Development Kit (JDK) 1.4. Oracle uses an Object instance for this method to avoid the JDK 1.4 requirement.

Advanced Language Features 7-29

Execution Contexts



void oracleRollbackToSavepoint (ConnectionContextImpl, Object) Roll back changes to the specified savepoint. This method takes the connection context as an instance of ConnectionContextImpl and the savepoint as an Object instance.



void oracleReleaseSavepoint(ConnectionContextImpl, Object) Release the specified savepoint. This method takes the connection context as an instance of ConnectionContextImpl and the savepoint as an Object instance.

You will generally use SQLJ savepoint statements instead of using these methods directly.

Close Method The Oracle SQLJ implementation provides extended functionality with a close() method for the ExecutionContext class: ■

close(): To avoid resource leakage, use this method if the following circumstances are all true: –

You are using the Oracle-specific code generation.



You explicitly created and used the ExecutionContext instance, instead of using the default instance available through the connection context instance.



You are not issuing SQLJ rollback or commit statements explicitly using the ExecutionContext instance: #sql [ec] { COMMIT }; #sql [ec] { ROLLBACK };



You are not calling executeBatch() on the ExecutionContext instance.

Under this set of circumstances, a batchable statement might remain open on the ExecutionContext instance and over time you may run out of database cursors. To avoid this, use the close() method as in the following example: Execution Context ec = new ExecutionContext(); ... try { ... #sql [ec] { SQL operation }; ... } finally { ec.close(); }

When an execution context instance is associated with a connection context instance, instead of being declared explicitly, then closing the connection context instance, with or without closing the underlying JDBC connection, will automatically close any statement remaining on the execution context instance.

Note:

Example: Using ExecutionContext Methods The following code demonstrates the use of some ExecutionContext methods: ExecutionContext execCtx = DefaultContext.getDefaultContext().getExecutionContext();

7-30 Oracle Database SQLJ Developer’s Guide and Reference

Multithreading in SQLJ

// Wait only 3 seconds for operations to complete execCtx.setQueryTimeout(3); // delete using execution context of default connection context #sql { DELETE FROM emp WHERE sal > 10000 }; System.out.println ("removed " + execCtx.getUpdateCount() + " employees");

Relation of Execution Contexts to Multithreading Do not use multiple threads with a single execution context. If you do, and two SQLJ statements try to use the same execution context simultaneously, then the second statement will be blocked until the first statement completes. Furthermore, status information from the first operation will likely be overwritten before it can be retrieved. Therefore, if you are using multiple threads with a single connection context instance, then you should take the following steps: 1.

Instantiate a unique execution context instance for use with each thread.

2.

Specify execution contexts with your #sql statements so that each thread uses its own execution context.

If you are using a different connection context instance with each thread, then no instantiation and specification of execution context instances is necessary, because each connection context instance implicitly has its own default execution context instance. For performance reasons, SQLJ performs no additional synchronization against ExecutionContext instances for Oracle-specific generated code. Therefore, you are responsible for ensuring that the same execution context instance will not be used by more than one thread. If multiple threads use the same execution context, then your application, rather than blocking, will experience errors such as incorrect results or NullPointer exceptions.

Note:

Multithreading in SQLJ This section discusses SQLJ support and requirements for multithreading and the relation between multithreading and execution context instances. You can use SQLJ in writing multithreaded applications. However, any use of multithreading in your SQLJ application is subject to the limitations of your JDBC driver or proprietary database access vehicle. This includes any synchronization limitations. You are required to use a different execution context instance for each thread. You can accomplish this in one of two ways: ■



Specify connection context instances for your SQLJ statements such that a different connection context instance is used for each thread. Each connection context instance automatically has its own default execution context instance. If you are using the same connection context instance with multiple threads, then declare additional execution context instances and specify execution context

Advanced Language Features 7-31

Multithreading in SQLJ

instances for your SQLJ statements such that a different execution context instance is used for each thread. See Also: "Specifying Connection Context Instances and Execution Context Instances" on page 4-10

If you are using one of Oracle JDBC drivers, then multiple threads can use the same connection context instance, if desired, as long as different execution context instances are specified and there are no synchronization requirements directly visible to you. However, note that data access is sequential. Only one thread is accessing data at any given time. Synchronization refers to the control flow of the various stages of the SQL operations executing through your threads. For example, each statement can bind input parameters, then execute, and then bind output parameters. With some JDBC drivers, special care must be taken not to intermingle these stages. For ISO standard code generation, if a thread attempts to execute a SQL operation that uses an execution context that is in use by another operation, then the thread is blocked until the current operation completes. If an execution context were shared between threads, then the results of a SQL operation performed by one thread would be visible in the other thread. If both threads were executing SQL operations, then a race condition might occur. The results of an execution in one thread might be overwritten by the results of an execution in the other thread before the first thread had processed the original results. This is why multiple threads are not allowed to share an execution context instance. The preceding paragraph does not apply if you use default Oracle-specific code generation. For performance reasons, SQLJ performs no additional synchronization against ExecutionContext instances for Oracle-specific generated code. Therefore, you are responsible for ensuring that the same execution context instance will not be used by more than one thread. If multiple threads use the same execution context, then your application, rather than blocking, will experience errors such as incorrect results or NullPointer exceptions.

Note:

Multithreading: MultiThreadDemo.sqlj The following is an example of a SQLJ application using multithreading. A ROLLBACK operation is executed before closing the connection, so the data is not permanently altered. import java.sql.SQLException; import java.util.Random; import sqlj.runtime.ExecutionContext; import oracle.sqlj.runtime.Oracle; /** Each instance of MultiThreadDemo is a thread that gives all employees a raise of some ammount when run. The main program creates two such instances and computes the net raise after both threads have completed. **/ class MultiThreadDemo extends Thread { double raise; static Random randomizer = new Random(); public static void main (String args[]) {

7-32 Oracle Database SQLJ Developer’s Guide and Reference

Iterator Class Implementation and Advanced Functionality

try { // set the default connection to the URL, user, and password // specified in your connect.properties file Oracle.connect(MultiThreadDemo.class, "connect.properties"); double avgStart = calcAvgSal(); MultiThreadDemo t1 = new MultiThreadDemo(250.50); MultiThreadDemo t2 = new MultiThreadDemo(150.50); t1.start(); t2.start(); t1.join(); t2.join(); double avgEnd = calcAvgSal(); System.out.println("average salary change: " + (avgEnd - avgStart)); } catch (Exception e) { System.err.println("Error running the example: " + e); } try { #sql { ROLLBACK }; Oracle.close(); } catch (SQLException e) { } } static double calcAvgSal() throws SQLException { double avg; #sql { SELECT AVG(sal) INTO :avg FROM emp }; return avg; } MultiThreadDemo(double raise) { this.raise = raise; } public void run() { // Since all threads will be using the same default connection // context, each run uses an explicit execution context instance to // avoid conflict during execution try { delay(); ExecutionContext execCtx = new ExecutionContext(); #sql [execCtx] { UPDATE EMP SET sal = sal + :raise }; int updateCount = execCtx.getUpdateCount(); System.out.println("Gave raise of " + raise + " to " + updateCount + " employees"); } catch (SQLException e) { System.err.println("error updating employees: " + e); } } // delay is used to introduce some randomness into the execution order private void delay() { try { sleep((long)Math.abs(randomizer.nextInt()/10000000)); } catch (InterruptedException e) {} } }

Iterator Class Implementation and Advanced Functionality This section discusses how iterator classes are implemented and what additional functionality is available beyond the essential methods. The following topics are covered:

Advanced Language Features 7-33

Iterator Class Implementation and Advanced Functionality



Implementation and Functionality of Iterator Classes



Using the IMPLEMENTS Clause in Iterator Declarations



Support for Extending Iterator Classes



Result Set Iterators



Scrollable Iterators

Implementation and Functionality of Iterator Classes Any named iterator class you declare will be generated by the SQLJ translator to implement the sqlj.runtime.NamedIterator interface. Classes implementing the NamedIterator interface have functionality that maps iterator columns to database columns by name, not by position. Any positional iterator class you declare will be generated by the SQLJ translator to implement the sqlj.runtime.PositionedIterator interface. Classes implementing the PositionedIterator interface have functionality that maps iterator columns to database columns by position, not by name. Both the NamedIterator interface and the PositionedIterator interface, and therefore all generated SQLJ iterator classes as well, implement or extend the sqlj.runtime.ResultSetIterator interface. The ResultSetIterator interface specifies the following methods for all SQLJ iterators: ■ ■

■ ■

close(): Closes the iterator. ResultSet getResultSet(): Extracts the underlying JDBC result set from the iterator. boolean isClosed(): Determines if the iterator has been closed. boolean next(): Moves to the next row of the iterator, returning true if there is a valid next row to go to.

The PositionedIterator interface adds the following method specification for positional iterators: ■

boolean endFetch(): Determines if you have reached the last row of a positional iterator.

Use the next() method to advance through the rows of a named iterator and accessor methods to retrieve the data. The SQLJ generation of a named iterator class defines an accessor method for each iterator column, where each method name is identical to the corresponding column name. For example, if you declare a name column, then a name() method will be generated. Use a FETCH INTO statement together with the endFetch() method to advance through the rows of a positional iterator and retrieve the data. A FETCH INTO statement implicitly calls the next() method. Do not explicitly use the next() method in a positional iterator unless you are using the special FETCH CURRENT syntax. The FETCH INTO statement also implicitly calls accessor methods that are named according to iterator column numbers. The SQLJ generation of a positional iterator class defines an accessor method for each iterator column, where each method name corresponds to the column position. See Also: "FETCH CURRENT Syntax: from JDBC Result Sets to SQLJ Iterators" on page 7-40

7-34 Oracle Database SQLJ Developer’s Guide and Reference

Iterator Class Implementation and Advanced Functionality

Use the close() method to close any iterator once you are done with it. The getResultSet() method is central to SQLJ-JDBC interoperability. See Also: "SQLJ Iterator and JDBC Result Set Interoperability" on page 7-48

Alternatively, you can use a ResultSetIterator instance or a ScrollableResultSetIterator instance directly as a weakly typed iterator. (ScrollableResultSetIterator extends ResultSetIterator.) This is convenient if you are interested only in converting it to a JDBC result set and you do not need named or positional iterator functionality. You can also access it through SQLJ FETCH CURRENT syntax. Note:

Using the IMPLEMENTS Clause in Iterator Declarations There may be situations where it will be useful to implement an interface in your iterator declaration. For example, you may have an iterator class where you want to restrict access to one or more columns. A named iterator class generated by SQLJ has an accessor method for each column in the iterator. If you want to restrict access to certain columns, you can create an interface with only a subset of the accessor methods, then expose instances of the interface type to the user instead of exposing instances of the iterator class type. For example, assume you are creating a named iterator of employee data, with columns ENAME (employee name), EMPNO (employee number), and SAL (salary). Accomplish this as follows: #sql iterator EmpIter (String ename, int empno, float sal);

This generates a class EmpIter with ename(), empno(), and sal() accessor methods. Assume, though, that you want to prevent access to the SAL column. You can create an EmpIterIntfc interface that has ename() and empno() methods, but no sal() method. Then you can use the following iterator declaration instead of the preceding declaration (presuming EmpIterIntfc is in the mypackage package): #sql iterator EmpIter implements mypackage.EmpIterIntfc (String emame, int empno, float sal);

Then if you code your application so that users can access data only through EmpIterIntfc instances, then they will not have access to the SAL column.

Support for Extending Iterator Classes SQLJ supports the ability to extend iterator classes. This feature can be very useful in allowing you to add functionality to your queries and query results. The one key requirement of an iterator subclass is that you must supply a public constructor that takes an instance of sqlj.runtime.RTResultSet as input. The SQLJ run time will call this constructor in assigning query results to an instance of your subclass. Beyond that, you provide functionality as you choose. You can continue to use functionality of the original iterator class (the superclass of your subclass). For example, you can advance through query results by calling the super.next() method.

Advanced Language Features 7-35

Iterator Class Implementation and Advanced Functionality

Result Set Iterators You may have situations where you do not require the strongly typed functionality of a SQLJ iterator. For such circumstances, you can directly use instances of the sqlj.runtime.ResultSetIterator type to receive query data, so that you are not required to declare a named or positional iterator class. Alternatively, you can use the sqlj.runtime.ScrollableResultSetIterator type, which extends ResultSetIterator. This enables you to use SQLJ scrollable iterator functionality. In using a result set iterator instead of a strongly typed iterator, you are trading the strong type-checking of the SQLJ SELECT operation for the convenience of not having to declare an iterator class. The ResultSetIterator interface underlies all named and positional iterator classes and specifies the getResultSet() and close() methods. If you want to use SQLJ to process a result set iterator instance, then use a ScrollableResultSetIterator instance and the FETCH CURRENT syntax. See Also: "FETCH CURRENT Syntax: from JDBC Result Sets to SQLJ Iterators" on page 7-40

If you want to use JDBC to process a result set iterator instance, you can use its getResultSet() method and then process the underlying result set that you retrieve. If you process a result set iterator through its underlying result set, you should close the result set iterator, not the result set, when you are finished. Closing the result set iterator will also close the result set, but closing the result set will not close the result set iterator. See Also: "Using and Converting Weakly Typed Iterators (ResultSetIterator)" on page 7-50

The Oracle SQLJ implementation supports result set iterators for use as host expressions and to represent cursors in FETCH statements. This functionality was not supported prior to Oracle9i Database.

Note:

Scrollable Iterators The ISO standard for SQLJ supports scrollable iterators, with functionality being patterned after the JDBC 2.0 specification for scrollable JDBC result sets. The Oracle SQLJ implementation supports this functionality. See Also:

Oracle Database JDBC Developer's Guide and Reference

Declaring Scrollable Iterators To characterize an iterator as scrollable, add the following clause to the iterator declaration: implements sqlj.runtime.Scrollable

This instructs the SQLJ translator to generate an iterator that implements the Scrollable interface. Following is an example of a declaration of a named, scrollable iterator: #sql public static MyScrIter implements sqlj.runtime.Scrollable (String ename, int empno);

7-36 Oracle Database SQLJ Developer’s Guide and Reference

Iterator Class Implementation and Advanced Functionality

The code that the SQLJ translator generates for the MyScrIter class will automatically support all the methods of the Scrollable interface. Scrollable Iterator Sensitivity You can declare scrollable iterators, like scrollable result sets, to have sensitivity to changes to the underlying data. By default, scrollable iterators in the Oracle SQLJ implementation have a sensitivity setting of INSENSITIVE, meaning they do not detect any such changes in the underlying data. However, you can use a with clause to alter this setting. The following example expands an earlier example to specify sensitivity: #sql public static MyScrIter implements sqlj.runtime.Scrollable with (sensitivity=SENSITIVE) (String ename, int empno);

Note:

The implements clause must precede the with clause.

The SQLJ standard also allows a setting of ASENSITIVE, but in the Oracle implementation this is undefined. Setting sensitivity to ASENSITIVE results instead in the default setting, INSENSITIVE, being used. Given the preceding declaration, MyScrIter instances will be sensitive to data changes, subject to factors such as the fetch size window. Oracle Database JDBC Developer's Guide and Reference for information about scrollable result sets

See Also:

The Scrollable Interface This section documents some key methods of the sqlj.runtime.Scrollable interface. You can provide hints about the fetch direction to scrollable iterators. The following methods are defined on scrollable iterators as well as on execution contexts. Use an ExecutionContext instance to provide the default direction to be used in creation of scrollable iterators. ■

setFetchDirection(int): Gives the SQLJ run time a hint as to the direction in which rows are processed. The direction should be one of sqlj.runtime.ResultSetIterator.FETCH_FORWARD, FETCH_REVERSE, or FETCH_UNKNOWN. If you do not specify a value for the direction on the ExecutionContext, then FETCH_FORWARD will be used as a default.



int getFetchDirection(): Retrieves the current direction for fetching rows of data (one of the integer constants described in the previous point).

There are also a number of scrollable iterator methods that will return information about the current position of the iterator object in the underlying result set. All these methods will return false whenever the result set underlying the iterator contains no rows: ■

boolean isBeforeFirst(): Indicates whether the iterator object is before the first row in the result set.

Advanced Language Features 7-37

Iterator Class Implementation and Advanced Functionality







boolean isFirst(): Indicates whether the iterator object is on the first row of the result set. boolean isLast(): Indicates whether the iterator object is on the last row of the result set. Note that calling the isLast() method may be expensive, because the JDBC driver may have to fetch ahead one row to determine whether the current row is the last row in the result set. boolean isAfterLast(): Indicates whether the iterator object is after the last row in the result set. Additional methods for navigation, also defined in the Scrollable interface, are available as well.

Note:

Scrollable Named Iterators Named iterators use navigation methods, defined in the Scrollable interface, to move through the rows of a result set. As described earlier in this manual, nonscrollable iterators have only the following method for navigation: ■

boolean next(): Moves the iterator object to the next row in the result set. See Also:

"Using Named Iterators" on page 4-31

Additional navigation methods are available for scrollable named iterators. These methods function similarly to the next() method. In that they try to position the iterator on an actual row of the result set. They return true if the iterator ends up on a valid row and false if it does not. Additionally, if you attempt to position the iterator object before the first row or after the last row in the result set, this leaves the iterator object in the "before first" or "after last" position, respectively. The following methods are supported: ■

boolean previous(): Moves the iterator object to the previous row in the result set.



boolean first(): Moves the iterator object to the first row in the result set.



boolean last(): Moves the iterator object to the last row in the result set.









boolean absolute(int): Moves the iterator object to the given row number in the result set. The first row is row 1, the second is row 2, and so on. If the given row number is negative, then the iterator object moves to a row position relative to the end of the result set. For example, calling absolute(-1) positions the iterator object on the last row, absolute(-2) indicates the next-to-last row, and so on. boolean relative(int): Moves the iterator object a relative number of rows, either positive or negative from the current position. Calling relative(0) is valid, but does not change the iterator position. void beforeFirst(): Moves the iterator object to the front of the result set, before the first row. This has no effect if the result set contains no rows. void afterLast(): Moves the iterator object to the end of the result set, after the last row. This has no effect if the result set contains no rows.

7-38 Oracle Database SQLJ Developer’s Guide and Reference

Iterator Class Implementation and Advanced Functionality

Note: The beforeFirst() and afterLast() methods return void, because they never place the iterator object on an actual row of the result set.

Scrollable Positional Iterators General FETCH syntax for positional iterators was described earlier, in "Using Positional Iterators" on page 4-34. For example: #sql { FETCH :iter INTO :x, :y, :z };

This is actually an abbreviated version of the following syntax: #sql { FETCH NEXT FROM :iter INTO :x, :y, :z

};

This suggests the pattern for alternatively moving to the previous, first, or last row in the result set. Unfortunately, JDBC 2.0, after which the movement methods were modeled, uses previous(). The FETCH syntax, which is patterned after SQL, employs PRIOR. In case you forget this inconsistency, the Oracle Database 11g SQLJ translator will also accept FETCH PREVIOUS. The syntax are: #sql { FETCH PRIOR FROM :iter INTO :x, :y, :z }; #sql { FETCH FIRST FROM :iter INTO :x, :y, :z }; #sql { FETCH LAST FROM :iter INTO :x, :y, :z };

There is also syntax to pass a numeric value for absolute or relative movements, to move to a particular (absolute) row, or to move forward or backward from the current position. The syntax are: #sql { FETCH ABSOLUTE :n FROM :iter INTO :x, :y, :z #sql { FETCH RELATIVE :n FROM :iter INTO :x, :y, :z

}; };

Note: In all of the preceding cases, the iterator endFetch() method returns true whenever the FETCH fails to move to a valid row and retrieve values.

Note that you must use a host expression to specify the movement. You cannot simply use a constant for the numeric value. Thus, instead of the following: #sql { FETCH RELATIVE 0 FROM :iter INTO :x, :y, :z };

You must write the following: #sql { FETCH RELATIVE :(0) FROM :iter INTO :x, :y, :z

};

Incidentally, this command leaves the position of the iterator unchanged. If the iterator is on a valid row, then the command just populates the variables. Alternatively, you can navigate through a scrollable positional iterator through a combination of the navigation methods and the FETCH CURRENT syntax.

Note:

Advanced Language Features 7-39

Iterator Class Implementation and Advanced Functionality

FETCH CURRENT Syntax: from JDBC Result Sets to SQLJ Iterators Consider a situation where you have an existing JDBC program that you want to rewrite in SQLJ with as little modification as possible. Your JDBC result set will use only movement methods, such as next(), previous(), absolute(), and so on. You can immediately model this in SQLJ through a named iterator. However, this also implies that all columns of the SQL result set must have a proper name. In practice, many columns of the result set, if not all, will require introduction of alias names. This is unacceptable if the query text is to remain untouched. The alternative, to avoid change to the query source, is to define a positional iterator type for the result set. However, this approach forces changes to the control-flow logic of the program. Consider the following JDBC code sample: ResultSet rs = ... // execute ...query...; while (rs.next()) { x := rs.getXxx(1); y:=rs.getXxx(2); ...process... }

This translates along the following lines to SQLJ: MyIter iter; #sql iter = { ...query... }; while(true) { #sql { FETCH :iter INTO :x, :y }; if (iter.endFetch()) break; ...process... }

The transformations to the program logic will become even more difficult when considering arbitrary movements on scrollable iterators. Because positional iterators implement all the movement commands of named iterators, it is possible to exploit this and use RELATIVE :(0) to populate variables from the iterator: MyIter iter; #sql iter = { ...query... }; while (iter.next()) { #sql { FETCH RELATIVE :(0) FROM :iter INTO :x, :y }; ...process... }

Now, you can preserve both the original query and the original program logic. Unfortunately, there still is one drawback to this approach. The MyIter iterator type must implement the Scrollable interface, even if this property is not really needed. To address this, the Oracle SQLJ implementation supports the following syntax extension: #sql { FETCH CURRENT FROM :iter INTO :x, :y, :z

};

Given this syntax, you can rewrite the JDBC example in SQLJ for scrollable as well as nonscrollable iterators: AnyIterator ai; #sql ai = { ...query... }; while (ai.next()) { #sql { FETCH CURRENT FROM :ai INTO :x, :y }; ...process... }

7-40 Oracle Database SQLJ Developer’s Guide and Reference

Advanced Transaction Control

Scrollable Result Set Iterators Support in the Oracle SQLJ implementation for weakly typed result set iterators includes a scrollable result set iterator type: package sqlj.runtime; public interface ScrollableResultSetIterator extends ResultSetIterator implements Scrollable { }

Because this type extends sqlj.runtime.ResultSetIterator, it supports the methods described in "Result Set Iterators" on page 7-36. Because it also implements the sqlj.runtime.Scrollable interface, it supports the methods described in "The Scrollable Interface" on page 7-37 and "Scrollable Named Iterators" on page 7-38. Furthermore, scrollable result set iterators support the FETCH CURRENT syntax described in "FETCH CURRENT Syntax: from JDBC Result Sets to SQLJ Iterators" on page 7-40. Consider the following JDBC code: Statement st = conn.createStatement("SELECT ename, empid FROM emp"); ResultSet rs = st.executeQuery(); while (rs.next()) { x = rs.getString(1); y = rs.getInt(2); } rs.close();

You can use a SQLJ result set iterator in writing equivalent code, as follows: sqlj.runtime.ResultSetIterator rsi; #sql rsi = { SELECT ename, empid FROM emp }; while (rsi.next()) { #sql { FETCH CURRENT FROM :rsi INTO :x, :y }; } rsi.close();

To take advantage of scrollability features, you could also write the following code: sqlj.runtime.ScrollableResultSetIterator srsi; #sql srsi = { SELECT ename, empid FROM emp }; srsi.afterLast(); while (srsi.previous()) { #sql { FETCH CURRENT FROM :srsi INTO :x, :y }; } srsi.close();

Advanced Transaction Control SQLJ supports the SQL SET TRANSACTION statement to specify the access mode and isolation level of any given transaction. Standard SQLJ supports READ ONLY and READ WRITE access mode settings, but the Oracle JDBC implementation does not support READ ONLY. However, you can set permissions to have the same effect. Supported settings for isolation level are SERIALIZABLE, READ COMMITTED, READ UNCOMMITTED, and REPEATABLE READ. However, the Oracle SQL implementation does not support READ UNCOMMITTED or REPEATABLE READ.

Advanced Language Features 7-41

Advanced Transaction Control

READ WRITE is the default access mode in both standard SQL and the Oracle SQL implementation. READ COMMITTED is the default isolation level in the Oracle SQL implementation. SERIALIZABLE is the default in standard SQL. The following sections provide details: ■

SET TRANSACTION Syntax



Access Mode Settings



Isolation Level Settings



Using JDBC Connection Class Methods See Also:

"Basic Transaction Control" on page 3-18

SET TRANSACTION Syntax The SQLJ SET TRANSACTION statement has the following syntax: #sql { SET TRANSACTION , };

If you do not specify a connection context instance, then the statement applies to the default connection. If you use SET TRANSACTION, then it must be the first statement in a transaction, preceding any DML statements. In other words, the first statement since your connection to the database or your most recent COMMIT or ROLLBACK. In standard SQLJ, any access mode or isolation level you set will remain in effect across transactions until you explicitly reset it at the beginning of a subsequent transaction. In a standard SQLJ SET TRANSACTION statement, you can optionally specify the isolation level first or only the access mode or only the isolation level. Following are some examples: #sql { SET TRANSACTION READ WRITE }; #sql { SET TRANSACTION ISOLATION LEVEL SERIALIZABLE }; #sql { SET TRANSACTION READ WRITE, ISOLATION LEVEL SERIALIZABLE }; #sql { SET TRANSACTION ISOLATION LEVEL READ COMMITTED, READ WRITE };

You can also specify a particular connection context instance for a SET TRANSACTION statement, as opposed to having it apply to the default connection: #sql [myCtxt] { SET TRANSACTION ISOLATION LEVEL SERIALIZABLE };

Note that in SQLJ, both the access mode and the isolation level can be set in a single SET TRANSACTION statement. This is not true in other Oracle SQL tools, such as Server Manager or SQL*Plus, where a single statement can set one or the other, but not both.

Access Mode Settings The READ WRITE and READ ONLY access mode settings, where supported, have the following functionality: ■



READ WRITE (default): In a READ WRITE transaction, you are not allowed to update the database. SELECT, INSERT, UPDATE, and DELETE are all legal. READ ONLY (also supported by the Oracle JDBC implementation): In a READ ONLY transaction, you are not allowed to update the database. SELECT is legal, but INSERT, UPDATE, DELETE, and SELECT FOR UPDATE are not.

7-42 Oracle Database SQLJ Developer’s Guide and Reference

Advanced Transaction Control

Isolation Level Settings The READ COMMITTED, SERIALIZABLE, READ UNCOMMITTED, and REPEATABLE READ isolation level settings, where supported, have the following functionality: ■







READ UNCOMMITTED: Dirty reads, nonrepeatable reads, and phantom reads are all allowed. READ COMMITTED (default for Oracle10g): Dirty reads are prevented, and nonrepeatable reads and phantom reads are allowed. If the transaction contains DML statements that require row locks held by other transactions, then any of the statements will block until the row lock it needs is released by the other transaction. REPEATABLE READ: Dirty reads and nonrepeatable reads are prevented, and phantom reads are allowed. SERIALIZABLE: Dirty reads, nonrepeatable reads, and phantom reads are all prevented. Any DML statements in the transaction cannot update any resource that might have had changes committed after the transaction began. Such DML statements will fail.

A dirty read occurs when transaction B accesses a row that was updated by transaction A, but transaction A later rolls back the updates. As a result, transaction B sees data that was never actually committed to the database. A nonrepeatable read occurs when transaction A retrieves a row, transaction B subsequently updates the row, and transaction A later retrieves the same row again. Transaction A retrieves the same row twice but sees different data. A phantom read occurs when transaction A retrieves a set of rows satisfying a given condition, transaction B subsequently inserts or updates a row such that the row now meets the condition in transaction A, and transaction A later repeats the conditional retrieval. Transaction A now sees an additional row. This row is referred to as a phantom. You can think of the four isolation level settings being in a progression: SERIALIZABLE > REPEATABLE READ > READ COMMITTED > READ UNCOMMITTED

If a desired setting is unavailable to you, such as REPEATABLE READ or READ UNCOMMITTED if you use Oracle Database 11g, use a greater setting (one further to the left) to ensure having at least the level of isolation that you want. See Also:

Oracle Database Advanced Application Developer's Guide

Using JDBC Connection Class Methods You can optionally access and set the access mode and isolation level of a transaction, using methods of the underlying JDBC connection instance of your connection context instance. SQLJ code using these JDBC methods is not portable, however. Following are the Connection class methods for access mode and isolation level settings: ■

abstract int getTransactionIsolation(): Returns the current transaction isolation level as one of the following constant values: TRANSACTION_NONE TRANSACTION_READ_COMMITTED TRANSACTION_SERIALIZABLE

Advanced Language Features 7-43

SQLJ and JDBC Interoperability

TRANSACTION_READ_UNCOMMITTED TRANSACTION_REPEATABLE_READ ■





abstract void setTransactionIsolation(int): Sets the transaction isolation level, taking as input one of the preceding constant values. abstract boolean isReadOnly(): Returns true if the transaction is READ ONLY. Returns false if the transaction is READ WRITE. abstract void setReadOnly(boolean): Sets the transaction access mode to READ ONLY if true is input. Sets the access mode to READ WRITE if false is input.

SQLJ and JDBC Interoperability SQLJ statements are typically used for static SQL operations. Oracle Database 11g has extensions to support dynamic SQL as well, but another alternative is to use JDBC code within your SQLJ application for dynamic operations, which would be more portable. And there might be additional scenarios where using JDBC code in your SQLJ application might be useful or even required. Because of this, SQLJ enables you to use SQLJ and JDBC statements concurrently and provides interoperability between SQLJ and JDBC constructs. Two kinds of interactions between SQLJ and JDBC are particularly useful: ■

Between SQLJ connection contexts and JDBC connections



Between SQLJ iterators and JDBC result sets See Also:

Oracle Database JDBC Developer's Guide and Reference

This section covers the following topics: ■

SQLJ Connection Context and JDBC Connection Interoperability



SQLJ Iterator and JDBC Result Set Interoperability

SQLJ Connection Context and JDBC Connection Interoperability SQLJ enables you to convert, in either direction, between SQLJ connection context instances and JDBC connection instances. When converting between a SQLJ connection context and a JDBC connection, bear in mind that the two objects are sharing the same underlying physical connection.

Note:

Converting from Connection Contexts to JDBC Connections If you want to perform a JDBC operation through a database connection that you have established in SQLJ (for example, if your application calls a library routine that returns a JDBC connection object), then you must convert the SQLJ connection context instance to a JDBC connection instance. Any connection context instance in a SQLJ application, whether an instance of the sqlj.runtime.ref.DefaultContext class or of a declared connection context class, contains an underlying JDBC connection instance and a getConnection() method that returns that JDBC connection instance. Use the JDBC connection instance to create JDBC statement objects if you want to use JDBC operations.

7-44 Oracle Database SQLJ Developer’s Guide and Reference

SQLJ and JDBC Interoperability

Following is an example of how to use the getConnection() method. import java.sql.*; ... DefaultContext ctx = new DefaultContext ("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger", true); ... (SQLJ operations through SQLJ ctx connection context instance) ... Connection conn = ctx.getConnection(); ... (JDBC operations through JDBC conn connection instance) ...

The connection context instance can be an instance of the DefaultContext class or of any connection context class that you have declared. To retrieve the underlying JDBC connection of your default SQLJ connection, you can use getConnection() directly from a DefaultContext.getDefaultContext() call, where getDefaultContext() returns a DefaultContext instance that you had previously initialized as your default connection and getConnection() returns its underlying JDBC connection instance. In this case, because you do not have to use the DefaultContext instance explicitly, you can also use the Oracle.connect() method. This method implicitly creates the instance and makes it the default connection. See Also: "Connection Considerations" on page 3-4 and "More About the Oracle Class" on page 3-9

Following is an example: import java.sql.*; ... Connection conn = Oracle.connect ("jdbc:oracle:thin:@localhost:1521/myservice", "scott", "tiger").getConnection(); ... (JDBC operations through JDBC conn connection instance) ...

Example: JDBC and SQLJ Connection Interoperability for Dynamic SQL Following is a sample method that uses the underlying JDBC connection instance of the default SQLJ connection context instance to perform dynamic SQL operations in JDBC. The dynamic operations are performed using JDBC java.sql.Connection, java.sql.PreparedStatement, and java.sql.ResultSet objects. Alternatively, you can use Oracle SQLJ extensions for dynamic SQL operations. Oracle Database JDBC Developer's Guide and Reference and "Support for Dynamic SQL" on page 7-50

See Also:

import java.sql.*; public static void projectsDue(boolean dueThisMonth) throws SQLException { // Get JDBC connection from previously initialized SQLJ DefaultContext. Connection conn = DefaultContext.getDefaultContext().getConnection();

Advanced Language Features 7-45

SQLJ and JDBC Interoperability

String query = "SELECT name, start_date + duration " + "FROM projects WHERE start_date + duration >= sysdate"; if (dueThisMonth) query += " AND to_char(start_date + duration, ’fmMonth’) " + " = to_char(sysdate, ’fmMonth’) "; PreparedStatement pstmt = conn.prepareStatement(query); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { System.out.println("Project: " + rs.getString(1) + " Deadline: " + rs.getDate(2)); } rs.close(); pstmt.close(); }

For a rework of this example using SQLJ dynamic SQL functionality with FETCH functionality from a result set iterator, refer to Example 5: Dynamic SQL with FETCH from Result Set Iterator on page 7-54. Converting from JDBC Connections to Connection Contexts If you initiate a connection as a JDBC Connection instance but later want to use it as a SQLJ connection context instance (for example, if you want to use it in a context expression to specify the connection to use for a SQLJ executable statement), you can convert the JDBC connection instance to a SQLJ connection context instance. The DefaultContext class and all declared connection context classes have a constructor that takes a JDBC connection instance as input and constructs a SQLJ connection context instance. For example, presume you instantiated and defined the JDBC connection instance conn and want to use the same connection for an instance of a declared SQLJ connection context class MyContext. You can do this as follows: ... #sql context MyContext; ... MyContext myctx = new MyContext(conn); ...

About Shared Connections A SQLJ connection context instance and the associated JDBC connection instance share the same underlying physical connection. As a result, the following is true: ■



When you get a JDBC connection instance from a SQLJ connection context instance (using the connection context getConnection() method), the Connection instance inherits the state of the connection context instance. Among other things, the Connection instance will retain the auto-commit setting of the connection context instance. When you construct a SQLJ connection context instance from a JDBC connection instance (using the connection context constructor that takes a connection instance as input), the connection context instance inherits the state of the Connection instance. Among other things, the connection context instance will retain the auto-commit setting of the Connection instance. By default, a JDBC connection instance has an auto-commit setting of true, but you can alter this through the setAutoCommit() method of the Connection instance.

7-46 Oracle Database SQLJ Developer’s Guide and Reference

SQLJ and JDBC Interoperability





Given a SQLJ connection context instance and associated JDBC connection instance, calls to methods that alter session state in one instance will also affect the other instance, because it is actually the underlying shared session that is being altered. Because there is just a single underlying physical connection, there is also a single underlying set of transactions. A COMMIT or ROLLBACK operation in one connection instance will affect any other connection instances that share the same underlying connection. It is also possible for multiple SQLJ connection context instances to be created from the same JDBC connection instance and, therefore, to share the same underlying physical connection. This might be useful, for example, if you want to share the same set of transactions between program modules. The preceding notes apply to this situation as well.

Note:

Closing Shared Connections When you get a JDBC connection instance from a SQLJ connection context instance (using the getConnection() method) or you create a SQLJ connection context instance from a JDBC connection instance (using the connection context constructor), you must close only the connection context instance. By default, calling the close() method of a connection context instance closes the associated JDBC connection instance and the underlying physical connection, thereby freeing all resources associated with the connection. If you want to close a SQLJ connection context instance without closing the associated JDBC connection instance (if, for example, the Connection instance is being used elsewhere, either directly or by another connection context instance), then you can specify the boolean constant KEEP_CONNECTION to the close() method, as follows (assume a connection context instance ctx): ctx.close(ConnectionContext.KEEP_CONNECTION);

If you do not specify KEEP_CONNECTION, then the associated JDBC connection instance is closed by default. You can also specify this explicitly: ctx.close(ConnectionContext.CLOSE_CONNECTION);

KEEP_CONNECTION and CLOSE_CONNECTION are static constants of the sqlj.runtime.ConnectionContext interface. If you close only the JDBC connection instance, this will not close the associated SQLJ connection context instance. The underlying physical connection would be closed, but the resources of the connection context instance would not be freed until garbage collection.

Advanced Language Features 7-47

SQLJ and JDBC Interoperability

Note: ■



If the same underlying JDBC connection is shared by multiple connection context instances, then use KEEP_CONNECTION when closing all but the last remaining open connection context instance. An error message will be issued if you try to close a connection context instance whose underlying JDBC connection has already been closed, or if you try to close the underlying connection when it has already been closed. If you encounter this, then verify that the JDBC connection is not being closed independently by JDBC code and all preceding close() calls on SQLJ connection context instances that use the underlying connection use the KEEP_CONNECTION parameter.

SQLJ Iterator and JDBC Result Set Interoperability SQLJ enables you to convert in either direction between SQLJ iterators and JDBC result sets. For situations where you are selecting data in a SQLJ statement but do not care about strongly typed iterator functionality, SQLJ also supports a weakly typed iterator, which you can convert to a JDBC result set. Converting from Result Sets to Named or Positional Iterators There are a number of situations where you might find yourself manipulating JDBC result sets. For example, another package might be implemented in JDBC and provide access to data only through result sets or might require ResultSetMetaData information because it is a routine written generically for any type of result set. Or your SQLJ application might invoke a stored procedure that returns a JDBC result set. If the dynamic result set has a known structure, it is typically desirable to manipulate it as an iterator to use the strongly typed paradigm that iterators offer. In SQLJ, you can populate a named or positional iterator object by converting an existing JDBC result set object. This can be thought of as casting a result set to an iterator, and the syntax reflects this as follows: #sql iter = { CAST :rs };

This binds the result set object, rs, into the SQLJ executable statement, converts the result set, and populates the iterator, iter, with the result set data. Following is an example. Assume myEmpQuery() is a static Java function in a class called RSClass, with a predefined query that returns a JDBC result set object: import java.sql.*; ... #sql public iterator MyIterator (String ename, float sal); ... ResultSet rs; MyIterator iter; ... rs = RSClass.myEmpQuery(); #sql iter = { CAST :rs }; ... (process iterator) ... iter.close(); ... 7-48 Oracle Database SQLJ Developer’s Guide and Reference

SQLJ and JDBC Interoperability

This example could have used a positional iterator instead of a named iterator. The functionality is identical. The following rules apply when converting a JDBC result set to a SQLJ iterator and processing the data: ■











To convert to a positional iterator, the result set and iterator must have the same number of columns and the types must map correctly. To convert to a named iterator, the result set must have at least as many columns as the iterator and all columns of the iterator must be matched by name and type. If the result set and iterator do not have the same number of columns, then the SQLJ translator will generate a warning unless you use the -warn=nostrict option setting. The result set being cast must implement the java.sql.ResultSet interface. The class oracle.jdbc.OracleResultSet implements this interface, as does any standard result set class. The iterator receiving the cast must be an instance of an iterator class that was declared as public. Do not access data from the result set, either before or after the conversion. Access data from the iterator only. When you are finished, close the iterator, not the result set. Closing the iterator will also close the result set, but closing the result set will not close the iterator. When interoperating with JDBC, always close the SQLJ entity.

Converting from Named or Positional Iterators to Result Sets You might also encounter situations where you want to define a query using SQLJ but ultimately need a result set. SQLJ offers more natural and concise syntax, but perhaps you want to do dynamic processing of the results, or perhaps you want to use an existing Java method that takes a result set as input.

Note:

So that you can convert iterators to result sets, every SQLJ iterator class, whether named or positional, is generated with a getResultSet() method. This method can be used to return the underlying JDBC result set object of an iterator object. Following is an example showing use of the getResultSet() method: import java.sql.*; #sql public iterator MyIterator (String ename, float sal); ... MyIterator iter; ... #sql iter = { SELECT * FROM emp }; ResultSet rs = iter.getResultSet(); ... (process result set) ... iter.close(); ...

Advanced Language Features 7-49

Support for Dynamic SQL

The following rules apply when converting a SQLJ iterator to a JDBC result set and processing the data. ■



When writing iterator data to a result set, you should access data only through the result set. Do not attempt to directly access the iterator, either before or after the conversion. When you finish, close the original iterator, not the result set. Closing the iterator will also close the result set, but closing the result set will not close the iterator. When interoperating with JDBC, always close the SQLJ entity.

Using and Converting Weakly Typed Iterators (ResultSetIterator) You might have a situation similar to what is discussed in "Converting from Named or Positional Iterators to Result Sets" on page 7-49, but where you do not require the strongly typed functionality of the iterator. All you might care about is being able to use SQLJ syntax for the query and then processing the data dynamically from a result set. For such circumstances, you can directly use the sqlj.runtime.ResultSetIterator type to receive query data. In using SQLJ statements and ResultSetIterator functionality instead of using JDBC statements and standard result set functionality, you enable yourself to use the more concise SELECT syntax of SQLJ. Following is an example of how to use and convert a weakly typed result set iterator: import sqlj.runtime.*; import java.sql.*; ... ResultSetIterator rsiter; ... #sql rsiter = { SELECT * FROM table }; ResultSet rs = rsiter.getResultSet(); ... (process result set) ... rsiter.close(); ...

Note: The Oracle SQLJ implementation permits navigation through a result set iterator using the next() method and FETCH CURRENT syntax. Furthermore, for scrollable result set iterators, additional navigation methods are supported.

Support for Dynamic SQL The Oracle SQLJ implementation includes extensions to support dynamic SQL, operations that are not predefined and can change in real time. Dynamic SQL expressions embedded in SQLJ statements are referred to as meta bind expressions. Using JDBC code is still an option for dynamic SQL in Oracle Database 11g and might be preferable if code portability is a concern, but SQLJ support for dynamic SQL permits use of SQLJ as a single, simplified API for data access.

Note:

7-50 Oracle Database SQLJ Developer’s Guide and Reference

Support for Dynamic SQL

This section covers the following topics: ■

Meta Bind Expressions



SQLJ Dynamic SQL Examples

Meta Bind Expressions Meta bind expressions are used for dynamic SQL in SQLJ statements, where otherwise static SQL clauses would appear. A meta bind expression contains a Java identifier of String type or a string-valued Java expression that is interpreted at run time. In addition, so that SQLJ can perform online semantics-checking, a meta bind expression can optionally include static SQL replacement code to be used for checking during translation. Meta Bind Expressions: General Usage and Restrictions You can use a meta bind expression in place of any of the following: ■

Table name



Column name in a SELECT statement (without the column alias, if specified)



All or part of a WHERE clause condition





Role, schema, catalog, or package name in a data definition language (DDL) or DML statement SQL literal value or SQL expression

Be aware of the following restrictions on meta bind expressions, enforced to ensure that the SQLJ translator can properly determine the nature of the SQL operation and can perform syntactic analysis of the SQLJ statement as a whole: ■





A meta bind expression cannot be the first noncomment of the SQL operation within a SQLJ statement. A meta bind expression cannot contain the INTO token of a SQLJ SELECT INTO statement and cannot expand to become the INTO-list of a SELECT INTO statement. A meta bind expression cannot appear in any of the following kinds of SQL/SQLJ instructions or clauses: CALL, VALUES, PSM SET, COMMIT, ROLLBACK, FETCH INTO, or CAST.

Meta Bind Expressions: Syntax and Behavior Following is the general syntax for meta bind expressions: :{ Java_bind_expression }

or: :{ Java_bind_expression :: SQL_replacement_code }

Note that spaces are optional. There can be multiple meta bind expressions within the SQL instructions of a SQLJ statement. Java Bind Expression A Java bind expression can be either of the following: ■

Java identifier of the String type



Java expression that evaluates to a character string

Advanced Language Features 7-51

Support for Dynamic SQL

Java bind expressions within meta bind expressions are subject to standard Java lexing rules and have syntax similar to that of SQLJ host expressions. However, unlike host expressions, Java bind expressions within meta bind expressions are not enclosed within parentheses. This is because, if there is SQL replacement code, then the :: token acts as a separator between the Java bind expression and the SQL code. If there is no SQL replacement code, then the closing braces (}) acts as a terminator. In either case, there is no ambiguity. There can be no mode specifiers, IN, OUT, or INOUT, within a Java bind expression or between : and { of the meta bind expression.

Note:

SQL Replacement Code A SQL replacement code clause consists of a sequence of zero or more SQL tokens, with the following requirements and restrictions: ■ ■



It is subject to SQL lexing rules. Braces ({ }) must occur in matching pairs (with the exception of those that are part of a SQL comment, constant, or identifier). There can be no SQLJ host expressions or nested meta bind expressions within the SQL instructions. Note:

It is permissible for the SQL replacement code to be empty.

Translation-Time Behavior Whenever there is SQL replacement code (even if only an empty string) in a meta bind expression, then the meta bind expression is replaced by the SQL code during translation. The purpose of SQL replacement code is to enable the SQLJ translator to perform online semantics-checking. If any meta bind expression within a SQLJ statement has no SQL replacement code clause, then the SQLJ translator cannot perform online semantics-checking on the statement. It is only checked syntactically. Run Time Behavior At run time, each meta bind expression is replaced by the evaluation of its Java bind expression. If a Java bind expression evaluates to null, then the dynamic SQL statement as a whole becomes undefined.

SQLJ Dynamic SQL Examples This section provides examples of dynamic SQL usage in SQLJ code. Example 1 ... int x = 10; int y = x + 10; int z = y + 10; String table = "new_Emp"; #sql { INSERT INTO :{table :: emp} VALUES (:x, :y, :z) }; ...

7-52 Oracle Database SQLJ Developer’s Guide and Reference

Support for Dynamic SQL

During translation, the SQL operation becomes: INSERT INTO emp VALUES (10, 20, 30);

SQLJ can perform online semantics-checking against a schema that has an emp table. Perhaps new_Emp only exists in the run-time schema and is not created until the application executes. During run time, the SQL operation becomes: INSERT INTO new_Emp VALUES (10, 20, 30);

Example 2 ... String table = "new_Emp"; String query = "ename LIKE ’S%’ AND sal>1000"; #sql myIter = { SELECT * FROM :{table :: emp2} WHERE :{query :: ename=’SCOTT’} }; ...

During translation, the SQL operation becomes: SELECT * FROM emp2 WHERE ename=’SCOTT’;

SQLJ can perform online semantics-checking against a schema that has an emp2 table. During run time, the SQL operation becomes: SELECT * FROM new_Emp WHERE ename LIKE ’S%’ AND sal>1000;

Example 3 ... double raise = 1.12; String col = "comm"; String whereQuery = "WHERE "+col+" IS NOT null"; for (int i=0; i execute dbms_java.set_output(10000);

Output exceeding the buffer size will be lost. If you want your code executing in the server to expressly write output to the user screen, then you can also use the PL/SQL DBMS_OUTPUT.PUT_LINE() procedure instead of the Java System.out.println() method. The PUT_LINE() procedure is overloaded, accepting either VARCHAR2, NUMBER, or DATE as input to specify what is printed. See Also:

Oracle Database PL/SQL Packages and Types Reference

11-4 Oracle Database SQLJ Developer’s Guide and Reference

Translating SQLJ Source on a Client and Loading Components

Name Resolution in the Server Class loading and name resolution in the server follow a very different paradigm than on a client, because the environments themselves are very different. Java name resolution in Oracle JVM includes the following: ■



Class resolver specs, which are schema lists to search in resolving a class schema object (functionally equivalent to the classpath on a client) The resolver, which maintains mappings between class schema objects that reference each other in the server

A class schema object must be resolved before Java objects of the class can be instantiated or methods of the class can be executed. A class schema object is said to be resolved when all of its external references to Java names are bound. In general, all the classes of a Java program should be compiled or loaded before they can be resolved. This is because Java programs are typically written in multiple source files that can reference each other recursively. When all the class schema objects of a Java program in the server are resolved and none of them have been modified since being resolved, the program is effectively prelinked and ready to run. The loadjava utility resolves references to classes but not to resources. For ISO standard code, which has to be translated on the client, be careful how you load any resources into resource schema objects in the server. If you enabled the SQLJ -ser2class flag for your client-side translation, then your SQLJ profiles will be in class files and you will typically not have any resource files. If you did not enable -ser2class, then your profiles will be in .ser resource files. Note:

See Also:

Oracle Database Java Developer's Guide

SQL Names Versus Java Names SQL names, such as names of source, class, and resource schema objects, are not global in the way that Java names are global. The Java Language Specification (JLS) directs that package names use Internet naming conventions to create globally unique names for Java programs. By contrast, a fully qualified SQL name is interpreted only with respect to the current schema and database. For example, the SCOTT.FIZZ name in one database does not necessarily denote the same program as SCOTT.FIZZ in another database. In fact, SCOTT.FIZZ in one database can even call SCOTT.FIZZ in another database. Because of this inherent difference, SQL names must be interpreted and processed differently than Java names. SQL names are relative names and are interpreted from the point of view of the schema where a program is executed. This is central to how the program binds local data stored at that schema. Java names are global names, and the classes that they designate can be loaded at any execution site, with reasonable expectation that those classes will be classes that were used to compile the program.

Translating SQLJ Source on a Client and Loading Components One approach to deploying SQLJ code in Oracle Database 11g is to run the SQLJ translator on a client computer to take care of translation, compilation, and profile

SQLJ in the Server 11-5

Translating SQLJ Source on a Client and Loading Components

customization, if applicable. Then load the resulting class and resource files, if any, into the server, typically using a Java Archive (JAR) file. In fact, this is the only way to use ISO standard code in the server, because the server-side translator supports only Oracle-specific code generation. If you are developing your source on a client computer, as is usually the case, and have a SQLJ translator available there, then this approach is advisable. It provides flexibility in running the translator, because option-setting and error-processing are not as convenient in the server. For ISO standard code, it might also be advisable to use the SQLJ -ser2class option during translation when you intend to load an application into the server. This results in SQLJ profiles being converted from .ser serialized resource files to .class files and simplifies their naming. However, be aware that profiles converted to .class files cannot be further customized. To further customize, you would have to rerun the translator and regenerate the profiles. See Also: "Conversion of .ser File to .class File (-ser2class)" on page 8-53

When you load .class files and .ser resource files into Oracle Database 11g, either directly or using a JAR file, the resulting library units are referred to as Java class schema objects and Java resource schema objects. Your SQLJ profiles, if any, will be in resource schema objects, if you load them as .ser files, or in class schema objects if you enabled -ser2class during translation and load them as .class files. This section covers the following topics: ■

Loading Classes and Resources into the Server



Naming of Loaded Class and Resource Schema Objects



Publishing the Application After Loading Class and Resource Files



Summary: Running a Client Application in the Server

Loading Classes and Resources into the Server Once you run the translator on the client, use the Oracle loadjava client-side utility to load class and resource files into schema objects in the server. Either specify the class and resource files, if any, individually on the loadjava command line, or put them into a JAR file and specify the JAR file on the command line. A separate schema object is created for each .class or .ser file in the JAR file or on the command line. Consider an example where you do the following: 1.

Translate and compile Foo.sqlj, which includes an iterator declaration for MyIter, using ISO standard code generation.

2.

Enable the -ser2class option when you translate Foo.sqlj.

3.

Archive the resulting files, Foo.class, MyIter.class, Foo_SJProfileKeys.class, and Foo_SJProfile0.class, into Foo.jar.

Then run loadjava with the following command line (plus any options you want to specify). This examples uses the default JDBC Oracle Call Interface (OCI) driver: % loadjava -user scott Foo.jar Password: password

Alternatively, you can use the original files: % loadjava -user scott Foo.class MyIter.class Foo_SJProfileKeys.class 11-6 Oracle Database SQLJ Developer’s Guide and Reference

Translating SQLJ Source on a Client and Loading Components

Foo_SJProfile0.class Password: password

or: % loadjava -user scott Foo*.class MyIter.class Password: password

You can use the JDBC Thin driver for loading as follows (specifying the -thin option and an appropriate URL): % loadjava -thin -user scott@localhost:1521/myservice Foo.jar Password: password

See Also: "Code Generation" on page 9-3 and "Java Compilation" on page 9-6

Note: ■



When you use the -codegen=iso setting during translation, generating profile files and then loading the profiles into the server as .ser files, they are first customized if they were not already customized on the client. If they were already customized, then they are loaded as is. You can access the USER_OBJECTS view in your schema to verify that your classes and resources are loaded properly.

Although the loadjava utility is recommended for loading your SQLJ and Java applications into the server, you can also use SQL CREATE JAVA commands such as the following: CREATE OR REPLACE JAVA CLASS ; CREATE OR REPLACE JAVA RESOURCE ;

See Also: Oracle Database SQL Language Reference and Oracle Database Java Developer's Guide

Naming of Loaded Class and Resource Schema Objects This section discusses how schema objects for classes and profiles are named when you load classes and profiles into the server. However, remember that profiles are created only for ISO standard code generation. For ISO standard code generation, if the SQLJ -ser2class option was enabled when you translated your application on the client, then profiles were converted to .class files and will be loaded into class schema objects in the server. If -ser2class was not enabled, then profiles were generated as .ser serialized resource files and will be loaded into resource schema objects in the server. In the following discussion, it is assumed that you use only the default connection context class for any application that will run in the server. Therefore, there will be only one profile.

SQLJ in the Server 11-7

Translating SQLJ Source on a Client and Loading Components

Full Names and Short Names There are two forms of schema object names in the server, full names and short names. Full names are fully qualified and are used as the schema object names whenever possible. If any full name is longer than 31 characters, however, or contains characters that are illegal or cannot be converted to characters in the database character set, then Oracle Database 11g converts the full name to a short name to use as the name of the schema object, keeping track of both names and how to convert between them. If the full name is 31 characters or less and has no illegal or inconvertible characters, then the full name is used as the schema object name. For more information about these and about other file naming considerations, including DBMS_JAVA procedures to retrieve a full name from a short name, and vice versa, refer to Oracle Database Java Developer's Guide Full Names of Loaded Classes Loaded classes will include profile files if you use ISO standard code generation and enable the -ser2class flag. The full name of the class schema object produced when you load a .class file into the server is determined by the package and class name in the original source code. Any path information you supply on the command line or in the JAR file is irrelevant in determining the name of the schema object. For example, if Foo.class consists of the Foo class, which was specified in the source code as being in the x.y package, then the full name of the resulting class schema object is as follows: x/y/Foo

Note that the .class extension is dropped. If Foo.sqlj declares an iterator, MyIter, then the full name of its class schema object is as follows (unless it is a nested class, in which case it will not have its own schema object): x/y/MyIter

Furthermore, if you are using ISO standard code generation: ■

The related profile-keys class file, generated by SQLJ when you translate Foo.sqlj, is Foo_SJProfileKeys.class. Therefore, the full name of its class schema object is: x/y/Foo_SJProfileKeys



If the -ser2class option was enabled when you translated your application, then the resulting profile is generated in Foo_SJProfile0.class. Therefore, the full name of the class schema object is: x/y/Foo_SJProfile0

Full Names of Loaded Resources This discussion is relevant only if you are using ISO standard code generation and did not enable the -ser2class option when you translated your application, or if you use other Java serialized resource (.ser) files in your application. The naming of resource schema objects is handled differently from class schema objects. Their names are not determined from the contents of the resources. Instead, their full names are identical to the names that appear in a JAR file or on the loadjava command line, including path information. Also note that the .ser extension is not dropped.

11-8 Oracle Database SQLJ Developer’s Guide and Reference

Translating SQLJ Source on a Client and Loading Components

It is important to note that because resource names are used to locate the resources at run time. Their names must include the correct path information. In the server, the correct full name of a resource is identical to the relative path and file name that Java would use to look it up on a client. In the case of a SQLJ profile, this is a subdirectory under the directory specified by the translator -d option, according to the package name. If the -d option, used to specify the top-level output directory for generated .class and .ser files, is set to /mydir and the application is in the abc.def package, then .class and .ser files generated during translation will be placed in the /mydir/abc/def directory. See Also: "Output Directory for Generated .ser and .class Files (-d)" on page 8-22

At run time, /mydir would presumably be in your classpath and Java will look for your application components in the abc/def directory underneath it. Therefore, when you load this application into the server, you must run loadjava or jar from the -d directory so that the path you specify on the command line to find the files also indicates the package name, as follows (where % is the system prompt): % cd /mydir % loadjava abc/def/*.class abc/def/*.ser

Alternatively, to use a JAR file: % cd /mydir % jar -cvf myjar.jar abc/def/*.class abc/def/*.ser % loadjava myjar.jar

If your application is App and your profile is App_SJProfile0.ser, then either of the preceding examples will correctly result in the following full name of the created resource schema object: abc/def/App_SJProfile0.ser

Note that .ser is retained. Note also that if you set -d to a directory whose hierarchy has no other contents (which is advisable), you can simply run the JAR utility as follows to recursively get your application components: % cd /mydir % jar -cvf myjar.jar * % loadjava myjar.jar

Publishing the Application After Loading Class and Resource Files Before using your SQLJ code in the server, you must publish the top-level methods, as is true of any Java code you use in the server. Publishing includes writing call descriptors, mapping data types, and setting parameter modes. See Also:

Oracle Database Java Developer's Guide

Summary: Running a Client Application in the Server This section summarizes the typical steps of running a client application in the server. As an example, it uses a demo application called NamedIterDemo.

SQLJ in the Server 11-9

Loading SQLJ Source and Translating in the Server

1.

Create a JAR file for your application components. For NamedIterDemo, the components include SalesRec.class as well as the application class and profile, if any. You can create JAR file niter-server.jar as follows: % jar cvf niter-server.jar Named*.class Named*.ser SalesRec.class connect.properties

But remember that .ser files are only relevant for ISO standard code generation. 2.

Load the JAR file into the server. Use loadjava as follows. This example instructs loadjava to use the OCI driver in loading the files. The -resolve option results in the class files being resolved. % loadjava -oci -resolve -force -user scott niter-server.jar Password: password

3.

Create a SQL wrapper in the server for your application. For example, run a SQL*Plus script that executes the following: set set set set

echo on serveroutput on termout on flush on

execute dbms_java.set_output(10000); create or replace procedure SQLJ_NAMED_ITER_DEMO as language java name ’NamedIterDemo.main (java.lang.String[])’; /

The DBMS_JAVA.SET_OUTPUT() routine reroutes default output to your screen, instead of to a trace file. The input parameter is the buffer size in bytes. 4.

Execute the wrapper. For example: sqlplus> call SQLJ_NAMED_ITER_DEMO();

Loading SQLJ Source and Translating in the Server Another approach to developing SQLJ code for the server is loading the source code into the server and translating it directly in the server. This uses the embedded SQLJ translator in Oracle JVM. This discussion still assumes you created the source on a client computer. The server-side SQLJ translator does not support ISO standard code generation. If you want to use such code in the server, you must translate on a client and load the individual class files and resources into the server.

Note:

As a general rule, loading SQLJ source into the server is identical to loading Java source into the server, with translation taking place implicitly when a compilation option is set, such as the loadjava -resolve option. When you load .sqlj source files into Oracle Database 11g, either directly or using a JAR file, the resulting library

11-10 Oracle Database SQLJ Developer’s Guide and Reference

Loading SQLJ Source and Translating in the Server

units containing the source code are referred to as Java source schema objects. A separate schema object is created for each source file. When translation and compilation take place, the resulting library units for the generated classes are referred to as Java class schema objects, just as they are when loaded directly into the server from .class files created on a client. A separate schema object is created for each class. Resource schema objects are used for properties files that you load into the server. This section covers the following topics: ■

Loading SQLJ Source Code into the Server



Option Support in the Server Embedded Translator



Naming of Loaded Source and Generated Class and Resource Schema Objects



Error Output from the Server Embedded Translator



Publishing the Application After Loading Source Files See Also: Oracle Database SQL Language Reference and Oracle Database Java Developer's Guide

Loading SQLJ Source Code into the Server Use the Oracle loadjava client-side utility on a .sqlj file, instead of on a .class file, to load source into the server. If you enable the loadjava -resolve option in loading a .sqlj file, then the server-side embedded translator is run to perform the translation and compilation of your application as it is loaded. Otherwise, the source is loaded into a source schema object without any translation. However, in this case, the source is implicitly translated and compiled the first time an attempt is made to use a class defined in the source. Such implicit translation might seem surprising at first, because there is nothing comparable in client-side SQLJ. For example, run loadjava as follows from the system prompt: % loadjava -user scott -resolve Foo.sqlj Password: password

Alternatively, you can use the JDBC Thin driver to load: % loadjava -thin -user scott@localhost:1521/myservice -resolve Foo.sqlj Password: password

Either of these will result in appropriate class schema objects being created in addition to the source schema object. Before running loadjava, however, you must set SQLJ options appropriately. Note that encoding can be set on the loadjava command line, instead of through the server-side SQLJ encoding option, as follows: % loadjava -user scott -resolve -encoding SJIS Foo.sqlj Password: password

The loadjava script, which runs the actual utility, is in the bin subdirectory under your ORACLE_HOME directory. This directory should already be in your path once Oracle has been installed.

SQLJ in the Server 11-11

Loading SQLJ Source and Translating in the Server

Note: ■







In processing a JAR file, loadjava first processes .sqlj, .java, and .class files. It then makes a second pass and processes everything else as Java resource files. You cannot load a .sqlj file along with .class files that were generated from processing of the same .sqlj file. This would create an obvious conflict, because the server would be trying to load the same classes that it would also be trying to generate. You can put multiple .sqlj files into a JAR file and specify the JAR file to loadjava. You can access the USER_OBJECTS view in your schema to verify that your classes are loaded properly.

Although the loadjava utility is recommended for loading your SQLJ and Java applications into the server, you can also use SQL CREATE JAVA commands such as the following: CREATE OR REPLACE JAVA SOURCE ;

If you specify AND COMPILE for a .sqlj file, then the source is translated and compiled at that time, creating class schema objects as appropriate in addition to the source schema object. Otherwise, it is not translated and compiled. In this case, only the source schema object is created. In this latter case, however, the source is implicitly translated and compiled the first time an attempt is made to use a class contained in the source. When you first load a source file, some checking of the source code is performed, such as determining what classes are defined. If any errors are detected at this time, the load fails.

Note:

Option Support in the Server Embedded Translator The following options are available in the server-side SQLJ translator: ■

encoding



online



debug

This section discusses these options, after leading off with some discussion of fixed settings in server-side SQLJ. There is also discussion of the loadjava utility and its -resolve option. Fixed Settings in the Server-Side SQLJ Translator The following settings, supported by SQLJ translator options on a client, are fixed in the server-side translator: ■

Both online semantics-checking and offline parsing are enabled in the server by default, equivalent to the default -parse=both setting on a client. You can override this to disable online semantics-checking through the online option, but cannot disable offline parsing.

11-12 Oracle Database SQLJ Developer’s Guide and Reference

Loading SQLJ Source and Translating in the Server

See Also:

"Online Semantics-Checking Versus Offline Parsing" on

page 8-57 ■

Oracle-specific code generation is used in the server, equivalent to the default -codegen=oracle setting on a client. This is a fixed setting. See Also: "Oracle-Specific Code Generation (No Profiles)" on page 3-28



Class schema objects created during server-side translation reference line numbers that map to the SQLJ source code. This is equivalent to enabling the -linemap option when you translate on a client. See Also: "Line-Mapping to SQLJ Source File (-linemap)" on page 8-36

The encoding Option This option determines any encoding used to interpret your source code when it is loaded into the server. The encoding option is used at the time the source is loaded, regardless of whether it is also compiled. Alternatively, when using loadjava to load your SQLJ application into the server, you can specify encoding on the loadjava command line. Any loadjava command-line setting for encoding overrides this encoding option. If no encoding is specified, either through this option or through loadjava, then encoding is performed according to the file.encoding setting of the client from which you run loadjava.

Note:

"Encoding for Input and Output Source Files (-encoding)" on page 8-21

See Also:

The online Option A true setting for the online option (the default value) enables online semantics-checking. Semantics-checking is performed relative to the schema in which the source is loaded. You do not specify an exemplar schema, as you do for online-checking on a client. If the online option is set to false, offline checking is performed. In either case, the default checker is oracle.sqlj.checker.OracleChecker, which will choose an appropriate checker according to your JDBC driver version and Oracle version. See Also: "Semantics-Checkers and OracleChecker Front End (default checker)" on page 8-56

The online option is used at the time the source is translated and compiled. If you load it with the loadjava -resolve option enabled, then this will occur immediately. Otherwise it will occur the first time an attempt is made to use a class defined in the source, resulting in implicit translation and compilation.

SQLJ in the Server 11-13

Loading SQLJ Source and Translating in the Server

Note: The online option is used differently in the server than on a client. In the server, the online option is only a flag that enables online checking using a default checker. On a client, the -online option specifies which checker to use, but it is the -user option that enables online checking.

The debug Option Setting this option to true instructs the server-side Java compiler to output debugging information when a .sqlj or .java source file is compiled in the server. This is equivalent to using the -g option when running the standard javac compiler on a client. Source is compiled during loading if you use the loadjava -resolve option, right after SQLJ translation in the case of a .sqlj file. If you do not use the -resolve option, then implicit translation and compilation occurs the first time an attempt is made to use a class defined in the source. Setting SQLJ Options in the Server There is no command line and there are no properties files when running the SQLJ translator in the server. Information about translator and compiler options is held in each schema in a table named JAVA$OPTIONS. Manipulate options in this table through the following functions and procedures of the DBMS_JAVA package: ■

DBMS_JAVA.GET_COMPILER_OPTION()



DBMS_JAVA.SET_COMPILER_OPTION()



DBMS_JAVA.RESET_COMPILER_OPTION()

Use set_compiler_option() to specify separate option settings for individual packages or sources. It takes the following as input, with each parameter enclosed by single-quotes: ■

Package name, using dotted names, or source name Specify this as a full name, not a short name. If you specify a package name, then the option setting applies to all sources in that package and subpackages, except where you override the setting for a particular subpackage or source.



Option name



Option setting

Execute the DBMS_JAVA routines using SQL*Plus as follows: sqlplus> execute dbms_java.set_compiler_option(’x.y’, ’online’, ’true’); sqlplus> execute dbms_java.set_compiler_option(’x.y.Create’, ’online’, ’false’);

These two commands enable online checking for all sources in the x.y package, then override that for the Create source by disabling online checking for that particular source. Similarly, set encoding for the x.y package to SJIS as follows: sqlplus> execute dbms_java.set_compiler_option(’x.y’, ’encoding’, ’SJIS’);

Server-Side Option Notes Be aware of the following:

11-14 Oracle Database SQLJ Developer’s Guide and Reference

Loading SQLJ Source and Translating in the Server





The set_compiler_option() parameter for package and source names uses dotted names, such as abc.def as a package name, even though schema object names use slash syntax, such as abc/def as a package name. When you specify a package name, be aware that the option will apply to any included packages as well. A setting of a.b.MyPackage sets the option for any source schema objects whose names are of the following form: a/b/MyPackage/subpackage/...



Specifying ’’ (empty set of single-quotes) as a package name makes the option apply to the root and all subpackages, effectively making it apply to all packages in your schema.

Naming of Loaded Source and Generated Class and Resource Schema Objects When you use the server-side SQLJ translator, such as when you use loadjava on a .sqlj file with the -resolve option enabled, the output generated by the server-side translator is essentially identical to what would be generated on a client. This output consists of a compiled class for each class you defined in the source and a compiled class for each iterator and connection context class. As a result, the following schema objects will be produced when you load a .sqlj file into the server with loadjava and have it translated and compiled: ■

A source schema object for the original source code



A class schema object for each class you defined in the source



A class schema object for each iterator or connection context class you declared in the source But presumably you will not need to declare connection context classes in code that will run in the server, unless it is to specify type maps for user-defined types.

The full names of these schema objects are determined as described in the following subsections. Use the loadjava -verbose option for a report of schema objects produced and what they are named. Full Name of Source When you load a source file into the server, regardless of whether it is translated and compiled, a source schema object is produced. The full name of this schema object is determined by the package and class names in the source code. Any path information you supply to loadjava on the command line is irrelevant to the determination of the name of the schema object. For example, if Foo.sqlj defines the Foo class in the x.y package and defines or declares no other classes, then the full name of the resulting source schema object is: x/y/Foo

Note that the .sqlj extension is dropped. If you define additional classes or declare iterator or connection context classes, then the source schema object is named according to the first public class definition or declaration encountered, or, if there are no public classes, the first class definition. In the server, there can be more than one public class definition in a single source. For example, if Foo.sqlj is still in the x.y package, defines public class Bar first and then class Foo, and has no public iterator or connection context class declarations

SQLJ in the Server 11-15

Loading SQLJ Source and Translating in the Server

preceding the definition of Bar, then the full name of the resulting source schema object is: x/y/Bar

However, if the declaration of public iterator class MyIter precedes the Bar and Foo class definitions, then the full name of the resulting source schema object is: x/y/MyIter

Full Names of Generated Classes Class schema objects are generated for each class you defined in the source, each iterator you declared, and the profile-keys class. The naming of the class schema objects is based on the class names and the package name from the source code. This discussion continues the example in "Full Name of Source". Presume your source code specifies the x.y package, defines public class Bar then class Foo, then declares public iterator class MyIter. The full names of the class schema objects for the classes you define and declare are as follows: x/y/Bar x/y/Foo x/y/MyIter

Note that .class is not appended. It is recommended that the source name always match the first public class defined or, if there are no public classes, the first class defined. This will avoid possible differences between client-side and server-side behavior.

Note:

The name of the original source file, as well as any path information you specify when loading the source into the server, is irrelevant in determining the names of the generated classes. If you define inner classes or anonymous classes in your code, then they are named according to the conventions of the standard javac compiler.

Error Output from the Server Embedded Translator SQLJ error processing in the server is similar to general Java error processing in the server. SQLJ errors are directed into the USER_ERRORS table of the user schema. You can SELECT from the TEXT column of this table to get the text of a given error message. However, if you use loadjava to load your SQLJ source, then loadjava also captures and writes the error messages from the server-side translator. Informational messages and suppressible warnings are withheld by the server-side translator in a way that is equivalent to the operation of the client-side translator with a -warn=noportable,noverbose setting, which is the default. See Also:

"Translator Warnings (-warn)" on page 8-33

Publishing the Application After Loading Source Files Before using your SQLJ code in the server, you must publish the top-level methods, as is true of any Java code you use in the server. Publishing includes writing call

11-16 Oracle Database SQLJ Developer’s Guide and Reference

Additional Server-Side Considerations

descriptors, mapping data types, and setting parameter modes. For information, refer to Oracle Database Java Developer's Guide.

Dropping Java Schema Objects To complement the loadjava utility, Oracle provides the dropjava utility to remove Java source, class, and resource schema objects. It is recommended that any schema object loaded into the server using loadjava be removed using dropjava only. The dropjava utility transforms command-line file names and JAR file contents to schema object names, then removes the schema objects. You can enter .sqlj, .java, .class, .ser, and .jar files on the command line in any order. You should always remove Java schema objects in the same way that you first loaded them. If you load a .sqlj source file and translate it in the server, then run dropjava on the same source file. If you translate on a client and load classes and resources directly, then run dropjava on the same classes and resources. For example, if you run loadjava on Foo.sqlj, then execute dropjava on the same file name, as follows: % dropjava -user scott/password Foo.sqlj

If you translate your program on the client and load it using JAR file containing the generated components, then use the same JAR file name to remove the program: % dropjava -user scott/password Foo.jar

If you translate your program on the client and load the generated components using the loadjava command line, then remove them using the dropjava command line, as follows (assume -codegen=oracle and no iterator classes): % dropjava -user scott/password Foo*.class

See Also:

Oracle Database Java Developer's Guide

Additional Server-Side Considerations This section discusses Java multithreading in the server and recursive SQLJ calls in the server. It covers the following topics: ■

Java Multithreading in the Server



Recursive SQLJ Calls in the Server



Verifying that Code is Running in the Server

Java Multithreading in the Server Programs that use Java multithreading can execute in Oracle Database 11g without modification. However, while client-side programs use multithreading to improve throughput for users, there are no such benefits when Java-multithreaded code runs in the server. If you are considering porting a multithreaded application into the server, be aware of the following important differences in the functionality of multithreading in Oracle JVM, as opposed to in client-side JVMs: ■

Threads in the server run sequentially, not simultaneously.



In the server, threads within a call die at the end of the call.

SQLJ in the Server 11-17

Additional Server-Side Considerations



Threads in the server are not preemptively scheduled. If one thread goes into an infinite loop, then no other threads can run.

Do not confuse Java multithreading in Oracle Database 11g with general Oracle server multithreading. The latter refers to simultaneous Oracle sessions, not Java multithreading. In the server, scalability and throughput are gained by having many individual users, each with his own session, executing simultaneously. The scheduling of Java execution for maximum throughput, such as for each call within a session, is performed by Oracle Database 11g, and not by Java. See Also:

"Multithreading in SQLJ" on page 7-31

Recursive SQLJ Calls in the Server SQLJ generally does not allow multiple SQLJ statements to use the same execution context instance simultaneously. Specifically, a statement trying to use an execution context instance that is already in use will be blocked until the first statement completes. However, this functionality would be less desirable in the server than on a client. This is because different stored procedures or functions, which all typically use the default execution context instance, can inadvertently try to use this same execution context instance simultaneously in recursive situations. For example, one stored procedure might use a SQLJ statement to call another stored procedure that uses SQLJ statements. When these stored procedures are first created, there is probably no way of knowing when such situations might arise, so it is doubtful that particular execution context instances are specified for any of the SQLJ statements. To address this situation, SQLJ does allow multiple SQLJ statements to use the same execution context instance simultaneously if this results from recursive calls. Consider an example of a recursive situation to see what happens to status information in the execution context instance. Presume that all statements use the default connection context instance and its default execution context instance. If stored procedure proc1 has a SQLJ statement that calls stored procedure proc2, which also has SQLJ statements, then the statements in proc2 will each be using the execution context instance while the procedure call in proc1 is also using it. Each SQLJ statement in proc2 results in status information for that statement being written to the execution context instance, with the opportunity to retrieve that information after completion of each statement, as desired. The status information from the statement in proc1 that calls proc2 is written to the execution context instance only after proc2 has finished executing, program flow has returned to proc1, and the operation in proc1 that called proc2 has completed. To avoid confusion about execution context status information in recursive situations, execution context methods are carefully defined to update status information about a SQL operation only after the operation has completed.

11-18 Oracle Database SQLJ Developer’s Guide and Reference

Additional Server-Side Considerations

Note: ■





To avoid confusion, use distinct execution context instances as appropriate whenever you plan to use execution context status or control methods in code that will run in the server. Be aware that if the preceding example does not use distinct execution context instances and proc2 has any method calls to the execution context instance to change control parameters, then this will affect operations subsequently executed in proc1. Update batching is not supported across recursive calls. By default, only the top-level procedure will perform batching, if enabled. This limitation can be avoided by using explicit execution context instances.

See Also:

"Execution Context Methods" on page 7-26

Verifying that Code is Running in the Server A convenient way to verify that your code is actually running in the server is to use the static getProperty() method of the java.lang.System class to retrieve the oracle.server.version Java property. If this property contains a version number, then you are running in the server. If it is null, then you are not. Here is an example: ... if (System.getProperty("oracle.server.version") != null { // (running in server) } ...

Do not use the getProperties() method, as this causes a security exception in the server.

Note:

SQLJ in the Server 11-19

Additional Server-Side Considerations

11-20 Oracle Database SQLJ Developer’s Guide and Reference

A Customization and Specialized Customizers Profiles and profile customization are introduced in "SQLJ Profiles" on page 3-33. This appendix presents more technical detail and discusses customizer options and how to use customizers other than the default Oracle customizer. There is also discussion of Oracle specialized customizers, particularly the SQLCheckerCustomizer for semantics-checking profiles, and the AuditorInstaller for installing auditors for debugging. The following topics are covered: ■

More About Profiles



More About Profile Customization



Customization Options and Choosing a Customizer



JAR Files for Profiles



SQLCheckerCustomizer for Profile Semantics-Checking



AuditorInstaller Customizer for Debugging If you use the default Oracle-specific code generation (-codegen=oracle), the discussion in this appendix does not pertain to your application. Note:

More About Profiles SQLJ profiles contain information about your embedded SQL operations, with a separate profile being created for each connection context class that your application uses. Profiles are created during the SQLJ translator code generation phase and customized during the customization phase. Customization enables your application to use vendor-specific database features. Separating these vendor-specific operations into your profiles enables the rest of your generated code to remain generic. Each profile contains a series of entries for the SQLJ statements that use the relevant connection context class, where each entry corresponds to one SQL operation in your application. Profiles exist as serialized objects stored in resource files packaged with your application. Because of this, profiles can be loaded, read, and modified (added to or recustomized) at any time. When profiles are customized, information is only added, never removed. Multiple customizations can be made without losing preceding customizations, so that your application maintains the capability to run in multiple environments. This is known as binary portability.

Customization and Specialized Customizers

A-1

More About Profiles

For profiles to have binary portability, SQLJ industry-standard requirements have been met in the Oracle SQLJ implementation.

Creation of a Profile During Code Generation During code generation, the translator creates each profile as follows: 1.

It creates a profile object as an instance of the sqlj.runtime.profile.Profile class.

2.

It inserts information about your embedded SQL operations into the profile object, for SQLJ statements that use the relevant connection context class.

3.

It serializes the profile object into a Java resource file, referred to as a profile file, with a .ser file name extension. The Oracle SQLJ implementation provides an option to have the translator automatically convert these .ser files to .class files. The.ser files are not supported by some browsers, and can be cumbersome when loading translated applications into the server. However, this prevents any further customization of the profile. For information, see "Conversion of .ser File to .class File (-ser2class)" on page 8-53. Note:

As discussed in "Code Generation" on page 9-3, profile file names for application Foo are of the form: Foo_SJProfilen.ser

SQLJ generates Foo_SJProfile0.ser, Foo_SJProfile1.ser, and so on, as needed, depending on how many connection context classes you use in your code. Or, if the -ser2class option is enabled, then SQLJ generates Foo_SJProfile0.class, Foo_SJProfile1.class, and so on. Each profile has a getConnectedProfile() method that is called during SQLJ runtime. This method returns something equivalent to a JDBC Connection object, but with added functionality. This is further discussed in "Functionality of a Customized Profile at Run Time" on page A-6. Note: Referring to a "profile object" indicates that the profile is in its original nonserialized state. Referring to a "profile file" indicates that the profile is in its serialized state in a .ser file.

Sample Profile Entry Following is a sample SQLJ executable statement with the profile entry that would result. For simplicity, the profile entry is presented as plain text with irrelevant portions omitted. Note that in the profile entry, the host variable is replaced by JDBC syntax (the question mark).

SQLJ Executable Statement Presume the following declaration: #sql iterator Iter (double sal, String ename);

A-2 Oracle Database SQLJ Developer’s Guide and Reference

More About Profile Customization

And presume the following executable statements: String empname = ’Smith’; Iter it; ... #sql it = { SELECT ename, sal FROM emp WHERE ename = :empname };

Corresponding SQLJ Profile Entry ================================================================= ... #sql { SELECT ename, sal FROM emp WHERE ename = ? }; ... PREPARED_STATEMENT executed through EXECUTE_QUERY role is QUERY descriptor is null contains one parameter 1. mode: IN, java type: java.lang.String (java.lang.String), sql type: VARCHAR, name: ename, ... result set type is NAMED_RESULT result set name is Iter contains 2 result columns 1. mode: OUT, java type: double (double), sql type: DOUBLE, name: sal, ... 2. mode: OUT, java type: java.lang.String (java.lang.String), sql type: VARCHAR, name: ename, ... =================================================================

This profile entry is presented here as text for convenience only; profiles are not actually in text format. They can be printed as text, however, using the SQLJ -P-print option, as discussed in "Overview of Customizer Harness Options" on page A-7.

Note:

More About Profile Customization When using ISO SQLJ code, running the sqlj script on a SQLJ source file includes an automatic customization process, where each profile created during the code generation phase is customized for use with your particular database. The default customizer is Oracle customizer, oracle.sqlj.runtime.OraCustomizer, which optimizes your profiles to use type extensions and performance enhancements specific to Oracle10i. You can also run the sqlj script to customize profiles created previously. On the SQLJ command line, you can specify .ser files individually, JAR files containing .ser files, or both.

Customization and Specialized Customizers

A-3

More About Profile Customization

Note: ■





Whenever you use the default Oracle customizer during translation, your application will require Oracle SQLJ run time and an Oracle JDBC driver when it runs, even if you do not use Oracle extensions in your code. If an application has no customizations, or none suitable for the connection, then the generic SQLJ run time is used. You can run SQLJ to process .sqlj and .java files (for translation, compilation, and customization) or to process .ser and .jar files (for customization only), but not both categories at once.

Overview of the Customizer Harness and Customizers Regardless of whether you use Oracle customizer or an alternative customizer, SQLJ uses a front-end customization utility known as the customizer harness in accomplishing your customizations. When you run SQLJ, you can specify customization options for the customizer harness (for general customization settings that apply to any customizer you use) and for your customizer (for settings used by the particular customizer). In either case, you can specify these options either on the command line or in a properties file. This is discussed in "Customization Options and Choosing a Customizer" on page A-6. A customizer is required to be a JavaBeans component adhering to the standard JavaBeans API to expose its properties, and must implement the sqlj.runtime.profile.util.ProfileCustomizer interface, which specifies a customize() method. For each profile to be customized, the customizer harness calls the customize() method of the customizer object. Oracle customizer meets the preceding requirements and is defined in the oracle.sqlj.runtime.OraCustomizer class.

Steps in the Customization Process The SQLJ customization process during translation consists of the following steps, as applicable, either during the customization stage of an end-to-end SQLJ run, or when you run SQLJ to customize existing profiles only: 1.

SQLJ instantiates and invokes the customizer harness and passes it any general customization options you specified.

2.

The customizer harness instantiates the customizer you are using and passes it any customizer-specific options you specified.

3.

When you run SQLJ for customization only, specifying one or more JAR files on the command line, the customizer harness discovers and extracts the profile files within these JAR files.

4.

The customizer harness deserializes each profile file into a profile object (.ser files automatically created during an end-to-end SQLJ run, .ser files specified on the command line for customization only, or .ser files extracted from JAR files specified on the command line for customization only).

5.

If the customizer you use requires a database connection, the customizer harness establishes that connection.

A-4 Oracle Database SQLJ Developer’s Guide and Reference

More About Profile Customization

6.

For each profile, the harness calls the customize() method of the customizer object instantiated in step 2 (customizers used with SQLJ must have a customize() method).

7.

For each profile, the customize() method typically creates and registers a profile customization within the profile. This depends on the intended functionality of the customizer, however. Some might have a specialized purpose that does not require a customization to be created and registered in this way.

8.

The customizer harness reserializes each profile and puts it back into a .ser file.

9.

When you run SQLJ for customization only, specifying one or more JAR files on the command line, the customizer harness recreates the JAR contents, inserting each customized .ser file to replace the original corresponding uncustomized .ser file. Note: ■





If an error occurs during customization of a profile, the original .ser file is not replaced. If an error occurs during customization of any profile in a JAR file, the original JAR file is not replaced. SQLJ can run only one customizer at a time. If you want to accomplish multiple customizations on a single profile, you must run SQLJ multiple times. For the additional customizations, enter the profile name directly on the SQLJ command line.

Creation and Registration of a Profile Customization When the harness calls the customize() method to customize a profile, it passes in the profile object, a SQLJ connection context object (if you are using a customizer that requires a connection), and an error log object (which is used in logging error messages during the customization). The same error log object is used for all customizations throughout a single running of SQLJ, but its use is transparent. The customizer harness reads messages written to the error log object and reports them in real-time to the standard output device (whatever SQLJ uses, typically your screen). Recall that each profile has a set of entries, where each entry corresponds to a SQL operation. (These would be the SQL operations in your application that use instances of the connection context class associated with this profile.) A customize() method implements special processing on these entries. It could be as simple as checking each entry to verify its syntax, or it could be more complicated, such as creating new entries that are equivalent to the original entries but are modified to use features of your particular database.

Customization and Specialized Customizers

A-5

Customization Options and Choosing a Customizer

Note: ■



Any customize() processing of profile entries does not alter the original entries. Customizing your profiles for use in a particular environment does not prevent your application from running in a different environment. You can customize a profile multiple times for use in multiple environments, and these customizations will not interfere with each other.

Customization Error and Status Messages The customizer harness outputs error and status messages in much the same way as the SQLJ translator, outputting them to the same output device. None of the warnings regarding customization are suppressible, however. Error messages reported by the customizer harness fall into four categories: ■

Unrecognized or illegal option



Connection instantiation error



Profile instantiation error



Customizer instantiation error

Status messages reported by the customizer harness during customization enable you to determine whether a profile was successfully customized. They fall into three categories: ■

Profile modification status



JAR file modification status



Name of backup file created (if the customizer harness backup option is enabled)

Additional customizer-specific errors and warnings might be reported by the customize() method of the particular customizer. During customization, the profile customizer writes messages to its error log, and the customizer harness reads the log contents in real-time and outputs these messages to the SQLJ output device, along with any other harness output. You never have to access error log contents directly.

Functionality of a Customized Profile at Run Time A customized profile is a static member of the connection context class with which it is associated. For each SQLJ statement in your application, the SQLJ run time determines the connection context class and instance associated with that statement, then uses the customized profile of the connection context class, together with the underlying JDBC connection of the particular connection context instance, to create a connected profile. This connected profile is the vehicle that the SQLJ run time uses in applying vendor-specific features to the execution of your SQLJ application.

Customization Options and Choosing a Customizer This section discusses options for profile customization, which fall into three categories:

A-6 Oracle Database SQLJ Developer’s Guide and Reference

Customization Options and Choosing a Customizer



Options you specify to the customizer harness, which apply to whatever customizer you use. This includes general options, connection options, and options that invoke specialized customizers.





Customizer-specific options you specify to your customizer through the customizer harness. SQLJ options, which determine basic aspects of customization, such as whether to customize at all and which customizer to use.

All categories of options are specified through the SQLJ command line or properties files. The following topics are included in this section: ■

Overview of Customizer Harness Options



General Customizer Harness Options



Customizer Harness Options for Connections



Customizer Harness Options that Invoke Specialized Customizers



Overview of Customizer-Specific Options



Oracle Customizer Options



SQLJ Translator Options for Profile Customization

To choose a customizer other than the default Oracle customizer, you can use either the customizer harness customizer option (discussed in "Overview of Customizer Harness Options" on page A-7) or the SQLJ -default-customizer option (discussed in "SQLJ Translator Options for Profile Customization" on page A-29).

Overview of Customizer Harness Options The customizer harness provided with the Oracle SQLJ implementation offers a number of options that are not specific to a particular customizer. The harness uses these options in its front-end coordination of the customization process.

Syntax for Customizer Harness Options Customizer harness option settings on the SQLJ command line have the following syntax: -P-option=value

Alternatively, in a SQLJ properties file: profile.option=value

Enable boolean options (flags) either with: -P-option

or: -P-option=true

Boolean options are disabled by default, but you can explicitly disable them with: -P-option=false

Customization and Specialized Customizers

A-7

Customization Options and Choosing a Customizer

This option syntax is also discussed in "Options to Pass to the Profile Customizer (-P)" on page 8-50 and "Properties File Syntax" on page 8-13.

Options Supported by the Customizer Harness The customizer harness supports the following general options: ■ ■

■ ■

backup: Save a backup copy of the profile before customizing it. context: Limit customizations to profiles associated with the listed connection context classes. customizer: Specify the customizer to use. digests: Specify digests for JAR file manifests (relevant only if specifying JAR files to customize).



help: Display customizer options (specified only in SQLJ command line).



verbose: Display status messages during customization.

The customizer harness supports the following options for customizer database connections. Currently, these are used by Oracle customizer if you enable its optcols option for column definitions (for performance optimization). In addition, they are used by the SQLCheckerCustomizer if you use this specialized customizer to perform online semantics-checking on profiles. ■

user: Specify the user name for the connection used in this customization.



password: Specify the password for the connection used in this customization.



url: Specify the URL for the connection used in this customization.



driver: Specify the JDBC driver for the connection used in this customization.

For information about the Oracle customizer optcols flag, see "Oracle Customizer Column Definition Option (optcols)" on page A-20. For information about the SQLCheckerCustomizer, see "SQLCheckerCustomizer for Profile Semantics-Checking" on page A-30. The following commands function as customizer harness options, but are implemented through specialized customizers provided with the Oracle SQLJ implementation. ■

■ ■

debug: Insert debugging information into the specified profiles, to be output at run time. This is a shortcut to invoke the Oracle SQLJ AuditorInstaller, which is described in "AuditorInstaller Customizer for Debugging" on page A-33. print: Output the contents of the specified profiles, in text format. verify: Perform semantics-checking on a profile that was produced during a previous execution of the SQLJ translator (equivalent to semantics-checking performed on source code during translation). This is a shortcut to invoke Oracle SQLJ SQLCheckerCustomizer, which is described in "SQLCheckerCustomizer for Profile Semantics-Checking" on page A-30.

General Customizer Harness Options This section describes general options supported by the customizer harness.

A-8 Oracle Database SQLJ Developer’s Guide and Reference

Customization Options and Choosing a Customizer

Profile Backup Option (backup) Use the backup flag to instruct the harness to save a backup copy of each .jar file and standalone .ser file before replacing the original. (Separate backups of .ser files that are within .jar files are not necessary.) Backup file names are given the extension .bakn, where n indicates digits used as necessary where there are similarly named files. For each backup file created, an informational message is issued. If an error occurs during customization of a standalone .ser file, then the original .ser file is not replaced and no backup is created. Similarly, if an error occurs during customization of any .ser file within a JAR file, then the original JAR file is not replaced and no backup is created. The command-line syntax for this option is: -P-backup

Command-line example is: -P-backup

Properties file syntax is: profile.backup

Default value is: false

Customization Connection Context Option (context) Use the context option to limit customizations to profiles that correspond to the specified connection context classes. Fully qualify the class names and use a comma-delimited list to specify multiple classes. For example: -P-context=sqlj.runtime.ref.DefaultContext,foo.bar.MyCtxtClass

There must be no space on either side of the comma. If this option is not specified, then all profiles are customized, regardless of their associated connection context classes. Command-line syntax is: -P-context=ctx_class1

Command-line example is: -P-context=foo.bar.MyCtxtClass

Properties file syntax is: profile.context=ctx_class1

Properties file example is: profile.context=foo.bar.MyCtxtClass

Customization and Specialized Customizers

A-9

Customization Options and Choosing a Customizer

Customizer Option (customizer) Use the customizer option to specify which customizer to use. Fully qualify the class name, such as in the following example: -P-customizer=oracle.sqlj.runtime.util.OraCustomizer

If you do not set this option, then SQLJ will use the customizer specified in the SQLJ -default-customizer option. Unless set otherwise, this is the following: oracle.sqlj.runtime.util.OraCustomizer

Command-line syntax is: -P-customizer=customizer_class

Command-line example is: -P-customizer=a.b.c.MyCustomizer

Properties file syntax is: profile.customizer=customizer_class

Properties file example is: profile.customizer=a.b.c.MyCustomizer

Default value is: None

Customization JAR File Digests Option (digests) When a JAR file is produced, the JAR utility can optionally include one or more digests for each entry, based on one or more specified algorithms, so that the integrity of the JAR file entries can later be verified. Digests are similar conceptually to checksums, for readers familiar with those. If you are customizing profiles in a JAR file and want the JAR utility to add new digests (or update existing digests) when the JAR file is updated, use the digests option to specify a comma-delimited list of one or more algorithms. These are the algorithms that the JAR utility will use in creating the digests for each entry. The JAR utility produces one digest for each algorithm for each JAR file entry in the JAR manifest file. Specify algorithms as follows: -P-digests=SHA,MD5

There must be no space on either side of the comma. In this example, there will be two digests for each entry in the JAR manifest file: an SHA digest and an MD5 digest. Note:

Visit the Sun site more information about JAR manifest file.

Command-line syntax is: -P-digests=algo1

Command-line example is:

A-10 Oracle Database SQLJ Developer’s Guide and Reference

Customization Options and Choosing a Customizer

-P-digests=SHA,MD5

Properties file syntax is: profile.digests=algo1

Properties file example is: profile.digests=SHA,MD5

Default value is: SHA,MD5

Customization Help Option (help) Use the help option to display the option lists of the customizer harness and the default customizer or a specified customizer. For the harness and Oracle customizer, this includes a brief description and the current setting of each option. Display the option lists for the harness and default customizer as follows (where the default customizer is Oracle customizer or whatever you have specified in the SQLJ -default-customizer option): -P-help

Use the help option in conjunction with the customizer option to display the option list of a particular customizer, as follows: -P-help -P-customizer=sqlj.runtime.profile.util.AuditorInstaller

Note: ■



You can use the -P-help option on the SQLJ command line only, not in a SQLJ properties file. No customizations are performed if the -P-help flag is enabled, even if you specify profiles to customize on the command line.

Command-line syntax is: -P-help

Command-line example is: -P-help

Properties file syntax is: NA

Properties file example is: NA

Default value is: None

Customization and Specialized Customizers

A-11

Customization Options and Choosing a Customizer

Customization Verbose Option (verbose) Use the verbose flag to instruct the harness to display status messages during customizations. These messages are written to the standard output device, wherever SQLJ writes its other messages. Command-line syntax is: -P-verbose

Command-line example is: -P-verbose

Properties file syntax is: profile.verbose

Properties file example is: profile.verbose

Default value is: false

Customizer Harness Options for Connections This section describes connection options supported by the customizer harness. These are used as follows: ■



Oracle customizer uses database connections only for column definitions. If you do not enable Oracle customizer optcols option, then there is no need to set the customizer harness user, password, url, and driver options. The SQLCheckerCustomizer, a specialized customizer that performs semantics-checking on profiles, uses the customizer harness user, password, url, and driver settings for online checking. Use -P-verify on the SQLJ command line to invoke this customizer.

Note: Do not confuse the customizer harness user, password, url, and driver options with the translator options of the same names, which are for semantics-checking during the translation step. However, the translator settings are passed to the customizer for convenience, in case customization is to use the same connection as translation. Override these initial settings through the customizer harness options if you wish.

Customization User Option (user) Set the user option to specify a database schema if your customizer uses database connections. In addition to specifying the schema, you can optionally specify the password, URL, or both in your user option setting. The password is preceded by a forward-slash (/), and the URL is preceded by an "at" sign (@), as in the following examples: -P-user=scott/tiger

A-12 Oracle Database SQLJ Developer’s Guide and Reference

Customization Options and Choosing a Customizer

-P-user=scott@jdbc:oracle:oci:@ -P-user=scott/tiger@jdbc:oracle:oci:@

When you use column definitions (optcols option), the user setting for the SQLJ translator is forwarded to the profile customizer as well, but you can use the customizer user option to override the translator setting.

Note:

Command-line syntax is: -P-user=username

Command-line examples is: -P-user=scott -P-user=scott/password -P-user=scott/password@jdbc:oracle:oci:@

Properties file syntax is: profile.user=username

Properties file examples is: profile.user=scott profile.user=scott/tiger profile.user=scott/tiger@jdbc:oracle:oci:@

Default value is: null

Customization Password Option (password) Use the password option if your customizer uses database connections. The password can also be set with the user option, as described in "Customization User Option (user)" on page A-12. When you use column definitions (optcols option), the password setting for the SQLJ translator is forwarded to the profile customizer as well, but you can use the customizer password option to override the translator setting.

Note:

Command-line syntax is: -P-password=password

Command-line example is: -P-password=password

Properties file syntax is: profile.password=password

Properties file example is:

Customization and Specialized Customizers

A-13

Customization Options and Choosing a Customizer

profile.password=password

Default value is: null

Customization URL Option (url) Use the url option if your customizer uses database connections. The URL can also be set with the user option, as described in "Customization User Option (user)" on page A-12. When you use column definitions (optcols option), the URL setting for the SQLJ translator is forwarded to the profile customizer as well, but you can use the customizer url option to override the translator setting. Note:

Command-line syntax is: -P-url=url

Command-line example is: -P-url=jdbc:oracle:oci:@

Properties file syntax is: profile.url=url

Properties file example is: profile.url=jdbc:oracle:oci:@

Default value is: jdbc:oracle:oci:@

Customization JDBC Driver Option (driver) Use the driver option to register a comma-delimited list of JDBC driver classes if your customizer uses database connections. For example: -P-driver=sun.jdbc.odbc.JdbcOdbcDriver,oracle.jdbc.OracleDriver

There must be no space on either side of the comma. Command-line syntax is: -P-driver=dvr_class1

Command-line example is: -P-driver=sun.jdbc.odbc.JdbcOdbcDriver

Properties file syntax is: profile.driver=dvr_class1

Properties file example is: A-14 Oracle Database SQLJ Developer’s Guide and Reference

Customization Options and Choosing a Customizer

profile.driver=sun.jdbc.odbc.JdbcOdbcDriver

Default value is: oracle.jdbc.OracleDriver

Customizer Harness Options that Invoke Specialized Customizers The customizer harness supports the following options that invoke specialized customizers: ■

debug: This invokes the AuditorInstaller customizer, used in debugging.



print: This invokes a customizer that prints a text version of a profile.



verify: This invokes the SQLCheckerCustomizer customizer, which performs semantics-checking on a profile.

Because each of these options invokes a customizer, and only one customizer can run in a single execution of SQLJ, you cannot perform any other customization when you use any of these options.

Important:

You also cannot use more than one of print, debug, or verify simultaneously.

Specialized Customizer: Profile Debug Option (debug) The debug option runs a specialized customizer, called the AuditorInstaller, that inserts debugging statements into profiles. Use this option in conjunction with a SQLJ command line file list to insert debugging statements into the specified profiles. These profiles must already be customized from a previous SQLJ run. For detailed information about this customizer, including additional options that it supports, see "AuditorInstaller Customizer for Debugging" on page A-33. The debugging statements will execute during SQLJ run time (when someone runs your application), displaying a trace of method calls and values returned. Following are examples of how to specify the debug option: % sqlj -P-debug Foo_SJProfile0.ser Bar_SJProfile0.ser % sqlj -P-debug *.ser

Command-line syntax is: sqlj -P-debug profile_list

Command-line example is: sqlj -P-debug Foo_SJProfile*.ser

Properties file syntax is: profile.debug

(Also specify profiles in the SQLJ file list.) Properties file example is: Customization and Specialized Customizers

A-15

Customization Options and Choosing a Customizer

profile.debug

Default value is: NA

Specialized Customizer: Profile Print Option (print) The print option runs a specialized customizer that prints profiles in text format. Use this option in conjunction with a SQLJ command line file list to output the contents of one or more specified profiles. The output goes to the standard SQLJ output device, typically the user screen. For example: % sqlj -P-print Foo_SJProfile0.ser Bar_SJProfile0.ser

Use the following command, if you want to see all the customizer options: % sqlj -P-print *.ser

The output of the preceding command is like the following: printing contents of profile Sample_SJProfile0 created 1154609279331 (8/3/06 5:47 AM) associated context is Mycontext1 profile loader is sqlj.runtime.profile.DefaultLoader@12a3793 contains one customization OracleCustomization Options : Version is :2300 Cstmtcache :5 Ccompat :false Cforce :false Coptcols :false Coptparams :false Coptparamdefaults:null CshowSQL :false Csummary :false CuserSQL :true #sql { SELECT a FROM test WHERE name= ? setFixedchar is enabled Ncharconv is disabled #sql { commit } setFixedchar is disabled Ncharconv is disabled ………

Command-line syntax is: sqlj -P-print profile_list

Command-line example is: sqlj -P-print Foo_SJProfile*.ser

Properties file syntax is: profile.print

(Also specify profiles in SQLJ file list.) Properties file example is:

A-16 Oracle Database SQLJ Developer’s Guide and Reference

}

Customization Options and Choosing a Customizer

profile.print

Default value is: NA

Specialized Customizer: Profile Semantics-Checking Option (verify) The verify option runs a specialized customizer, called the SQLCheckerCustomizer, that performs semantics-checking on a profile. This is equivalent to the semantics-checking that is performed on source code during translation. The profile will have been created during a previous execution of the SQLJ translator. This option is useful for checking semantics against the run time database, after deployment, and after the source code may no longer be available. For detailed information about this customizer, including additional options that it supports, see "SQLCheckerCustomizer for Profile Semantics-Checking" on page A-30. For online semantics-checking of the profile, you must also use the customizer harness user, password, and url options.

Note:

Following are examples of how to specify the verify option. Both of these examples use the SQLCheckerCustomizer default semantics-checker, which employs online checking through the specified database connection. (The first is a single wraparound command.) % sqlj -P-verify -P-user=scott -P-url=jdbc:oracle:oci:@ Foo_SJProfile0.ser Bar_SJProfile0.ser Password: password % sqlj -P-verify -P-user=scott -P-url=jdbc:oracle:oci:@ *.ser Password: password

Command-line syntax is: sqlj -P-verify profile_list

Command-line example is: sqlj -P-verify Foo_SJProfile*.ser

Properties file syntax is: profile.verify

(You must also specify profiles, and typically customizer harness connection options, in the SQLJ command line.) Properties file example is: profile.verify

Default value is: NA

Customization and Specialized Customizers

A-17

Customization Options and Choosing a Customizer

Overview of Customizer-Specific Options You can set customizer-specific options, such as options for Oracle customizer, on the SQLJ command line or in a SQLJ properties file. The syntax is similar to that for setting customizer harness options. Set a customizer option on the SQLJ command line by preceding it with: -P-C

Alternatively, you can set it in a SQLJ properties file by preceding it with: profile.C

This option syntax is also discussed in "Options to Pass to the Profile Customizer (-P)" on page 8-50 and "Properties File Syntax" on page 8-13. The remainder of this section discusses features of Oracle customizer, which supports several options. Most of these options are boolean and are enabled as follows: -P-Coption

or: -P-Coption=true

Boolean options are disabled by default, but you can explicitly disable them with: -P-Coption=false

Numeric or string options are set similarly: -P-Coption=value

Oracle Customizer Options This section describes options that are specific to Oracle customizer, beginning with an overview of the options supported.

Options Supported by Oracle Customizer Oracle customizer implements the following options: ■ ■







compat: Display version-compatibility information. force: Instruct the customizer to customize even if a valid customization already exists. optcols: Enable iterator column type and size definitions to optimize performance. optparams: Enable parameter size definitions to optimize JDBC resource allocation (used in conjunction with optparamdefaults). optparamdefaults: Set parameter size defaults for particular data types (used in conjunction with optparams).



fixedchar: Enable CHAR comparisons with blank padding for WHERE clauses.



showSQL: Display SQL statement transformations.





stmtcache: Set the statement cache size (the number of statements that can be cached for each connection during run time) for performance optimization, or set it to zero to disable statement caching. summary: Display a summary of Oracle features used in your application.

A-18 Oracle Database SQLJ Developer’s Guide and Reference

Customization Options and Choosing a Customizer

Any output displayed by these options is written to the standard output device, wherever SQLJ writes its other messages.

Oracle Customizer Version Compatibility Option (compat) Use the compat flag to instruct Oracle customizer to display information about compatibility of your application with different versions of Oracle Database and Oracle JDBC drivers. This can be accomplished either during a full SQLJ translation run or on profiles previously created. For example, to see compatibility output when translating and customizing the application MyApp: % sqlj -P-Ccompat MyApp.sqlj

In this example, the MyApp profiles will be created, customized, and checked for compatibility in a single running of SQLJ. To see compatibility output for MyApp profiles previously created: % sqlj -P-Ccompat MyApp_SJProfile*.ser

In this example, the MyApp profiles were created (and possibly customized) in a previous running of SQLJ and will be customized (if needed) and checked for compatibility in the above running of SQLJ. Following are two output samples from a -P-Ccompat setting when using the default Oracle customizer. The first example indicates that the application can be used with all Oracle JDBC driver versions: MyApp_SJProfile0.ser: Info: compatible with all Oracle JDBC drivers

This second example indicates that the application can be used only with the JDBC implementation from an Oracle 8.1.x or later release: MyApp_SJProfile0.ser: Info: compatible with Oracle 8.1 or later JDBC driver

If customization does not take place because a valid previous customization is detected, the compat option reports compatibility regardless.

Note:

Command-line syntax is: -P-Ccompat

Command-line example is: -P-Ccompat

Properties file syntax is: profile.Ccompat

Properties file example is: profile.Ccompat

Default value is: false

Customization and Specialized Customizers

A-19

Customization Options and Choosing a Customizer

Oracle Customizer Force Option (force) Use the force flag to instruct Oracle customizer to force the customization of a given profile (specified on the command line) even if a valid customization already exists in that profile. For example: % sqlj -P-Cforce MyApp_SJProfile*.ser

This will customize all the MyApp profiles, regardless of whether they have already been customized. Otherwise, by default, Oracle customizer will not reinstall over a previously existing customization unless the previous one had been installed with an older version of the customizer. Command-line syntax is: -P-Cforce

Command-line example is: -P-Cforce

Properties file syntax is: profile.Cforce

Properties file example is: profile.Cforce

Default value is: false

Oracle Customizer Column Definition Option (optcols) Use the optcols flag to instruct Oracle customizer to determine types and sizes of iterator or result set columns and add this information to the profile. This enables the SQLJ run time to automatically register the columns with Oracle JDBC driver when your application runs, saving round trips to Oracle depending on the particular driver implementation. Specifically, this is effective for the Thin driver and positional iterators. For an overview of column definitions, see "Column Definitions" on page 10-16. An error will be generated if you enable Oracle customizer optcols option without setting the user name, password, and URL for a database connection. You can accomplish this through the translator -user, -password, and -url options, which are forwarded to the customizer during ISO standard code generation, or directly through the customizer user, password, and url options. The customizer does not have to connect to the same schema or even the same database that your application will connect to at run time, but the relevant columns will have to be in the same order and of identical types and sizes to avoid run time errors. For information about the customizer harness connection options, see the user, password, url, and driver sections under "Overview of Customizer Harness Options" on page A-7.

A-20 Oracle Database SQLJ Developer’s Guide and Reference

Customization Options and Choosing a Customizer

You can use the SQLJ translator -optcols option instead. This sets the customizer option automatically. (And for Oracle-specific code generation, which uses no profiles, you must use the translator option instead.) See "Column Definitions (-optcols)" on page 8-41.

Note:

That section also has some additional conceptual information. You can enable or disable the customizer optcols flag on the SQLJ command line or in a properties file. Enable it on the command line as follows: -P-Coptcols

or: -P-Coptcols=true

This flag is disabled by default, but you can also disable it explicitly. Disable it on the command line as follows: -P-Coptcols=false

Column definitions require the customizer to make a database connection to examine columns of tables being queried, so the customizer harness user, password, and url options must be set appropriately (as well as the customizer harness driver option if you are not using the default OracleDriver class). For example: % sqlj -P-user=scott@jdbc:oracle:oci:@ -P-Coptcols MyApp.sqlj Password: password

Note that as with the SQLJ translator, you can optionally set the password and URL in the user option instead of in the password and url options. Alternatively, you can insert column definitions into a previously existing profile. In this case you must also use the Oracle customizer force option to force a recustomization: % sqlj -P-user=scott@jdbc:oracle:oci:@ -P-Cforce -P-Coptcols MyApp_SJProfile*.ser Password: password

You also can insert column definitions into previously existing profiles in a JAR file: % sqlj -P-user=scott@jdbc:oracle:oci:@ -P-Cforce -P-Coptcols MyAppProfiles.jar Password: password

When you run Oracle customizer with its optcols flag enabled, either during translation and creation of a new profile or during customization of an existing profile, you can also enable the customizer harness verbose flag. This will instruct Oracle customizer to display information about what iterators and result sets are being processed and what their column type and size definitions are. For example: % sqlj -P-user=scott@jdbc:oracle:oci:@ -P-verbose -P-Cforce -P-Coptcols MyApp_SJProfile*.ser Password: password

For general information about the verbose flag, see that section under "Overview of Customizer Harness Options" on page A-7. You can execute Oracle customizer with its summary flag enabled on an existing profile to determine if column definitions have been added to that profile:

Customization and Specialized Customizers

A-21

Customization Options and Choosing a Customizer

% sqlj -P-Csummary MyApp_SJProfile*.ser

For general information about the summary flag, see that section under "Overview of Customizer-Specific Options" on page A-18. Command-line syntax is: -P-Coptcols

Command-line example is: -P-Coptcols

Properties file syntax is: profile.Coptcols

Properties file example is: profile.Coptcols

Default value is: false

Oracle Customizer Parameter Definition Option (optparams) Use the optparams flag to enable parameter size definitions. If this flag is enabled, SQLJ will register your input and output parameters (host variables) to optimize JDBC resource allocations according to sizes you specify. For an overview of parameter size definitions and a discussion of source code hints, see "Parameter Size Definitions" on page 10-17. You can use the SQLJ translator -optparams option instead. This sets the customizer option automatically. (And for Oracle-specific code generation, which uses no profiles, you must use the translator option instead.) See "Parameter Definitions (-optparams)" on page 8-43.

Note:

That section also has some additional conceptual information. You can enable or disable the optparams flag on the command line or in a SQLJ properties file. Enable it on the command line as follows: -P-Coptparams

or: -P-Coptparams=true

This flag is disabled by default, but you can also disable it explicitly. Disable it on the command line as follows: -P-Coptparams=false

A-22 Oracle Database SQLJ Developer’s Guide and Reference

Customization Options and Choosing a Customizer

Note: Unlike the optcols option, the optparams option does not require a database connection by the customizer, because you are providing the size specifications yourself.

Following is a command-line example (omitting a setting for the optparamdefaults option, which is discussed in the next section): % sqlj -P-Coptparams -P-Coptparamdefaults=defaults_string MyApp.sqlj

Alternatively, to enable parameter size definitions for a previously existing profile: % sqlj -P-Coptparams -P-Coptparamdefaults= defaults_string MyApp_SJProfile*.ser

You can also use previously existing profiles in a JAR file: % sqlj -P-Coptparams -P-Coptparamdefaults= defaults_string MyAppProfiles.jar

Command-line syntax is: -P-Coptparams

Command-line example is: -P-Coptparams

Properties file syntax is: profile.Coptparams

Properties file example is: profile.Coptparams

Default value is: false

Oracle Customizer Parameter Default Size Option (optparamdefaults) If you enable the optparams option to set parameter sizes, use the optparamdefaults option as desired to set default sizes for specified data types. If optparams is not enabled, then any optparamdefaults setting is ignored. For an overview of parameter size definitions and a discussion of source code hints, see "Parameter Size Definitions" on page 10-17. Note: You can use the SQLJ translator -optparamdefaults option instead. This sets the customizer option automatically. (And for Oracle-specific code generation, which uses no profiles, you must use the translator option instead.) See "Parameter Default Size (-optparamdefaults)" on page 8-44.

That section also has important additional conceptual and syntax information. Functionality of the two options is equivalent.

Customization and Specialized Customizers

A-23

Customization Options and Choosing a Customizer

You can set the optparamdefaults flag on the command line or in a SQLJ properties file. Set it on the command line as follows: -P-Coptparamdefaults=datatype1(size1),datatype2(size2),...

Following is a command-line example, including the optparams setting as well: % sqlj -P-Coptparams -P-Coptparamdefaults=CHAR_TYPE(50),RAW_TYPE(500),CHAR(10) MyApp.sqlj

The syntax is explained in "Parameter Default Size (-optparamdefaults)" on page 8-44. Alternatively, you can specify parameter size defaults for a previously existing profile, in which case you must also use the Oracle customizer force option to force a recustomization: % sqlj -P-Cforce -P-Coptparams -P-Coptparamdefaults=CHAR_TYPE(50),RAW_TYPE(500),CHAR(10) MyApp_SJProfile*.ser

You also can specify parameter size defaults for previously existing profiles in a JAR file: % sqlj -P-Cforce -P-Coptparams -P-Coptparamdefaults=CHAR_TYPE(50),RAW_TYPE(500),CHAR(10) MyAppProfiles.jar

If at run time the actual size exceeds the registered size of any parameter, run time errors will occur.

Note:

Command-line syntax is: -P-Coptparamdefaults=defaults_string

Command-line example is: -P-Coptparamdefaults=VAR%(50),LONG%(500),RAW_TYPE()

Properties file syntax is: profile.Coptparamdefaults=defaults_string

Properties file example is: profile.Coptparamdefaults=VAR%(50),LONG%(500),RAW_TYPE()

Default value is: null

Oracle Customizer CHAR Comparisons with Blank Padding (fixedchar) Set this flag to true to account for blank padding in CHAR database columns when binding character strings for WHERE clause comparisons. This way, for example, "mystring" would compare positively against "mystring ". Here is an example of Oracle customizer fixedchar usage: % sqlj -P-Cfixedchar MyProgram.sqlj AnotherProg.java ...

A-24 Oracle Database SQLJ Developer’s Guide and Reference

Customization Options and Choosing a Customizer

Note: ■



You can use the SQLJ translator -fixedchar option instead. This sets the customizer option automatically. (And for Oracle-specific code generation, which uses no profiles, you must use the translator option instead.) See "CHAR Comparisons with Blank Padding (-fixedchar)" on page 8-46. That section also has some additional conceptual information. If you also enable the Oracle customizer summary flag, the number of usages of the Oracle setFixedCHAR() API (used behind the scenes for fixedchar functionality) will be displayed. See "Oracle Customizer Summary Option (summary)" on page A-27 for an example.

Command-line syntax is: -P-Cfixedchar

Command-line example is: -P-Cfixedchar

Properties file syntax is: profile.Cfixedchar

Properties file example is: profile.Cfixedchar

Default value is: false

Oracle Customizer Show-SQL Option (showSQL) Use the showSQL flag to display any SQL statement transformations performed by Oracle customizer. Such transformations are necessary in cases where SQLJ supports syntax that Oracle10i does not. To show SQL transformations when translating and customizing the application MyApp: % sqlj -P-CshowSQL MyApp.sqlj

In this example, the MyApp profiles will be created and customized and their SQL transformations displayed in a single running of SQLJ. To show SQL transformations when customizing MyApp profiles previously created: % sqlj -P-CshowSQL MyApp_SJProfile*.ser

In this example, the MyApp profiles were created (and possibly customized) in a previous running of SQLJ and will be customized (if needed) and have their SQL transformations displayed in the above running of SQLJ. The showSQL output might include an entry such as this: MyApp.sqlj:14: Info: #sql {BEGIN

? := VALUES(tkjsSET_f1); END};

Customization and Specialized Customizers

A-25

Customization Options and Choosing a Customizer

in file MyApp, line 14, we had: #sql {set :v1= VALUES(tkjsSET_f1) };

SQLJ supports the SET statement, but Oracle10i does not. During customization, Oracle customizer replaces the SET statement with an equivalent PL/SQL block. If customization does not take place because a valid previous customization is detected, the showSQL option shows SQL transformations regardless.

Note:

Command-line syntax is: -P-CshowSQL

Command-line example is: -P-CshowSQL

Properties file syntax is: profile.CshowSQL

Properties file example is: profile.CshowSQL

Default value is: false

Oracle Customizer Statement Cache Size Option (stmtcache) Use the Oracle customizer stmtcache option to set the statement cache size—the number of statements that can be cached for each database connection as your application runs—or to disable statement caching. The default statement cache size is 5. For an overview of statement caching, see "Statement Caching" on page 10-3. With the default Oracle-specific code generation (-codegen=oracle), SQLJ does not produce profiles and skips the customization step. In this case, use connection context methods to control SQLJ statement caching. See "Connection Context Methods for Statement Caching (Oracle-Specific Code)" on page 10-3. Important:

You can set the statement cache size on the command line or in a properties file. To use the command line to set the statement cache size to 15 (for example) for the application MyApp: % sqlj -P-Cstmtcache=15 MyApp.sqlj

To disable statement caching, set the cache size to 0: % sqlj -P-Cstmtcache=0 MyApp.sqlj

A-26 Oracle Database SQLJ Developer’s Guide and Reference

Customization Options and Choosing a Customizer

You also can alter the statement cache size in an existing profile without retranslating the application, but you must also use the Oracle customizer force option to force a recustomization, as follows: % sqlj -P-Cforce -P-Cstmtcache=15 MyApp_SJProfile0.ser

If you have multiple profiles, you can set their statement cache sizes individually by running SQLJ separately for each profile, after you have translated your application: % sqlj -P-Cforce -P-Cstmtcache=10 MyApp_SJProfile0.ser % sqlj -P-Cforce -P-Cstmtcache=15 MyApp_SJProfile1.ser % sqlj -P-Cforce -P-Cstmtcache=0 MyApp_SJProfile2.ser

Of course, you must determine which profile corresponds to each of your connection context classes. This is determined as follows: profile 0 will correspond to the connection context class used for the first executable statement in your application; profile 1 will correspond to the connection context class used for the first executable statement that does not use the first connection context class, and so on. You can verify the correlation by using the customizer harness print option to examine each profile. Command-line syntax is: -P-Cstmtcache=value

Command-line example is: -P-Cstmtcache=10

Properties file syntax is: profile.Cstmtcache=value

Properties file example is: profile.Cstmtcache=10

Default value is: 5

Oracle Customizer Summary Option (summary) Use the summary flag to instruct Oracle customizer to display a summary of Oracle features used in an application being translated, or in specified profile files. This is useful in identifying features that would prevent portability to other platforms and can be accomplished either during a full SQLJ translation run or on profiles previously created. To see summary output when translating and customizing the application MyApp: % sqlj -P-Csummary MyApp.sqlj

In this example, the MyApp profiles will be created, customized, and summarized in a single running of SQLJ. To see summary output for MyApp profiles previously created: % sqlj -P-Csummary MyApp_SJProfile*.ser

In this example, the MyApp profiles were created (and possibly customized) in a previous running of SQLJ and will be customized (if needed) and summarized in the above running of SQLJ.

Customization and Specialized Customizers

A-27

Customization Options and Choosing a Customizer

Following are two samples resulting from a -P-Csummary setting when using the default Oracle customizer. The first example indicates no Oracle features are used: MyApp_SJProfile0.ser: Info: Oracle features used: MyApp_SJProfile0.ser: Info: * none

This second example indicates that Oracle features are used—several Oracle extended data types from the oracle.sql package—and lists them: MyApp_SJProfile0.ser: MyApp_SJProfile0.ser: MyApp_SJProfile0.ser: MyApp_SJProfile0.ser: MyApp_SJProfile0.ser:

Info: Info: Info: Info: Info:

Oracle features used: * oracle.sql.NUMBER: 2 * oracle.sql.DATE: 2 * oracle.sql.CHAR: 2 * oracle.sql.RAW: 2

The following example prints out the number of usages of the Oracle setFixedCHAR() API (enabled through the Oracle customizer fixedchar option, to account for blank padding when binding a string into a WHERE clause for comparison against CHAR data): % sqlj -P-Cfixedchar -P-Csummary -P-Cforce *.ser FC_SJProfile0.ser: Info: re-installing Oracle customization FC_SJProfile0.ser: Info: Oracle features used: FC_SJProfile0.ser: Info: * setFixedCHAR(): 4

If customization does not take place because a valid previous customization is detected, the summary option produces a summary regardless.

Note:

Command-line syntax is: -P-Csummary

Command-line example is: -P-Csummary

Properties file syntax is: profile.Csummary

Properties file example is: profile.Csummary

Default value is: false

Options for Other Customizers The Oracle SQLJ implementation provides additional, specialized customizers described later in this chapter. These customizers also have command-line options: ■

SQLCheckerCustomizer (for profile semantics-checking): See "SQLCheckerCustomizer for Profile Semantics-Checking" on page A-30 for general information, and "SQLCheckerCustomizer Options" on page A-32 for information about its options.

A-28 Oracle Database SQLJ Developer’s Guide and Reference

JAR Files for Profiles



AuditorInstaller (for debugging): See "AuditorInstaller Customizer for Debugging" on page A-33 for general information, and "AuditorInstaller Options" on page A-36 for information about its options.

SQLJ Translator Options for Profile Customization The following SQLJ translator options relate to profile customization and are described elsewhere in this manual: ■

-default-customizer: Specify the default profile customizer to use if none is specified in the customizer harness -customizer option. See "Default Profile Customizer (-default-customizer)" on page 8-67.



-profile: Specify whether to customize during this running of SQLJ. See "Profile Customization Flag (-profile)" on page 8-52.

JAR Files for Profiles As discussed previously, you can specify a JAR file on the SQLJ command line in order to customize any profiles that the JAR file contains. Note: ■





Remember that you can specify .sqlj or .java files or both on the SQLJ command line for standard SQLJ processing, or you can specify .ser or .jar files or both on the command line for customization only, but not both categories. It is permissible for the .jar file to contain files that are not profiles. Any file whose manifest entry indicates that the file is not a profile will be ignored during customization. The .jar file is used as the class-loading context for each profile it contains. If a profile contains a reference to a class contained within the .jar file, then that class is loaded from the .jar file. If a profile contains a reference to a class not in the .jar file, then the system class loader will find and load the class according to your classpath, as usual.

JAR File Requirements There are requirements for the manifest entry of each profile. Create a plain text file with two lines for each profile that will be included in the JAR file. One line starts with "Name:", followed by the path or package and name. The other line is the following: SQLJProfile: TRUE

The two lines must be consecutive (no blank line in between), and there must be a blank line preceding line-pairs for additional profiles. Use the JAR utility -m option to input this file. For example, presume your MyApp application (in the directory foo/bar) has three profiles, and you will be creating a JAR file that will include these profiles. Complete the following steps:

Customization and Specialized Customizers

A-29

SQLCheckerCustomizer for Profile Semantics-Checking

1.

Create a text file with the following eight lines (including the blank lines used as separators): Name: foo/bar/MyApp_SJProfile0.ser SQLJProfile: TRUE Name: foo/bar/MyApp_SJProfile1.ser SQLJProfile: TRUE Name: foo/bar/MyApp_SJProfile2.ser SQLJProfile: TRUE

Presume you call this file MyAppJarEntries.txt. 2.

When you run jar to create the JAR file, use the -m option to input your text file as follows (presume you want to call the JAR file myjarfile.jar):

% jar -cvfm myjarfile.jar MyAppJarEntries.txt foo/bar/MyApp_SJProfile*.ser foo/bar/*.class

As the JAR utility constructs the manifest during creation of the JAR file, it reads your text file and inserts the SQLJProfile: TRUE line into the manifest entry of each profile. It accomplishes this by matching the names in the manifest with the names you specify in your text file.

JAR File Logistics When you specify a JAR file on the SQLJ command line, each profile in the JAR file is deserialized and customized. A JAR file is successfully customized only if all the profiles it contains are successfully customized. After a successful customization, each profile has been reserialized into a .ser file, the JAR file has been modified to replace the original .ser files with the customized .ser files, and the JAR file manifest has been updated to indicate the new entries. If any error is encountered in the customization of any profile in a JAR file, then the JAR file customization has failed, and the original JAR file is left completely unchanged. If you use signature files for authentication, the signature files that appeared in the original JAR file will appear unchanged in the updated JAR file. You are responsible for resigning the new JAR file if the profiles require signing.

Note:

SQLCheckerCustomizer for Profile Semantics-Checking Oracle provides a special customizer, SQLCheckerCustomizer, that will perform semantics-checking on a profile that was produced during previous execution of the translator. This semantics-checking is similar to what is usually performed during translation of the source code. This is particularly valuable when the database to be used at run time is not available for semantics-checking during translation. In these circumstances, you can use SQLCheckerCustomizer after deployment, against the run time database, typically in a scenario where the source code is no longer available. You can specify the checker to use. If you accept the default OracleChecker front end, SQLCheckerCustomizer will perform online semantics-checking using an appropriate online checker. A-30 Oracle Database SQLJ Developer’s Guide and Reference

SQLCheckerCustomizer for Profile Semantics-Checking

For online semantics-checking of the profile, you must also specify connection parameters using the customizer harness connection options.

Note:

Invoking SQLCheckerCustomizer with the Customizer Harness verify Option Following are examples of how to specify the Oracle customizer harness verify option to run SQLCheckerCustomizer in its default mode. Because it defaults to an online checker, you typically must provide connection parameters through the customizer harness user, password, and url options. (The first example is a single wraparound command line.) % sqlj -P-verify -P-user=scott -P-url=jdbc:oracle:oci:@ Foo_SJProfile0.ser Bar_SJProfile0.ser Password: password % sqlj -P-verify -P-user=scott -P-url=jdbc:oracle:oci:@ *.ser Password: password

The verify option results in the customizer harness instantiating and invoking the following class: sqlj.runtime.profile.util.SQLCheckerCustomizer

This class coordinates semantics-checking of the SQL operations in the profile. You can specify a semantics-checker or accept the default OracleChecker semantics-checker front end. The -P-verify option is equivalent to the following: -P-customizer=sqlj.runtime.profile.util.SQLCheckerCustomizer

This overrides the customizer specified in the SQLJ -default-customizer option. Note: ■





As with any Oracle customizer, help output and an option list will be provided if you specify -P-verify together with -P-help on the SQLJ command line. It is important to realize that because the verify option invokes a customizer, and only one customizer can run in any single running of SQLJ, you cannot do any other customization when you use this option. You also cannot use more than one of -P-print, -P-debug, and -P-verify simultaneously, because each of these invokes a specialized customizer.

Command-line syntax is: sqlj -P-verify profile_list

Command-line example is: sqlj -P-verify Foo_SJProfile*.ser

Properties file syntax is:

Customization and Specialized Customizers

A-31

SQLCheckerCustomizer for Profile Semantics-Checking

profile.verify

(You must also specify profiles, and typically customizer harness connection options, in the SQLJ command line.) Properties file example is: profile.verify

Default value is: NA

SQLCheckerCustomizer Options Like any customizer, SQLCheckerCustomizer has its own options, which can be set using the -P-C prefix on the SQLJ command line or the profile.C prefix in a SQLJ properties file. SQLCheckerCustomizer supports the following options: ■



checker: Specify the semantics-checker to use. The default is the OracleChecker front end, as for checking during SQLJ translation. warn: Specify the categories of warnings and messages to display during semantics-checking of the profile. This is equivalent to the SQLJ -warn flag for warning categories during translation-time semantics-checking, supports the same settings, and uses the same defaults. See "Translator Warnings (-warn)" on page 8-33.

SQLCheckerCustomizer Semantics-Checker Option (checker) The checker option enables you to specify the semantics-checker to use in checking the SQL operations in a profile. This defaults to the Oracle semantics-checker front end, oracle.sqlj.checker.OracleChecker, which for SQLCheckerCustomizer chooses an appropriate online checker for your environment. For more information about OracleChecker, see "Semantics-Checkers and OracleChecker Front End (default checker)" on page 8-56. Following is a full command-line example, showing how to use the SQLCheckerCustomizer checker option, in conjunction with the customizer harness verify option and connection options. % sqlj -P-verify -P-user=scott -P-url=jdbc:oracle:oci:@ -P-Cchecker=abc.def.MyChecker *.ser Password: password

(This is a single wraparound command line.) Command-line syntax is: -P-Cchecker=checker_class

Command-line example is: -P-Cchecker=a.b.c.MyChecker

Properties file syntax is: profile.Cchecker=checker_class

A-32 Oracle Database SQLJ Developer’s Guide and Reference

AuditorInstaller Customizer for Debugging

Properties file example is: profile.Cchecker=a.b.c.MyChecker

Default value is: oracle.sqlj.checker.OracleChecker

SQLCheckerCustomizer Warnings Option (warn) The warn option is equivalent to the SQLJ translator -warn option, enabling you to choose the categories of warnings and messages to be displayed as semantics-checking is performed on a profile. For a complete description of the functionality and possible settings of these options, see "Translator Warnings (-warn)" on page 8-33. This defaults to the all,noverbose,noportable settings, resulting in all warning categories except verbose and portable being enabled. You will receive any warnings regarding inheritance hierarchy requirements, data precision, conversion loss for nullable data, and strict matching for named iterators. These are the same defaults as for warnings during SQLJ translation. Following is a full command-line example showing how to use the SQLCheckerCustomizer warn option, in conjunction with the customizer harness verify option and connection options. This would result in only portability warnings being displayed. % sqlj -P-verify -P-user=scott -P-url=jdbc:oracle:oci:@ -P-Cwarn=none,portable *.ser Password: password

(This is a single wraparound command line.) Command-line syntax is: -P-Cwarn=comma-delimited_list_of_flags

Command-line example is: -P-Cwarn=none,verbose

Properties file syntax is: profile.Cwarn=comma-delimited_list_of_flags

Properties file example is: profile.Cwarn=none,verbose

Default value is: all,noverbose,noportable

AuditorInstaller Customizer for Debugging For ISO code generation, SQLJ provides a special customizer, AuditorInstaller. This customizer will insert sets of debugging statements, known as auditors, into profiles specified on the SQLJ command line. These profiles must already exist from previous customization.

Customization and Specialized Customizers

A-33

AuditorInstaller Customizer for Debugging

The debugging statements will execute during SQLJ run time (when someone runs your application), displaying a trace of method calls and values returned. Use the customizer harness debug option, preceded by -P- as with any general customization option, to insert the debugging statements. (Syntax for this option is discussed in "Invoking AuditorInstaller with the Customizer Harness debug Option" on page A-34.)

Overview of Auditors and Code Layers When an application is customized, Oracle customizer implements profiles in layers of code (typically less than five) for different levels of run time functionality. The deepest layer uses straight Oracle JDBC calls and implements any of your SQLJ statements that can be executed through JDBC functionality. Each higher layer is a specialized layer for some category of SQLJ functionality that is not supported by JDBC and so must be handled specially by the SQLJ run time. For example, a layer for iterator conversion statements (CAST) is used to convert JDBC result sets to SQLJ iterators. Another layer is used for assignment statements (SET). At run time, each SQLJ executable statement is first passed to the shallowest layer and then passed, layer-by-layer, until it reaches the layer that can process it (usually the deepest layer, which executes all JDBC calls). You can install debugging statements at only one layer during a single execution of AuditorInstaller. Each set of debugging statements installed at a particular layer of code is referred to as an individual auditor. During run time, an auditor is activated whenever a call is passed to the layer at which the auditor is installed. Any one of the specialized code layers above the JDBC layer is usually of no particular interest during debugging, so it is typical to install an auditor at either the deepest layer or the shallowest layer. If you install an auditor at the shallowest layer, its run time debugging output will be a trace of method calls resulting from all your SQLJ executable statements. If you install an auditor at the deepest layer, its run time output will be a trace of method calls from all your SQLJ executable statements that result in JDBC calls. Use multiple executions of AuditorInstaller to install auditors at different levels. You might want to do that to install auditors at both the deepest layer and the shallowest layer, for example. See "AuditorInstaller Depth Option (depth)" on page A-37 for information about how to specify the layer at which to install an auditor.

Invoking AuditorInstaller with the Customizer Harness debug Option Following are examples of how to specify the Oracle customizer harness debug option to run AuditorInstaller in its default mode: % sqlj -P-debug Foo_SJProfile0.ser Bar_SJProfile0.ser % sqlj -P-debug *.ser % sqlj -P-debug myappjar.jar

The debug option results in the customizer harness instantiating and invoking the following class: % sqlj.runtime.profile.util.AuditorInstaller

This class performs the work of inserting the debugging statements. A-34 Oracle Database SQLJ Developer’s Guide and Reference

AuditorInstaller Customizer for Debugging

The -P-debug option is equivalent to the following: -P-customizer=sqlj.runtime.profile.util.AuditorInstaller

This overrides the customizer specified in the SQLJ -default-customizer option. Be aware of the following: ■







To run an application with auditors installed, the SQLJ file translator.jar must be in your classpath. (Usually, running a already translated SQLJ application requires only a runtime library.) As with any Oracle customizer, help output and an option list will be provided if you specify -P-debug together with -P-help on the SQLJ command line. It is important to realize that because the debug option invokes a customizer, and only one customizer can run in any single running of SQLJ, you cannot perform any other customization when you use this option. You also cannot use more than one of -P-print, -P-debug, and -P-verify simultaneously, because each of these invokes a specialized customizer.

Command-line syntax is: sqlj -P-debug profile_list

Command-line example is: sqlj -P-debug Foo_SJProfile*.ser

Properties file syntax is: profile.debug

(You must also specify profiles in the file list.) Properties file example is: profile.debug

Default value is: NA

AuditorInstaller Run Time Output During run time, debugging statements placed by AuditorInstaller result in a trace of methods called and values returned. This happens for all profile layers that had debugging statements installed. There is no means of selective debug output at run time. AuditorInstaller output relates to profiles only; there is currently no mapping to lines in your original .sqlj source file. Following is a sample portion of AuditorInstaller run-time output. This is what the output might look like for a SQLJ SELECT INTO statement: oracle.sqlj.runtime.OraProfile@1 . getProfileData ( ) oracle.sqlj.runtime.OraProfile@1 . getProfileData returned sqlj.runtime.profile.ref.ProfileDataImpl@2 oracle.sqlj.runtime.OraProfile@1 . getStatement ( 0 ) oracle.sqlj.runtime.OraProfile@1 . getStatement returned oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 . setMaxRows ( 1000 )

Customization and Specialized Customizers

A-35

AuditorInstaller Customizer for Debugging

oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTResultSet@6 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTResultSet@6 oracle.sqlj.runtime.OraRTResultSet@6 oracle.sqlj.runtime.OraRTResultSet@6 oracle.sqlj.runtime.OraRTResultSet@6 oracle.sqlj.runtime.OraRTResultSet@6 oracle.sqlj.runtime.OraRTResultSet@6

. . . . . . . . . . .

setMaxRows returned setMaxFieldSize ( 3000 ) setMaxFieldSize returned setQueryTimeout ( 1000 ) setQueryTimeout returned setBigDecimal ( 1 , 5 ) setBigDecimal returned setBoolean ( 2 , false ) setBoolean returned executeRTQuery ( ) executeRTQuery returned

. . . . . . . . . .

getWarnings ( ) getWarnings returned null executeComplete ( ) executeComplete returned next ( ) next returned true getBigDecimal ( 1 ) getBigDecimal returned 5 getDate ( 7 ) getDate returned 1998-03-28

There are two lines for each method call. The first shows the call and input parameters; the second shows the return value. The classes you see in the oracle.sqlj.runtime package are SQLJ run time classes with equivalent functionality to similarly named JDBC classes. For example, OraRTResultSet is the SQLJ run time implementation of the JDBC ResultSet interface, containing equivalent attributes and methods.

Note:

AuditorInstaller Options As with any customizer, AuditorInstaller has its own options that can be set using the -P-C prefix on the SQLJ command line (or profile.C in a SQLJ properties file). AuditorInstaller supports the following options: ■











depth: Specify how deeply you want to go into the layers of run time functionality in your profiles. log: Specify the target file for run time output of the debugging statements of the installed auditor. prefix: Specify a prefix for each line of run time output that will result from this installation of debugging statements. showReturns: Enable the installed auditor to include return arguments in its run time call tracing. showThreads: Enable the installed auditor to include thread names in its run time call tracing (relevant only for multithreaded applications). uninstall: Remove the debugging statements placed into the profiles during the most recent previous invocation of AuditorInstaller on those profiles.

A-36 Oracle Database SQLJ Developer’s Guide and Reference

AuditorInstaller Customizer for Debugging

AuditorInstaller Depth Option (depth) As discussed in "Overview of Auditors and Code Layers" on page A-34, AuditorInstaller can install a set of debugging statements, known as an auditor, at only a single layer of code during any one execution. The AuditorInstaller depth option enables you to specify which layer. Use multiple executions of AuditorInstaller to install auditors at different levels. Layers are numbered in integers. The shallowest depth is layer 0; a maximum depth of 2 or 3 is typical. The only depth settings typically used are 0 for the shallowest layer or -1 for the deepest layer. In fact, it is difficult to install an auditor at any other particular layer, because the layer numbers used for the various kinds of SQLJ executable statements are not publicized. The depth option is sometimes used in conjunction with the prefix option. By running AuditorInstaller more than once, with different prefixes for different layers, you can see at runtime what information is coming from which layers. If you do not set the depth option, or the specification exceeds the number of layers in a given profile, then an auditor will be installed at the deepest layer. Command-line syntax is: -P-Cdepth=n

Command-line example is: -P-Cdepth=0

Properties file syntax is: profile.Cdepth=n

Properties file example is: profile.Cdepth=0

Default value is: -1 (deepest layer)

AuditorInstaller Log File Option (log) Use the log option to specify an output file for runtime output that will result from the auditor that you are currently installing. Otherwise, standard output will be used, so that debug output will go to wherever SQLJ messages go. When auditors write messages to an output file, they append; they do not overwrite. Therefore, you can specify the same log file for multiple auditors without conflict. In fact, it is typical in this way to have debug information from all layers of your application go to the same log file. Command-line syntax is: -P-Clog=log_file

Command-line example is: -P-Clog=foo/bar/mylog.txt

Properties file syntax is: profile.Clog=log_file

Customization and Specialized Customizers

A-37

AuditorInstaller Customizer for Debugging

Properties file example is: profile.Clog=foo/bar/mylog.txt

Default value is: Empty (for standard output)

AuditorInstaller Prefix Option (prefix) Use the prefix option to specify a prefix for each line of runtime output resulting from the debugging statements installed during this invocation of AuditorInstaller. This option is often used in conjunction with the depth option. By running AuditorInstaller multiple times with different prefixes for different layers, you can easily see at runtime what information is coming from which layers. Command-line syntax is: -P-Cprefix="string"

Command-line example is: -P-Cprefix="layer 2: "

Properties file syntax is: profile.Cprefix="string"

Properties file example is: profile.Cprefix="layer 2: "

Default value is: Empty

AuditorInstaller Return Arguments Option (showReturns) Use the showReturns option to enable or disable the display of return arguments as part of the runtime call tracing. This is enabled by default. The following few lines show sample output with showReturns enabled (default): oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTResultSet@6 oracle.sqlj.runtime.OraRTResultSet@6 oracle.sqlj.runtime.OraRTResultSet@6 oracle.sqlj.runtime.OraRTResultSet@6 oracle.sqlj.runtime.OraRTResultSet@6 oracle.sqlj.runtime.OraRTResultSet@6

. . . . . . . .

executeComplete ( ) executeComplete returned next ( ) next returned true getBigDecimal ( 1 ) getBigDecimal returned 5 getDate ( 7 ) getDate returned 1998-03-28

With showReturns disabled, the output would appear as follows: oracle.sqlj.runtime.OraRTStatement@3 oracle.sqlj.runtime.OraRTResultSet@6 oracle.sqlj.runtime.OraRTResultSet@6 oracle.sqlj.runtime.OraRTResultSet@6

. . . .

executeComplete ( ) next ( ) getBigDecimal ( 1 ) getDate ( 7 )

A-38 Oracle Database SQLJ Developer’s Guide and Reference

AuditorInstaller Customizer for Debugging

Instead of both a call line and a return line for each method call, there is only a call line. Command-line syntax is: -P-CshowReturns

Command-line example is: -P-CshowReturns=false

Properties file syntax is: profile.CshowReturns

Properties file example is: profile.CshowReturns=false

Default value is: true

AuditorInstaller Thread Names Option (showThreads) Use the showThreads option to enable or disable the display of thread names as part of the runtime call tracing (relevant only for multithreaded applications). This is disabled by default. When this option is enabled, thread names prefix the method names in the trace output. Command-line syntax is: -P-CshowThreads

Command-line example is: -P-CshowThreads

Properties file syntax is: profile.CshowThreads

Properties file example is: profile.CshowThreads

Default value is: false

AuditorInstaller Uninstall Option (uninstall) Use the uninstall option to remove debugging statements placed during previous invocations of AuditorInstaller. Each time you use the uninstall option, it will remove the auditor most recently installed. To remove all auditors from a profile, run AuditorInstaller repeatedly until you get a message indicating that the profile was unchanged. Command-line syntax is: -P-Cuninstall

Customization and Specialized Customizers

A-39

AuditorInstaller Customizer for Debugging

Command-line example is: -P-Cuninstall

Properties file syntax is: profile.Cuninstall

Properties file example is: profile.Cuninstall

Default value is: Disabled

Full Command-Line Examples Following are some full SQLJ command-line examples showing the specification of AuditorInstaller options. Insert a set of debugging statements, or auditor, into the deepest layer (which is the default layer), with runtime output to standard output: % sqlj -P-debug MyApp_SJProfile*.ser

Insert an auditor into the deepest layer, with runtime output to log.txt: % sqlj -P-debug -P-Clog=foo/bar/log.txt MyApp_SJProfile*.ser

Insert an auditor into the deepest layer, with runtime output to standard output, showing thread names but not return arguments: % sqlj -P-debug -P-CshowThreads=true -P-CshowReturns=false MyApp_SJProfile*.ser

Insert an auditor into layer 0 (the shallowest layer). Send runtime output to log.txt; prefix each line of runtime output with "Layer 0: " (the following command is a single wraparound line): % sqlj -P-debug -P-Clog=foo/bar/log.txt -P-Cdepth=0 -P-Cprefix="Layer 0: " MyApp_SJProfile*.ser

Uninstall an auditor (this uninstalls the auditor most recently installed; do it repeatedly to uninstall all auditors): % sqlj -P-debug -P-Cuninstall MyApp_SJProfile*.ser

A-40 Oracle Database SQLJ Developer’s Guide and Reference

Index A access mode settings (transactions), 7-42 alternative environments, support, 8-62 applets, using SQLJ, 2-12 arrays as iterator columns, 5-7 VARRAYs, 6-3 ASENSITIVE (cursor state), 4-5 assignment statements (SET), 4-41 assumptions, environment, 1-1 AuditorInstaller command-line examples, A-40 customizer for debugging, A-33 invoking, A-34 options, A-36 runtime output, A-35 auditors in profiles for debugging, A-34 auto-commit modifying in existing connection, 3-20 not supported in server, 11-3 specifying in new connection, 3-19

B backup option (customizer harness), A-9 backward compatibility Oracle SQLJ, general, 1-3 batch updates batch limit, 10-13 batchable and compatible statements, 10-9 batching incompatible statements, 10-14 canceling a batch, 10-12 cautions, 10-15 enabling and disabling, 10-9 error conditions during execution, 10-16 explicit and implicit batch execution, 10-10 overview, 10-9 update counts, 10-12 using implicit execution contexts, 10-15 with respect to recursive call-ins, 10-16 BetterDate (custom Java class), 6-14 BFILEs as stored function results, 5-24 BFILE support, 5-21 BigDecimal

mapping (for attributes), 6-27 support, 5-31 binary portability of profiles, 3-34 bind-by-identifier option (sqlj -bind-by-identifier), 8-55 BLOB support, 5-21 BOOLEAN type (PL/SQL), 5-7 builtintypes option (JPublisher -builtintypes),

6-27

C C prefix (sqlj -C-x), 8-48 cache option (sqlj -cache), 8-60 caching online checker results, 8-60 caching statements, 10-3 CALL syntax for stored procedures, 4-43 calling stored functions, 4-44 calling stored procedures, 4-43 calls to runtime, generated, 9-5 case option (JPublisher -case), 6-26 case-sensitive SQL UDT names, 6-9, 6-10, 6-25, 6-31 cause/action output for errors, 8-36 CHAR comparisons, blank padding, 8-46, A-24 character encoding command line example, 9-18 for messages, 9-17 for source, 9-17 overview, 9-15 setting at runtime, 9-22 using native2ascii, 9-22 check source name against. public class, 8-65 check sources, expand resolution search, 8-54 checker option (SQLCheckerCustomizer), A-32 checkfilename option (sqlj -checkfilename), 8-65 checksource option (sqlj -checksource), 8-54 class loading in server, 11-5 class schema object naming generated, 11-16 loaded, 11-8 classpath and path, 1-4 classpath option (sqlj -classpath), 8-17 clauses, SQLJ executable statements, 4-9 client-side translation to run in server, 11-5 CLOB support, 5-21 close() method (DefaultContext), 3-12 close() method (ExecutionContext), 7-30

Index-1

close() method (Oracle class), 3-10, 3-12 CLOSE_CONNECTION, 7-47 code generation general information, 9-3 Oracle-specific vs. ISO standard, 3-31 translator -codegen option, 8-41 code layers in profiles, A-34 codegen option (SQLJ -codegen), 8-41 collections about custom Java classes, 6-4 creating collection types, 6-18 datatypes, 6-4 fundamentals, 6-3 mapping to alternative classes, 6-29 ORAData specifications, 6-5 overview of collection support, 6-1 specifying type mapping, 6-24, 6-27 strongly typed, 6-44 weak types, restrictions, 6-57 weak types, support, 6-57 column definitions (types/sizes) general information, 10-16 Oracle customizer optcols option, A-20 SQLJ -optcols option, 8-41 command line (translator) echoing without executing, 8-12 example, 8-12 overview, 8-1 syntax and arguments, 8-9 commit automatic vs. manual, 3-19 effect on iterators and result sets, 3-21 manual, 3-20 modifying auto-commit in existing connection, 3-20 specifying auto-commit in new connection, 3-19 compat(ibility) option (Oracle customizer), A-19 compatible option (JPublisher -compatible), 6-24 compilation compiling in two passes, 8-66 debug option in server, 11-14 during translation, 9-6 enabling/disabling, 8-51 in server, 11-5 compile option (sqlj -compile), 8-51 compiler classpath option, 8-17 option support for javac, 8-7 options through SQLJ, 8-48 related options, 8-62 required behavior, 8-63 specifying name, 8-63 compiler encoding support option (sqlj), 8-64 compiler executable option (sqlj), 8-63 compiler output file option (sqlj -compiler...), 8-65 components option (sqlj -components), 8-39 configuration and installation verification, 1-3 connect string for OCI driver, 3-2 for Thin driver, 3-3

Index-2

server-side internal driver, 3-3 server-side Thin driver, 3-3 SIDs deprecated, 1-6 use of database service names, 1-6 connect() method (Oracle class), 3-9 connection contexts close connection, 7-7 concepts, 7-2 converting from JDBC connection, 7-46 converting to JDBC connection, 7-44 declaration with IMPLEMENTS clause, 7-8 declarations, 4-3 declaring connection context class, 7-4 from SQLJ data sources, 7-11, 7-14 get default connection, 7-7 get execution context, 7-7 get JDBC connection, 7-7 implementation and functionality, 7-7 instantiating connection object, 7-5 methods, 7-7 multiple connections, example, 7-6 relation to execution contexts, 7-24 semantics-checking, 7-9 set default connection, 7-7 specifying connection for statement, 7-5 specifying for executable statement, 4-10 connections closing, 3-8 closing shared connections with JDBC, 7-47 database connection in server, 11-3 from SQLJ data sources, 7-11, 7-14 JDBC transaction methods, 7-43 modifying auto-commit, 3-20 multiple, using declared connect contexts, 3-9 Oracle class to connect, 3-9 set up, 1-6 shared connections with JDBC, 7-46 single or multiple using default context, 3-5 specifying auto-commit, 3-19 translator options, 8-25 verify, 1-7 context expressions evaluation at runtime, 4-17 overview, 4-17 context option (customizer harness), A-9 converting .ser profiles to .class, 8-53 CURSOR syntax (nested tables), 6-44 custom Java classes about custom Java classes, 6-4 compiling, 6-12 creation by JPublisher, 6-20 examples, 6-34 extending, 6-37 generation by JPublisher, 6-23 mapping to alternative classes, 6-29 reading and writing data, 6-13 requirements, 6-8 sample class, 6-14 specifying member names, 6-32 strongly typed, definition, 6-2

support for object methods, 6-7 using to serialize object, 6-52 weakly typed, definition, 6-2 CustomDatum (deprecated), 6-6 customization converting .ser profiles to .class, 8-53 creation and registration, A-5 customizer harness connection options, A-12 customizer harness general options, A-8 customizer harness options overview, A-7 defining column types/sizes, A-20 defining parameter sizes, A-22 during translation, 9-7 enabling/disabling, 8-52 error and status messages, A-6 force customization, A-20 jar file usage, A-29 more about customization, A-3 options, A-6 options to invoke special customizers, A-15 Oracle customizer options, A-18 overview/syntax of customizer-specific options, A-18 parameter default sizes, A-23 related SQLJ options, A-29 show SQL transformations, A-25 statement cache size, A-26 steps in process, A-4 summary of Oracle features used, A-27 version compatibility, A-19 customizer, 3-33 customizer harness connection options, A-12 general options, A-8 invoke special customizers, A-15 options overview, A-7 overview, A-4 customizer option (customizer harness), A-10 customizers choosing, A-6 option to choose customizer, A-10 overview, A-4 passing options through SQLJ, 8-50 specifying default, 8-67

D d option (sqlj -d), 8-22 data source support associating a connection, 7-10 associating a default context, 7-11 auto-commit mode, 7-10 dataSource (WITH clause), 4-5 general overview, 7-9 requirements, 7-11 SQLJ data source classes, 7-12 SQLJ data source interfaces, 7-11 SQLJ-specific data sources, 7-11 database connection, verify, 1-7 database URL

default prefix for online checking, 8-32 SIDs deprecated, 1-6 use of database service names, 1-6 DBMS_JAVA package set server output device, 11-4 set server-side options, 11-14 DBMS_LOB package, 5-21 debug option (customizer harness), A-15 debug option for compile (in server), 11-14 debugging AuditorInstaller command-line examples, A-40 AuditorInstaller customizer, A-33 AuditorInstaller options, A-36 AuditorInstaller runtime output, A-35 debug option for compile (in server), 11-14 debug option, customizer harness, A-15 in JDeveloper, 10-20 invoking AuditorInstaller, A-34 line-mapping, SQLJ source to class, 8-36 line-mapping, SQLJ source to class for jdb, 8-37 declarations connection context declarations, 4-3 IMPLEMENTS clause, 4-3 iterator declarations, 4-2 overview, 4-1 WITH clause, 4-4 default connection setting with Oracle.connect(), 3-5 setting with setDefaultContext(), 3-8 default customizer option (sqlj), 8-67 default output device in server, 11-4 default properties files (translator), 8-14 default semantics-checker, 8-56 default URL prefix option (sqlj), 8-32 DefaultContext class close() method parameters, 3-12 constructors, 3-11 key methods, 3-11 use for single or multiple connections, 3-5 defining column types/sizes, 10-16 defining parameter sizes, 10-17 demo applications (SQLJ), availability, 1-3 depth option (AuditorInstaller), A-37 digests option, jar (customizer harness), A-10 dir option (sqlj -dir), 8-24 directory for generated .class and .ser, 8-22 for generated .java, 8-24 dirty reads, 7-43 DMS support command-line options for DMS, 8-38, 10-22 examples, 10-26 overview of DMS support, 10-21 runtime commands for DMS, 10-23 sensors and metrics, 10-24 SQLJ DMS properties files, 10-23 driver option (customizer harness), A-14 driver registration option (sqlj -driver), 8-32 dropjava, 11-17 dropping Java schema objects, 11-17

Index-3

Dynamic Monitoring Service, SQLJ support, dynamic SQL defined, 2-1 in JDBC code, 7-44 in PL/SQL code, 4-11 dynamic SQL support in SQLJ examples, 7-52 introduction, 7-50 meta bind expressions, 7-51 runtime behavior, 7-52 translation-time behavior, 7-52

10-20

E echo option, without execution, 8-20 echoing command line without executing, 8-12 encoding character encoding for messages, 9-17 character encoding for source, 9-17 command line example, 9-18 do not pass option to compiler, 8-64 overview of character encoding, 9-15 setting at runtime, 9-22 specifying in server, 11-13 using native2ascii, 9-22 encoding option (in server), 11-13 encoding option, source files (sqlj -encoding), 8-21 environment assumptions and requirements, 1-1 environment variable, translator options, 8-15 environments--scenarios and limitations, 1-2 errors character encoding for messages, 9-17 customization messages, A-6 messages, codes, and SQL states, 3-17 outputting cause and action, 8-36 runtime categories, 9-13 server-side error output, 11-16 translator error, warning, info messages, 9-8 exceptions exception-handling requirements, 3-16 processing, 3-17 set up exception-handling, 3-24 using SQLException subclasses, 3-18 executable statements examples, 4-11 overview, 4-8 rules, 4-8 specifying connection/execution contexts, 4-10 SQLJ clauses, 4-9 using PL/SQL blocks, 4-11 execution contexts cancellation method, 7-28 close() method, 7-30 control methods, 7-27 creating and specifying, 7-25 method usage, example, 7-30 overview, 7-24 relation to connection contexts, 7-24 relation to multithreading, 7-31 savepoint methods, 7-29

Index-4

specifying for executable statement, 4-10 status methods, 7-27 synchronization, 7-26 update-batching methods, 7-28 exemplar schema, 3-13 exit codes, translator, 9-11 explain option (sqlj -explain), 8-36 extending iterator classes, 7-35 extending JPub-generated classes, 6-37 extensions overview, 2-3 performance extensions, 10-1 summary of features used, A-27 type extensions, 5-20

F FETCH CURRENT syntax (iterators), 7-40 FETCH syntax (scrollable positional iterators), 7-39 file name requirements and restrictions, 3-41 fixedchar option (Oracle customizer), A-24 fixedchar option (SQLJ -fixedchar), 8-46 flags for special processing, 8-51 force option (Oracle customizer), A-20 ForUpdate/updateColumns (WITH clause), unsupported, 4-6 full names (schema names), 11-8 function calls, stored, 4-44

G getConnection() method (Oracle class), 3-9 globalization support character encoding, language support, 9-14 outside of SQLJ, 9-22 overview, 2-15 related datatypes, 5-4 related Java types, 9-19 related SQLJ and Java settings, 9-16 support for Unicode characters, 9-18

H help option (customizer harness), A-11 help options (sqlj -help-xxxx), 8-18 hints in code, parameter sizes, 10-18 holdability (cursor states, WITH clause), unsupported, 4-6 host expressions basic syntax, 4-13 bind by identifier, 8-55 evaluation at runtime, 4-17 examples, 4-15 examples of evaluation at runtime, 4-18 iterators and result sets as host variables, 4-37 overview, 4-13 restrictions, 4-24 selecting a nested table, 6-45 supported types for JDBC 2.0, 5-6 type support summary, 5-1 host variables, 2-6

I IDE SQLJ integration, 2-15 IMPLEMENTS clause in connection context declarations, 7-8 in iterator declarations, 7-35 syntax, 4-3 importing required classes, 3-23 informational messages, translator, 9-8 input to translator, 2-7 INSENSITIVE (cursor state), 4-5 installation and configuration verification, 1-3 instrument option (sqlj -instrument), 8-38 instrumenting class file (linemap), 8-37 interoperability with JDBC connection contexts and connections, 7-44 iterators and result sets, 7-48 isolation level settings (transactions), 7-43 iterators accessing named iterators, 4-33 accessing positional iterators, 4-35 array columns, 5-7 as host variables, 4-37 as iterator columns (nested), 4-39 as stored function returns, 4-45 commit/rollback effect, 3-21 concepts, 4-27 converting from result sets, 7-48 converting to result sets, 7-49 declarations, 4-2 declaring named iterators, 4-31 declaring positional iterators, 4-34 declaring with IMPLEMENTS clause, 7-35 extending, 7-35 general steps in using, 4-29 instantiating/populating named iterators, 4-32 instantiating/populating positional iterators, 4-35 iterator class functionality, 7-34 named vs. positional, 4-30 nested iterators for nested tables, 6-47 overview, 4-26 positional iterators, using next(), 4-37 result set iterators (strongly typed), 4-27 result set iterators (weakly typed), 4-29, 7-36 scrollable, 7-36 scrollable result set iterators, 7-41 selecting objects and references, 6-40 set up named iterator (example), 3-25 subclassing, 7-35 using named iterators, 4-31 using positional iterators, 4-34 using weakly typed iterators, 7-50 with serialized objects, 6-55

J J prefix (sqlj -J-x), 8-48 jar file digests option, customization, A-10 jar files for profiles, A-29 Java bind expressions (dynamic SQL), 7-51

Java names vs. SQL names in server, 11-5 Java properties, getProperty(), 9-22 Java VM classpath option, 8-17 options through SQLJ, 8-48 specifying name, 8-63 JavaBeans for SQLJ connections, 7-14 javac compatibility, 8-7 JDBC 2.0 support for LOB types, 5-20 support for weakly typed Struct, Ref, Array, 6-57 types supported, 5-6 JDBC connection methods (transactions), 7-43 JDBC considerations in server, 11-3 JDBC driver registration option (sqlj -driver), 8-32 JDBC drivers Oracle drivers, 3-1 select for translation, 3-3 select/register for customization, A-14 select/register for runtime, 3-4 verify, 1-7 JDBC interoperability connection contexts and connections, 7-44 iterators and result sets, 7-48 JDBC mapping (for attributes), 6-27 JDBC vs. SQLJ, sample application, 2-8 jdblinemap option (sqlj -jdblinemap), 8-37 JDeveloper debugging with, 10-20 SQLJ integration, 2-15 JDK supported versions, 1-2 JNDI name of default data source, 7-11 use for data sources, connections, 7-9 JPublisher builtintypes option, 6-27 case option, 6-26 compatible option, 6-24 creation of custom Java classes, 6-20 custom Java class examples, 6-34 extending generated classes, 6-37 generating custom Java classes, 6-23 generating wrapper methods, 6-28 implementation of method wrappers, 6-33 input files, 6-30 lobtypes option, 6-27 mapping to alternative classes, 6-29 numbertypes option, 6-27 properties files, 6-31 specifying member names, 6-32 specifying type mapping, 6-24 sql option, 6-24 type categories and mapping options, 6-27 type mapping, 6-27 type mapping modes and option settings, 6-27 types option, 6-25 user option, 6-25 what JPublisher produces, 6-21

Index-5

K KEEP_CONNECTION, 7-47

L language support (globalization support), 9-16 linemap option (sqlj -linemap), 8-36 line-mapping SQLJ source to class file, 8-36 SQLJ source to class for jdb, 8-37 loading classes/resources into server, 11-6 loading/translating source in server, 11-11 loadjava compatibility options, SQLJ, 8-7 loading classes/resources, 11-6 loading source, translating, 11-11 output from loading source, 11-15 LOBs as iterator columns, 5-25 as stored function results, 5-24 FETCH INTO LOB host variables, 5-26 SELECT INTO LOB host variables, 5-24 support (oracle.sql and DBMS_LOB), 5-21 lobtypes option (JPublisher -lobtypes), 6-27 locale command line example, 9-18 for messages, 9-17 setting at runtime, 9-22 log option (AuditorInstaller), A-37

M mapping to alternative classes (UDTs), 6-29 member names (objects), 6-32 meta bind expressions (dynamic SQL), 7-51 method support for objects, 6-7 method wrappers (JPub), implementation, 6-33 middle-tier considerations, 3-42 multithreading in server, 11-17 in SQLJ, overview, 7-31 relation to execution contexts, 7-31 sample application, 7-32

N n option (sqlj -n) (echo without execution), 8-20 name of compiler, 8-63 name of Java VM, 8-63 named iterators accessing, 4-33 declaring, 4-31 instantiating and populating, 4-32 scrollable, 7-38 using, 4-31 naming requirements and restrictions file names, 3-41 local variables, classes (Java namespace), 3-40 SQL namespace, 3-41 SQLJ namespace, 3-41

Index-6

naming schema objects generated class, 11-16 loaded classes, 11-8 loaded resources, 11-8 source, 11-15 native2ascii for encoding, 9-22 NCHAR class (globalization support), 9-19 NcharAsciiStream class (globalization support), 9-19 ncharconv translator option, 8-4, 9-20 NcharUnicodeStream class (globalization support), 9-19 NCLOB class (globalization support), 9-19 nested iterators, 6-47 nested tables accessing, 6-44 inserting in SQLJ, 6-45 manipulating, 6-47 selecting into host expression, 6-45 types, 6-3 using nested iterator, 6-47 non-repeatable reads, 7-43 NString class, 9-19 NString class (globalization support), 9-19 null-handling examples, 3-15 wrapper classes for null-handling, 3-14 numbertypes option (JPublisher -numbertypes), 6-27

O object method wrappers (JPub), 6-33 object references selecting into iterators, 6-40 strongly typed in SQLJ, 6-39 updating in SQLJ, 6-43 weak types, restrictions, 6-57 weak types, support, 6-57 object-JDBC mapping (for attributes), 6-27 objects about custom Java classes, 6-4 creating object types, 6-17 datatypes, 6-4 fundamentals, 6-3 inserting in SQLJ, 6-42 mapping to alternative classes, 6-29 method support, 6-7 ORAData specifications, 6-5 overview of object support, 6-1 selecting into iterators, 6-40 serializing (overview), 6-50 serializing RAW and BLOB columns, 6-51 serializing with custom Java class, 6-52 specifying type mapping, 6-24, 6-27 SQLData specifications, 6-7 strongly typed in SQLJ, 6-39 updating a reference in SQLJ, 6-43 updating in SQLJ, 6-40 weak types, restrictions, 6-57 weak types, support, 6-57

wrapper methods, 6-28 OCI driver (JDBC), 3-2 offline checking default checker, Oracle checkers, 8-56 specifying checker, 8-58 offline option (sqlj -offline), 8-58 offline parsing sqlj -parse option, 8-61 steps involved, 9-2 vs. online checking, 8-57 online checking caching results, 8-60 default checker, Oracle checkers, 8-56 enabling in server, 11-13 enabling, setting user schema, 8-25 registering drivers, 8-32 setting default URL prefix, 8-32 setting password, 8-28 setting URL, 8-30 specifying checker, 8-59 vs. offline parsing, 8-57 online option (in server), 11-13 online option (sqlj -online), 8-59 opaque types, 6-58 optcols option (Oracle customizer), A-20 optcols option (SQLJ -optcols), 8-41 optimizer, SQL, 10-2 options (translator) command line only, 8-17 flags for special processing, 8-51 for connections, 8-25 for customization, 8-67 for javac compatibility, 8-7 for loadjava compatibility, 8-7 for output files and directories, 8-21 for reporting and line-mapping, 8-33 for semantics-checking, offline parsing, 8-56 for VM and compiler, 8-62 help, 8-18 order of precedence, 8-15 overview, 8-2 prefixes for passing options, 8-48 summary list, 8-2 support for alternative environments, 8-62 options for customizer harness connection options, A-12 general options, A-8 invoke special customizers, A-15 overview, A-7 options for Oracle customizer, A-18 options for translation in server fixed settings, 11-12 setting options, 11-14 supported options, 11-12 optparamdefaults option (Oracle customizer), A-23 optparamdefaults option (SQLJ -optparamdefaults), 8-44 optparams option (Oracle customizer), A-22 optparams option (SQLJ -optparams), 8-43 Oracle class

close() method parameters, 3-10 connect() method, 3-9 for DefaultContext instances, 3-9 getConnection() method, 3-9 Oracle customizer blank padding for CHAR comparisons, A-24 define column types/sizes, A-20 define parameter sizes, A-22 force customization, A-20 options, A-18 set default parameter sizes, A-23 show SQL transformation, A-25 statement cache size, A-26 summary of Oracle features used, A-27 version compatibility, A-19 Oracle extensions overview, 2-3 performance extensions, 10-1 summary of features used, A-27 type extensions, 5-20 Oracle mapping (for attributes), 6-27 Oracle optimizer, 10-2 Oracle system identifiers (SIDs) in connect strings, deprecated, 1-6 OracleChecker default checker, 8-56 Oracle-specific code generation advantages and disadvantages, 3-31 coding considerations, limitations, 3-28 introduction, 3-28, 3-39 server-side considerations, 3-31 translator/customizer usage changes, 3-30 oracle.sql package, 5-20 ORAData additional uses, 6-13 specifications, 6-5 use in custom Java classes, 6-4 versus CustomDatum, 6-6 output device in server, default, 11-4 output directory for generated .class and .ser, 8-22 for generated .java, 8-24 output file and directory options (translator), 8-21 output file for compiler, 8-65 output from server-side translator, 11-15 output from translator, 2-7 output, server-side translator errors, 11-16 Overview of SQLJ, 2-1

P P prefix (sqlj -P-x), 8-50 parameter definitions (sizes) general information, 10-17 Oracle customizer optparamdefaults option, A-23 Oracle customizer optparams option, A-22 SQLJ -optparamdefaults option, 8-44 SQLJ -optparams option, 8-43 parse option (sqlj -parse), 8-61 passes option (sqlj -passes), 8-66

Index-7

passes, two-pass compiling, 8-66 passing options to other executables, 8-48 password option (customizer harness), A-13 password option for checking (sqlj), 8-28 path (WITH clause), unsupported, 4-6 path and classpath, 1-4 performance enhancements, 10-1 performance monitoring, DMS support, 10-20 phantom reads, 7-43 PL/SQL blocks in executable statements, 4-11 BOOLEAN type, 5-7 RECORD type, 5-7 TABLE type, 5-7 positional iterators accessing, 4-35 declaring, 4-34 instantiating and populating, 4-35 navigation with next(), 4-37 scrollable, 7-39 using, 4-34 positioned delete, 5-28 positioned update, 5-28 prefetching rows, 10-2 prefix option (AuditorInstaller), A-38 prefixes to pass options to customizer, 8-50 to pass options to Java compiler, 8-48 to pass options to Java VM, 8-48 print option (customizer harness), A-16 procedure calls, stored, 4-43 profile customization (see customization), 9-7 profile option (sqlj -profile), 8-52 profile-keys, 3-36 profile-keys class, 3-34, 9-4 profiles auditors for debugging, A-34 binary portability, 3-34 code layers, A-34 creation during code generation, A-2 debug option, A-15 functionality at runtime, A-6 generated profiles, 9-4 more about profiles, A-1 overview, 3-33 print option, A-16 sample profile entry, A-2 use of jar files, A-29 verify option, A-17 properties files (translator) default properties files, 8-14 overview, 8-12 setting input file, 8-17 syntax, 8-13 properties files, SQLJ DMS, 10-23 properties, Java, getProperty(), 9-22 props option (sqlj -props), 8-17 public class name / source name check, 8-65

Index-8

R READ COMMITTED transactions, 7-43 READ ONLY transactions, 7-42 READ UNCOMMITTED transactions, 7-43 READ WRITE transactions, 7-42 RECORD type (PL/SQL), 5-7 recursive SQLJ calls in server, 11-18 REF CURSOR about REF CURSOR types, 5-30 example, 5-30 SQLJ support, 5-30 register JDBC drivers for runtime, 3-4 for translation, 8-32 registering column types/sizes, 10-16 registering parameter sizes, 10-17 REPEATABLE READ transactions, 7-43 reporting options (translator), 8-33 requirements, environment, 1-2 resource schema object naming loaded, 11-8 result expressions evaluation at runtime, 4-17 overview, 4-17 result set iterators (strongly typed) Overview, 4-27 result set iterators (weakly typed) general information, 7-36 Overview, 4-29 scrollable, 7-41 result sets as host variables, 4-37 as iterator columns, 4-39 as stored function returns, 4-45 commit/rollback effect, 3-21 converting from iterators, 7-49 converting to iterators, 7-48 persistence across calls in server, 11-3 ResultSetIterator type, 7-36 returnability (cursor states, WITH clause), 4-5, 4-7 rollback effect on iterators and result sets, 3-21 manual, 3-20 with savepoint, 3-21 row prefetching, 10-2 ROWID as stored function results, 5-27 FETCH INTO ROWID host variable, 5-27 SELECT INTO ROWID host variable, 5-27 support, 5-26 runtime categories of errors, 9-13 debugging output (AuditorInstaller), A-35 functionality, 9-11 functionality of profiles, A-6 generated calls to runtime, 9-5 globalization support, 9-13 JDBC driver selection and registration, 3-4 overview, 2-2, 3-33 packages, 9-12

set up connection, 1-6 steps in runtime processing, 2-8 test, 1-7

S sample applications JDBC vs. SQLJ, 2-8 multiple connection contexts, 7-6 multiple-row query (named iterator), 3-26 multithreading, 7-32 single-row query (SELECT INTO), 3-25 sample classes custom Java class (BetterDate), 6-14 SerializableDatum class, 6-55 savepoints ExecutionContext savepoint methods, 7-29 ISO syntax, 3-22 Oracle syntax, 3-22 savepoint statements, 3-21 schema objects naming generated classes, 11-16 naming loaded classes, 11-8 naming loaded resources, 11-8 naming sources, 11-15 scrollable iterators declaring, 7-36 scrollable named iterators, 7-38 scrollable positional iterators, 7-39 sensitivity, 7-37 the scrollable interface, 7-37 ScrollableResultSetIterator type, 7-41 SELECT INTO statements error conditions, 4-26 examples, 4-25 syntax, 4-24 semantics-checking caching online results, 8-60 default checker, Oracle checkers, 8-56 enabling online in server, 11-13 enabling online, setting user schema, 8-25 invoking SQLCheckerCustomizer, A-31 of profiles, via customizer harness, A-17 options, 8-56 registering drivers, 8-32 setting default URL prefix, 8-32 setting password, 8-28 setting URL, 8-30 specifying offline checker, 8-58 specifying online checker, 8-59 SQLCheckerCustomizer options, A-32 steps involved, 9-2 SENSITIVE (cursor state), 4-5 sensitivity (cursor states, WITH clause), 4-5 ser profiles (.ser) converting to .class, 8-53 generated profiles, 9-4 ser2class option (sqlj -ser2class), 8-53 SERIALIZABLE transactions, 7-43 serialized objects

as host variables, 6-55 in iterator columns, 6-55 overview, 6-50 SerializableDatum class (sample), 6-55 through custom Java class, 6-52 to RAW and BLOB columns, 6-51 server-side internal driver (JDBC), 3-3 server-side SQLJ class loading, 11-5 coding considerations, 11-2 compilation, 11-5 connection to database, 11-3 default output device, 11-4 dropjava, 11-17 dropping Java schema objects, 11-17 error output, 11-16 fixed settings, 11-12 generated output from translation, 11-15 Java multithreading, 11-17 JDBC differences, 11-3 loading classes/resources into server, 11-6 loading source into server, translating, 11-11 naming generated class schema objects, 11-16 naming loaded class schema objects, 11-8 naming loaded resource schema objects, 11-8 naming source schema objects, 11-15 options, 11-12 Overview, 11-1 overview, 2-13 recursive calls, 11-18 running client program in server, 11-9 setting options, 11-14 SQL names vs. Java names, 11-5 translating in server, 11-10 translating on client, 11-5 verifying code is running in server, 11-19 server-side Thin driver (JDBC), 3-3 SET (assignment) statements, 4-41 SET TRANSACTION syntax, 7-42 setFormOfUse method, 9-20 setup of SQLJ, testing, 1-5 short names (schema names), 11-8 showReturns option (AuditorInstaller), A-38 showSQL option (Oracle customizer), A-25 showThreads option (AuditorInstaller), A-39 SIDs in connect strings, deprecated, 1-6 source check for type resolution, 8-54 source file line-mapping for jdb, 8-37 general, 8-36 source files encoding option, 8-21 source name / public class name check, 8-65 source schema object naming, 11-15 SQL names vs. Java names in server, 11-5 SQL optimizer, 10-2 sql option (JPublisher -sql), 6-24 SQL replacement code (dynamic SQL), 7-52 SQL states (for errors), 3-17 SQLCheckerCustomizer for semantics-checking of profiles, A-30

Index-9

invoking, A-31 options, A-32 SQLData specifications, 6-7 use in custom Java classes, 6-4 SQLException subclasses, using, 3-18 SQLJ vs. JDBC, sample application, 2-8 SQLJ_OPTIONS environment variable, 8-15 SqljConnBean for simple connection, 7-15 SqljConnCacheBean for connection caching, 7-16 sqljutl package, 1-5 statement caching, 10-3 static SQL, defined, 2-1 status messages for customization, A-6 for translation, 9-10 translator, enabling/disabling, 8-35 status option (sqlj -status), 8-35 stmtcache option (Oracle customizer), A-26 stored function calls, 4-44 stored procedure calls, 4-43 streams as function return values, 5-19 as output parameters, 5-18 classes and methods, 5-15 examples, 5-17 general use in SQLJ, 5-9 precautions, 5-12 retrieving data, 5-13 sending data to database, 5-10 supporting classes, 5-8 strongly typed collections, 6-44 strongly typed custom Java classes, 6-2 strongly typed objects and references, 6-39 subclassing iterator classes, 7-35 summary option (Oracle customizer), A-27 Sun JDK supported versions, 1-2 synchronization of execution contexts, 7-26 syntax translator command line, 8-9 translator properties files, 8-13 system identifiers (SIDs) in connect strings, deprecated, 1-6

T TABLE syntax (nested tables), 6-44, 6-47 TABLE type (PL/SQL), 5-7 Thin driver (JDBC), 3-2 transactions access mode settings, 7-42 advanced transaction control, 7-41 automatic commit vs. manual commit, 3-19 basic transaction control, 3-18 isolation level settings, 7-43 JDBC Connection methods, 7-43 manual commit and rollback, 3-20 modifying auto-commit, 3-20 overview, 3-19

Index-10

savepoints for rollbacks, 3-21 specifying auto-commit, 3-19 transformGroup ( WITH clause), unsupported, 4-6 TRANSLATE (object member names), 6-32 translating in server to run in server, 11-10 translating on client to run in server, 11-5 translator basic translation steps, 2-5 code generation, 9-3 compilation, 9-6 customization, 9-7 error, warning, info messages, 9-8 exit codes, 9-11 globalization support, 9-13 input and output, 2-7 internal operations, 9-1 Java and SQLJ code-parsing, syntax-checking, 9-1 output, server-side, 11-15 overview, 2-2, 3-33 SQL semantics-checking and offline parsing, 9-2 status messages, 9-10 support for alternative environments, 8-62 test, 1-7 type extensions, 5-20 type mapping BigDecimal mapping, 6-27 JDBC mapping, 6-27 JPublisher mapping option, 6-24 object JDBC mapping, 6-27 Oracle mapping, 6-27 type categories and mapping modes, 6-27 type resolution, expand search, 8-54 typeMap (WITH clause), 4-5 types option (JPublisher -types), 6-25 types supported for JDBC 2.0, 5-6 summary of types, 5-1

U uninstall option (AuditorInstaller), A-39 update batching batch limit, 10-13 batchable and compatible statements, 10-9 batching incompatible statements, 10-14 canceling a batch, 10-12 cautions, 10-15 enabling and disabling, 10-9 error conditions during execution, 10-16 explicit and implicit batch execution, 10-10 overview, 10-9 update counts, 10-12 using implicit execution contexts, 10-15 with respect to recursive call-ins, 10-16 updateColumns/ForUpdate (WITH clause), unsupported, 4-6 url option (customizer harness), A-14 url option for checking (sqlj -url), 8-30 URL, database default prefix for online checking, 8-32

SIDs deprecated, 1-6 use of database service names, 1-6 user option (customizer harness), A-12 user option (JPublisher -user), 6-25 user option for checking (sqlj -user), 8-25 user-defined types, 6-17

V VALUES syntax for stored functions, 4-44 VARRAYs inserting a row, 6-50 selecting into host expression, 6-49 VARRAY types, 6-3 verbose option (customizer harness), A-12 verify option (customizer harness), A-17 version compatibility (Oracle customizer), A-19 version number options (sqlj -version-xxxx), 8-19 VM classpath option, 8-17 options through SQLJ, 8-48 specifying name, 8-63 vm option (sqlj -vm), 8-63

W warn option (SQLCheckerCustomizer), A-33 warn option (sqlj -warn), 8-33 warning messages, translator, 9-8 warnings, translator, enabling/disabling, 8-33 weak object/collection types restrictions, 6-57 support, 6-57 weakly typed custom Java classes, 6-2 weakly typed iterators, 7-36 WHERE CURRENT OF, 5-28 WHERE CURRENT OF clause, 5-28 Windows, SQLJ development in, 2-15 WITH clause syntax, 4-4 wrapper classes for null-handling, 3-14 wrapper methods (JPub), generating, 6-28

Index-11

Index-12