SQLJ Developers Guide
SQLJ Developers Guide
Release 21c
F31394-01
December 2020
Oracle Database SQLJ Developer's Guide, Release 21c
F31394-01
Contributing Authors: Tanmay Choudhury, Tulika Das, Venkatasubramaniam Iyer, Brian Wright, Janice
Nygard
Contributors: Krishna Mohan, Amit Bande, Sumit Sahu, 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
This software and related documentation are provided under a license agreement containing restrictions on
use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your
license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license,
transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse
engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is
prohibited.
The information contained herein is subject to change without notice and is not warranted to be error-free. If
you find any errors, please report them to us in writing.
If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on
behalf of the U.S. Government, then the following notice is applicable:
U.S. GOVERNMENT END USERS: Oracle programs (including any operating system, integrated software,
any programs embedded, installed or activated on delivered hardware, and modifications of such programs)
and Oracle computer documentation or other Oracle data delivered to or accessed by U.S. Government
end users are "commercial computer software" or "commercial computer software documentation" pursuant
to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such,
the use, reproduction, duplication, release, display, disclosure, modification, preparation of derivative works,
and/or adaptation of i) Oracle programs (including any operating system, integrated software, any programs
embedded, installed or activated on delivered hardware, and modifications of such programs), ii) Oracle
computer documentation and/or iii) other Oracle data, is subject to the rights and limitations specified in the
license contained in the applicable contract. The terms governing the U.S. Government’s use of Oracle cloud
services are defined by the applicable contract for such services. No other rights are granted to the U.S.
Government.
This software or hardware is developed for general use in a variety of information management applications.
It is not developed or intended for use in any inherently dangerous applications, including applications that
may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you
shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its
safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this
software or hardware in dangerous applications.
Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of
their respective owners.
Intel and Intel Inside are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are
used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Epyc,
and the AMD logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered
trademark of The Open Group.
This software or hardware and documentation may provide access to or information about content, products,
and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly
disclaim all warranties of any kind with respect to third-party content, products, and services unless otherwise
set forth in an applicable agreement between you and Oracle. Oracle Corporation and its affiliates will not
be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content,
products, or services, except as set forth in an applicable agreement between you and Oracle.
Contents
Preface
Audience xv
Related Documents xv
Documentation Accessibility xvi
Conventions xvii
2 Getting Started
2.1 Assumptions and Requirements 2-1
2.1.1 Assumptions About Your Environment 2-1
2.1.2 Requirements for Using the Oracle SQLJ Implementation 2-2
2.1.3 SQLJ Environment 2-2
2.1.4 Environment Considerations 2-3
2.1.5 SQLJ Backward Compatibility 2-3
2.2 Checking the Installation and Configuration 2-4
2.2.1 Check for Availability of SQLJ and Demo Applications 2-4
2.2.2 Check for Installed Directories and Files 2-4
2.2.3 Set the Path and Classpath 2-4
2.2.4 Verify Installation of the sqljutl Package 2-5
2.3 Testing the Setup 2-6
2.3.1 Set Up the Run-Time Connection 2-7
2.3.2 Create a Table to Verify the Database 2-7
2.3.3 Verify the JDBC Driver 2-8
2.3.4 Verify the SQLJ Translator and Run Time 2-8
2.3.5 Verify the SQLJ Translator Connection to the Database 2-9
3 Introduction to SQLJ
3.1 Overview of SQLJ 3-1
3.2 Overview of SQLJ Components 3-2
iii
3.2.1 SQLJ Translator Functionality 3-2
3.2.2 SQLJ Run Time 3-3
3.3 Overview of Oracle Extensions to the SQLJ Standard 3-3
3.3.1 SQLJ Type Extensions 3-4
3.3.2 SQLJ Functionality Extensions 3-5
3.4 Basic Translation Steps and Run-Time Processing 3-6
3.4.1 SQLJ Translation Steps 3-6
3.4.2 Summary of Translator Input and Output 3-8
3.4.2.1 Translator Input 3-9
3.4.2.2 Translator Output 3-9
3.4.2.3 Output File Locations 3-10
3.4.3 SQLJ Run-Time Processing 3-10
3.5 SQLJ Sample Code 3-11
3.5.1 SQLJ Version of the Sample Code 3-11
3.5.2 JDBC Version of the Sample Code 3-13
3.6 Alternative Deployment Scenarios 3-14
3.6.1 Running SQLJ in Applets 3-14
3.6.1.1 General Development and Deployment Considerations 3-15
3.6.1.2 General End User Considerations 3-15
3.6.1.3 Java Environment and the Java Plug-In 3-15
3.7 Alternative Development Scenarios 3-16
3.7.1 SQLJ Globalization Support 3-17
3.7.2 SQLJ in Oracle JDeveloper 10g and Other IDEs 3-17
3.7.3 Windows Considerations 3-17
iv
4.3.2 Examples of NULL-Handling 4-17
4.4 Exception-Handling Basics 4-18
4.4.1 SQLJ and JDBC Exception-Handling Requirements 4-18
4.4.2 Processing Exceptions 4-19
4.4.3 Using SQLException Subclasses 4-20
4.5 Basic Transaction Control 4-21
4.5.1 Overview of Transactions 4-21
4.5.2 Automatic Commits Versus Manual Commits 4-22
4.5.3 Specifying Auto-Commit as You Define a Connection 4-22
4.5.4 Modifying Auto-Commit in an Existing Connection 4-23
4.5.5 Using Manual COMMIT and ROLLBACK 4-23
4.5.6 Effect of Commits and Rollbacks on Iterators and Result Sets 4-24
4.5.7 Using Savepoints 4-25
4.6 Summary: First Steps in SQLJ Code 4-26
4.7 Oracle-Specific Code Generation (No Profiles) 4-31
4.7.1 Environment Requirements for Oracle-Specific Code Generation 4-31
4.7.2 Code Considerations and Limitations with Oracle-Specific Code
Generation 4-32
4.7.3 SQLJ Usage Changes with Oracle-Specific Code Generation 4-33
4.7.4 Advantages and Disadvantages of Oracle-Specific Code Generation 4-34
4.8 ISO Standard Code Generation 4-35
4.8.1 Environment Requirements for ISO Standard Code Generation 4-35
4.8.2 SQLJ Translator and SQLJ Run Time 4-36
4.8.3 SQLJ Profiles 4-36
4.8.3.1 Overview of Profiles 4-37
4.8.3.2 Binary Portability 4-37
4.8.4 SQLJ Translation Steps 4-38
4.8.5 Summary of Translator Input and Output 4-39
4.8.5.1 Translator Input 4-39
4.8.5.2 Translator Output 4-39
4.8.5.3 Output File Locations 4-41
4.8.6 SQLJ Run-Time Processing 4-41
4.8.7 Deployment Scenarios 4-42
4.9 Oracle-Specific Code Generation Versus ISO Standard Code Generation 4-44
4.10 Requirements and Restrictions for Naming 4-44
4.10.1 Java Namespace: Local Variable and Class Naming Restrictions 4-44
4.10.2 SQLJ Namespace 4-46
4.10.3 SQL Namespace 4-46
4.10.4 File Name Requirements and Restrictions 4-46
4.11 Considerations for SQLJ in the Middle Tier 4-47
v
5 Basic Language Features
5.1 Overview of SQLJ Declarations 5-1
5.1.1 Rules for SQLJ Declarations 5-2
5.1.2 Iterator Declarations 5-3
5.1.3 Connection Context Declarations 5-3
5.1.4 Declaration IMPLEMENTS Clause 5-4
5.1.5 Declaration WITH Clause 5-5
5.1.5.1 Standard WITH Clause Usage 5-5
5.1.5.2 Oracle-Specific WITH Clause Usage 5-7
5.1.5.3 Example: Returnability 5-7
5.2 Overview of SQLJ Executable Statements 5-8
5.2.1 Rules for SQLJ Executable Statements 5-9
5.2.2 SQLJ Clauses 5-9
5.2.3 Specifying Connection Context Instances and Execution Context
Instances 5-11
5.2.4 Executable Statement Examples 5-11
5.2.5 PL/SQL Blocks in Executable Statements 5-12
5.3 Java Host, Context, and Result Expressions 5-13
5.3.1 Overview of Host Expressions 5-14
5.3.2 Basic Host Expression Syntax 5-15
5.3.3 Examples of Host Expressions 5-17
5.3.4 Overview of Result Expressions and Context Expressions 5-18
5.3.5 Evaluation of Java Expressions at Run Time 5-18
5.3.6 Examples of Evaluation of Java Expressions at Run Time (ISO Code
Generation) 5-20
5.3.7 Restrictions on Host Expressions 5-25
5.4 Single-Row Query Results: SELECT INTO Statements 5-26
5.4.1 SELECT INTO Syntax 5-26
5.4.2 Examples of SELECT INTO Statements 5-27
5.4.3 Examples with Host Expressions in SELECT-List 5-27
5.4.4 SELECT INTO Error Conditions 5-28
5.5 Multirow Query Results: SQLJ Iterators 5-28
5.5.1 Iterator Concepts 5-29
5.5.1.1 Overview of Strongly Typed Iterators 5-29
5.5.1.2 Overview of Weakly Typed Iterators 5-31
5.5.2 General Steps in Using an Iterator 5-31
5.5.3 Named, Positional, and Result Set Iterators 5-32
5.5.4 Using Named Iterators 5-33
5.5.5 Using Positional Iterators 5-36
5.5.6 Using Iterators and Result Sets as Host Variables 5-39
5.5.7 Using Iterators and Result Sets as Iterator Columns 5-42
vi
5.6 Assignment Statements (SET) 5-44
5.7 Stored Procedure and Function Calls 5-45
5.7.1 Calling Stored Procedures 5-45
5.7.2 Calling Stored Functions 5-46
5.7.3 Using Iterators and Result Sets as Stored Function Returns 5-47
6 Type Support
6.1 Supported Types for Host Expressions 6-1
6.1.1 Summary of Supported Types 6-2
6.1.2 Supported Types and Requirements for JDBC 2.0 6-6
6.1.3 Using PL/SQL BOOLEAN, RECORD Types, and TABLE Types 6-8
6.1.4 Backward Compatibility for Previous Oracle JDBC Releases 6-9
6.2 Support for Streams 6-9
6.2.1 General Use of SQLJ Streams 6-10
6.2.2 Key Aspects of Stream Support Classes 6-11
6.2.3 Using SQLJ Streams to Send Data 6-11
6.2.4 Retrieving Data into Streams: Precautions 6-14
6.2.5 Using SQLJ Streams to Retrieve Data 6-15
6.2.6 Stream Class Methods 6-17
6.2.7 Examples of Retrieving and Processing Stream Data 6-19
6.2.8 SQLJ Stream Objects as Output Parameters and Function Return
Values 6-21
6.3 Support for JDBC 2.0 LOB Types and Oracle Type Extensions 6-22
6.3.1 Package oracle.sql 6-23
6.3.2 Support for BLOB, CLOB, and BFILE 6-24
6.3.3 Support for Oracle ROWID 6-29
6.3.4 Support for Oracle REF CURSOR Types 6-33
6.3.5 Support for Other Oracle Database 11g Data Types 6-35
6.3.6 Extended Support for BigDecimal 6-35
vii
7.2.4 Compiling Custom Java Classes 7-11
7.2.5 Reading and Writing Custom Data 7-12
7.2.6 Additional Uses for ORAData Implementations 7-12
7.3 User-Defined Types 7-16
7.4 Strongly Typed Objects and References in SQLJ Executable Statements 7-20
7.4.1 Selecting Objects and Object References into Iterator Columns 7-20
7.4.2 Updating an Object 7-21
7.4.3 Inserting an Object Created from Individual Object Attributes 7-22
7.4.4 Updating an Object Reference 7-23
7.5 Strongly Typed Collections in SQLJ Executable Statements 7-24
7.5.1 Accessing Nested Tables: TABLE syntax and CURSOR syntax 7-25
7.5.2 Inserting a Row that Includes a Nested Table 7-25
7.5.3 Selecting a Nested Table into a Host Expression 7-26
7.5.4 Manipulating a Nested Table Using TABLE Syntax 7-27
7.5.5 Selecting Data from a Nested Table Using a Nested Iterator 7-28
7.5.6 Selecting a VARRAY into a Host Expression 7-29
7.5.7 Inserting a Row that Includes a VARRAY 7-30
7.6 Serialized Java Objects 7-30
7.6.1 Serializing Java Classes to RAW and BLOB Columns 7-31
7.6.2 SerializableDatum: an ORAData Implementation 7-33
7.6.3 SerializableDatum in SQLJ Applications 7-35
7.6.4 SerializableDatum (Complete Class) 7-36
7.7 Weakly Typed Objects, References, and Collections 7-37
7.7.1 Support for Weakly Typed Objects, References, and Collections 7-37
7.7.2 Restrictions on Weakly Typed Objects, References, and Collections 7-38
7.8 Oracle OPAQUE Types 7-38
viii
8.1.12 Connecting to PDBs 8-25
8.2 Execution Contexts 8-25
8.2.1 Relation of Execution Contexts to Connection Contexts 8-26
8.2.2 Creating and Specifying Execution Context Instances 8-27
8.2.3 Execution Context Synchronization 8-28
8.2.4 Execution Context Methods 8-28
8.2.4.1 Status Methods 8-29
8.2.4.2 Control Methods 8-29
8.2.4.3 Cancellation Method 8-30
8.2.4.4 Update Batching Methods 8-31
8.2.4.5 Savepoint Methods 8-31
8.2.4.6 Close Method 8-32
8.2.4.7 Example: Using ExecutionContext Methods 8-32
8.2.5 Relation of Execution Contexts to Multithreading 8-33
8.3 Multithreading in SQLJ 8-33
8.4 Iterator Class Implementation and Advanced Functionality 8-36
8.4.1 Implementation and Functionality of Iterator Classes 8-36
8.4.2 Using the IMPLEMENTS Clause in Iterator Declarations 8-37
8.4.3 Support for Extending Iterator Classes 8-38
8.4.4 Result Set Iterators 8-38
8.4.5 Scrollable Iterators 8-39
8.5 Advanced Transaction Control 8-45
8.5.1 SET TRANSACTION Syntax 8-45
8.5.2 Access Mode Settings 8-46
8.5.3 Isolation Level Settings 8-46
8.5.4 Using JDBC Connection Class Methods 8-47
8.6 SQLJ and JDBC Interoperability 8-47
8.6.1 SQLJ Connection Context and JDBC Connection Interoperability 8-48
8.6.2 SQLJ Iterator and JDBC Result Set Interoperability 8-52
8.7 Support for Dynamic SQL 8-54
8.7.1 Meta Bind Expressions 8-55
8.7.2 SQLJ Dynamic SQL Examples 8-56
8.8 Using Stored Outlines 8-59
8.9 Using Plan Baselines 8-65
8.9.1 Generating Plan Baselines 8-65
8.9.2 Command-Line and Property File Options 8-66
8.9.2.1 plan_baseline 8-66
8.9.2.2 plan_prefix 8-68
8.9.2.3 plan_run 8-69
8.9.2.4 plan_fixed 8-70
8.9.2.5 plan_enabled 8-70
ix
8.9.3 Generated SQL File 8-71
8.9.3.1 Generated SQL File Name 8-71
8.9.3.2 Generated SQL File Format 8-71
8.9.4 Generated Log File 8-72
8.9.4.1 Generated Log File Name 8-72
8.9.4.2 Generated Log File Format 8-72
8.9.5 Generated Java File 8-73
x
10.2.2 Translator Status Messages 10-11
10.2.3 Translator Exit Codes 10-12
10.3 SQLJ Run Time 10-12
10.3.1 SQLJ Run Time Packages 10-13
10.3.2 Categories of Run-Time Errors 10-14
10.4 Globalization Support in the Translator and Run Time 10-15
10.4.1 Character Encoding and Language Support 10-15
10.4.2 SQLJ and Java Settings for Character Encoding and Language
Support 10-18
10.4.3 SQLJ Extended Globalization Support 10-20
10.4.4 Manipulation Outside of SQLJ for Globalization Support 10-24
xi
A.2.4 Customization Error and Status Messages A-6
A.2.5 Functionality of a Customized Profile at Run Time A-6
A.3 Customization Options and Choosing a Customizer A-7
A.3.1 Overview of Customizer Harness Options A-7
A.3.1.1 Syntax for Customizer Harness Options A-7
A.3.1.2 Options Supported by the Customizer Harness A-8
A.3.2 General Customizer Harness Options A-8
A.3.2.1 Profile Backup Option (backup) A-9
A.3.2.2 Customization Connection Context Option (context) A-9
A.3.2.3 Customizer Option (customizer) A-10
A.3.2.4 Customization JAR File Digests Option (digests) A-10
A.3.2.5 Customization Help Option (help) A-11
A.3.2.6 Customization Verbose Option (verbose) A-12
A.3.3 Customizer Harness Options for Connections A-12
A.3.3.1 Customization User Option (user) A-13
A.3.3.2 Customization Password Option (password) A-14
A.3.3.3 Customization URL Option (url) A-14
A.3.3.4 Customization JDBC Driver Option (driver) A-15
A.3.4 Customizer Harness Options that Invoke Specialized Customizers A-15
A.3.4.1 Specialized Customizer: Profile Debug Option (debug) A-16
A.3.4.2 Specialized Customizer: Profile Print Option (print) A-16
A.3.4.3 Specialized Customizer: Profile Semantics-Checking Option
(verify) A-17
A.3.5 Overview of Customizer-Specific Options A-18
A.3.6 Oracle Customizer Options A-19
A.3.6.1 Options Supported by Oracle Customizer A-19
A.3.6.2 Oracle Customizer Version Compatibility Option (compat) A-20
A.3.6.3 Oracle Customizer Force Option (force) A-21
A.3.6.4 Oracle Customizer Column Definition Option (optcols) A-21
A.3.6.5 Oracle Customizer Parameter Definition Option (optparams) A-23
A.3.6.6 Oracle Customizer Parameter Default Size Option
(optparamdefaults) A-24
A.3.6.7 Oracle Customizer CHAR Comparisons with Blank Padding
(fixedchar) A-26
A.3.6.8 Oracle Customizer Show-SQL Option (showSQL) A-26
A.3.6.9 Oracle Customizer Statement Cache Size Option (stmtcache) A-27
A.3.6.10 Oracle Customizer Summary Option (summary) A-29
A.3.7 Options for Other Customizers A-30
A.3.8 SQLJ Translator Options for Profile Customization A-30
A.4 JAR Files for Profiles A-30
A.4.1 JAR File Requirements A-31
A.4.2 JAR File Logistics A-32
xii
A.5 SQLCheckerCustomizer for Profile Semantics-Checking A-32
A.5.1 Invoking SQLCheckerCustomizer with the Customizer Harness verify
Option A-33
A.5.2 SQLCheckerCustomizer Options A-34
A.5.2.1 SQLCheckerCustomizer Semantics-Checker Option (checker) A-34
A.5.2.2 SQLCheckerCustomizer Warnings Option (warn) A-35
A.6 AuditorInstaller Customizer for Debugging A-35
A.6.1 Overview of Auditors and Code Layers A-36
A.6.2 Invoking AuditorInstaller with the Customizer Harness debug Option A-36
A.6.3 AuditorInstaller Run-Time Output A-37
A.6.4 AuditorInstaller Options A-38
A.6.4.1 AuditorInstaller Depth Option (depth) A-39
A.6.4.2 AuditorInstaller Log File Option (log) A-39
A.6.4.3 AuditorInstaller Prefix Option (prefix) A-40
A.6.4.4 AuditorInstaller Return Arguments Option (showReturns) A-40
A.6.4.5 AuditorInstaller Thread Names Option (showThreads) A-41
A.6.4.6 AuditorInstaller Uninstall Option (uninstall) A-42
A.6.5 Full Command-Line Examples A-42
Index
xiii
List of Tables
5-1 SQLJ Statement Clauses 5-10
5-2 SQLJ Assignment Clauses 5-10
6-1 Type Mappings for Supported Host Expression Types 6-2
6-2 Correlation between Oracle Extensions and JDBC 2.0 Types 6-7
6-3 Plausible values for the for_update option and the corresponding SQL statement 6-33
8-1 Table showing the options and values for generating outlines 8-63
9-1 SQLJ Translator Options 9-2
9-2 SQLJ Support for javac Options 9-9
9-3 Tests and Flags for SQLJ Warnings 9-36
9-4 Oracle Online Semantics-Checkers Chosen by OracleChecker 9-60
9-5 Oracle Offline Semantics-Checkers Chosen by OracleChecker 9-60
9-6 Feature Comparison: Offline Parsing Versus Online Semantics-Checking 9-61
10-1 Steps for Generated Calls, ISO Standard Versus Oracle-Specific 10-6
10-2 SQLJ Translator Error Message Categories 10-11
10-3 JDBC and SQLJ Types and Corresponding Globalization Types 10-21
xiv
Preface
This preface introduces you to the Oracle Database SQLJ Developer's Guide,
discussing the intended audience and conventions of this document. A list of related
Oracle documents is also provided.
This preface covers the following topics:
• Audience
• Related Documents
• Conventions
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.
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 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
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.
xv
Preface
The following documents are from the Oracle Server Technologies group:
• Oracle Database Development 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 Guide
• Oracle Database Globalization Support Guide
• Oracle Database Reference
• Oracle Database Sample Schemas
Note:
Oracle error message documentation is available on Oracle Technology
Network. 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.
For documentation of SQLJ standard features and syntax, refer to the following
specification:
Information Technology - Database Languages - SQL - Part 10: Object Language
Bindings (SQL/OLB)
Throughout this manual, the term "ISO SQLJ standard" is used to refer to this
standard.
You can obtain the ISO SQLJ standard from ANSI through the following Web site:
http://www.ansi.org/
Click eStandards Store and search for the term "INCITS/ISO/IEC 9075-10".
You can also obtain the ISO SQLJ standard from ISO through their web store
http://www.iso.org/iso/store.htm
Visit the preceding link and search for the term "ISO/IEC 9075-10".
Documentation Accessibility
For information about Oracle's commitment to accessibility, visit the
Oracle Accessibility Program website at http://www.oracle.com/pls/topic/lookup?
ctx=acc&id=docacc.
xvi
Preface
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
Note:
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.
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.
xvii
Preface
The following table describes typographic conventions used in code examples and
provides examples of their use.
Changed first row below to note this doc uses *angle* brackets for optional.
xviii
Preface
xix
1
Changes in This Release for Oracle SQLJ
Developer’s Guide
Deprecated Features
The following feature is deprecated in this release, and may be desupported in a later
release:
oracle.sql.* Package
Starting Oracle Database 12c Release 2 (12.2), the oracle.sql.* package is
deprecated.
Desupported Features
The following features are no longer supported by Oracle:
Extended Datatype Support (EDS)
The Extended Datatype Support (EDS) feature is desupported in Oracle Database
19c. All Data types that the EDS feature supported are now supported natively by both
Logical Standby and Oracle GoldenGate.
The Extended Datatype Support (EDS) feature provides a mechanism for logical
standbys to support certain Oracle data types that lack native redo-based support.
For example, EDS was used to replicate tables with a SDO_GEOMETRY column.
However, starting with Oracle Database 12c Release 2 (12.2), there are no EDS-
supported Oracle data types that are not supported natively, either by Logical standby,
or by Oracle GoldenGate. This feature is desupported with Oracle Database 19c
(19.1).
SQLJ in the Server
Starting with Oracle Database 12c Release 2 (12.2), Oracle does not support server-
side SQLJ code.
Oracle supports using client-side SQLJ. However, Oracle does not support the use of
server-side SQLJ, including running stored procedures, functions, and triggers in the
database environment.
JPublisher
All Oracle JPublisher features are desupported and unavailable in Oracle Database
12c Release 2 (12.2.0.1). Oracle recommends that you use the alternatives listed
here:
• To continue to use Web service callouts, Oracle recommends that you use the
Oracle JVM Web Services Callout utility, which is a replacement for the Web
Services Callout utility.
• To replace other JPublisher automation capabilities, including mapping user-
defined SQL types or SQL types, wrapping PL/SQL packages and similar
1-1
Chapter 1
See Also:
My Oracle Support Note 1937939.1 for more information about JDeveloper
deprecation and desupport:
https://support.oracle.com/CSP/main/article?
cmd=show&type=NOT&id=1937939.1
See Also:
Oracle Database Upgrade Guide to see a list of all desupported features in
this release of Oracle Database
1-2
2
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
See Also:
"SQLJ Environment"
2-1
Chapter 2
Assumptions and Requirements
Note:
A Java run-time environment (JRE), such as the one installed with Oracle
Database 12c Release 2 (12.2), 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.
See also:
Oracle Database JDBC Developer’s Guide
Note:
For more information about translator.jar, refer to "Set the Path and
Classpath".
Note:
runtime12ee.jar has been deprecated since Oracle Database 11g
Release 1. Use runtime12.jar instead.
2-2
Chapter 2
Assumptions and Requirements
Note:
Code generation is determined by the SQLJ -codegen option. Refer to "Code
Generation (-codegen)" for more information.
Note:
If you are running against different JDBC versions, then translate against the
earlier version.
Note:
For more information about translator.jar, refer to "Set the Path and
Classpath".
2-3
Chapter 2
Checking the Installation and Configuration
– 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.
The ORACLE_HOME/bin directory contains utilities for all Java product areas, including
the SQLJ executable files.
2-4
Chapter 2
Checking the Installation and Configuration
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 the following JDBC JAR files in the CLASSPATH:
ORACLE_HOME/jdbc/lib/ojdbc6.jar
ORACLE_HOME/jdbc/lib/ojdbc7.jar
Note:
See Also:
"Requirements for Using the Oracle SQLJ Implementation"
2-5
Chapter 2
Testing the Setup
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 HR and password hr. Most
Oracle Database installations have this account. You can substitute other values for HR
and hr if desired.
Note:
Running the demo applications requires that the demo directory be the current
directory, and that the current directory (".") should be specified in the
CLASSPATH.
2-6
Chapter 2
Testing the Setup
See Also:
"Check for Availability of SQLJ and Demo Applications"
Note:
In the Oracle Database 12c Release 2 (12.2) JDBC implementation,
database URL connection strings using SIDs are deprecated. Following is
an example, where orcl is the SID:
jdbc:oracle:thin:@localhost:5221: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:5221/myservice
# Users should uncomment one of the following URLs or add their own.
# (If using Thin, edit as appropriate.)
#sqlj.url=jdbc:oracle:thin:@localhost:5221/myservice
#sqlj.url=jdbc:oracle:oci:@
#
# User name and password here
sqlj.user=HR
sqlj.password=hr
2-7
Chapter 2
Testing the Setup
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));
See Also:
"Set the Path and Classpath"
2-8
Chapter 2
Testing the Setup
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=hr
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"
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
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:
2-9
Chapter 2
Testing the Setup
2-10
3
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
3-1
Chapter 3
Overview of SQLJ Components
Note:
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.
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.
3-2
Chapter 3
Overview of Oracle Extensions to the SQLJ Standard
See Also:
Translator Command Line and Options
See Also:
"SQLJ Run Time"
Note:
Since Oracle Database 10g Release 1, only Oracle JDBC drivers are
supported with SQLJ.
Note:
Oracle SQLJ implementation requires the run-time environment of JDK 6 or
JDK 7.
The ISO SQLJ standard addresses not only the SQL-92 Entry level dialect of SQL, but
also enables extension beyond that. The Oracle SQLJ implementation supports the
Oracle SQL dialect, which is a superset of SQL-92 Entry level. 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 Entry level of SQL-92 and, therefore, may not be supported in
other environments.
This section covers the following topics:
• SQLJ Type Extensions
• SQLJ Functionality Extensions
3-3
Chapter 3
Overview of Oracle Extensions to the SQLJ Standard
See Also:
Type Support, and Objects_ Collections_ and OPAQUE Types for
information about SQLJ extensions provided by Oracle Database
See Also:
"Support for JDBC 2.0 LOB Types and Oracle Type Extensions"
• Custom Java classes, 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.
See Also:
"Custom Java Classes"
See Also:
"Support for Streams"
• Iterator and result set instances as input or output parameters. The SQLJ standard
specifies them only in result expressions or cast statements.
3-4
Chapter 3
Overview of Oracle Extensions to the SQLJ Standard
See Also:
"Using Iterators and Result Sets as Host Variables" and "Using Iterators
and Result Sets as Stored Function Returns"
See Also:
"SQLJ Extended Globalization Support"
See Also:
See " Translator Command Line and Options"
See Also:
"Oracle-Specific Code Generation (No Profiles)"
See Also:
"Support for Dynamic SQL"
• Scrollable result set iterators with additional navigation methods, and FETCH
syntax from result set iterators and scrollable result set iterators
3-5
Chapter 3
Basic Translation Steps and Run-Time Processing
See Also:
"Scrollable Iterators"
See Also:
"Column Definitions", "Parameter Size Definitions", and "Options for
Code Generation_ Optimizations_ and CHAR Comparisons"
• Flags for modified translator behavior, such as for binding host expressions by
identifier or accounting for blank padding in CHAR comparisons for WHERE clauses
• SQLJ statement caching on connection contexts
See Also:
"Statement Caching"
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.
3-6
Chapter 3
Basic Translation Steps and Run-Time Processing
Oracle SQLJ
emp.sqlj emp.java emp.class
Checker
The following sequence of events occurs, presuming each step completes without
error:
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:
"Java Host_ Context_ and Result Expressions"
3. 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.
3-7
Chapter 3
Basic Translation Steps and Run-Time Processing
See Also:
"Oracle-Specific Code Generation (No Profiles)"
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"
• 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"
See Also:
"Translator Command Line and Properties Files"
• Your application requires an Oracle JDBC driver when it runs, even if your code
does not use Oracle-specific features.
3-8
Chapter 3
Basic Translation Steps and Run-Time Processing
• Translator Input
• Translator Output
• Output File Locations
Note:
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.
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"
3-9
Chapter 3
Basic Translation Steps and Run-Time Processing
See Also:
"Overview of SQLJ Declarations"
• 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.
• 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.
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"
See Also:
"Oracle-Specific Code Generation (No Profiles)"
3-10
Chapter 3
SQLJ Sample Code
Note:
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.
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:
• 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.
Note:
The JDBC and SQLJ versions of the sample code are only partial
samples and cannot run independently. There is no main() method in
either.
3-11
Chapter 3
SQLJ Sample Code
import java.sql.*;
/**
This is what you have to do in SQLJ
**/
public class SimpleDemoSQLJ // line 6
{
//TO DO: make a main that calls this
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.
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().
3-12
Chapter 3
SQLJ Sample Code
Line 23
The updateAddress() method returns the addr object.
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
{
3-13
Chapter 3
Alternative Deployment Scenarios
Address addr;
PreparedStatement pstmt = // line 16
conn.prepareStatement("SELECT office_addr FROM employees" +
" WHERE empnumber = ?");
pstmt.setInt(1, empno);
OracleResultSet rs = (OracleResultSet)pstmt.executeQuery();
rs.next(); // line 21
//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 25
pstmt.close();
return addr; // line
27
}
public Address updateAddress(Address addr, Connection conn)
throws SQLException // line 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;
}
}
See Also:
Oracle Database JDBC Developer’s Guide
3-14
Chapter 3
Alternative Deployment Scenarios
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"
• 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"
3-15
Chapter 3
Alternative Development Scenarios
is to use a Java plug-in offered by Sun Microsystems. For information, refer to the
following:
http://www.oracle.com/technetwork/java/index.html
• 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.
Note:
The term "Oracle-specific features" refers to the use of Oracle type
extensions (discussed in Type Support) and the use of SQLJ features
that require Oracle-specific code generation or, for ISO SQLJ standard
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 Basic Language Features.)
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"
• 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 that you use supports JDK 6 and permits reflection.
– Run your applet through a browser Java plug-in.
3-16
Chapter 3
Alternative Development Scenarios
See Also:
"Globalization Support in the Translator and Run Time"
3-17
Chapter 3
Alternative Development Scenarios
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.
3-18
4
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
Note:
Your application will require an Oracle JDBC driver if you use Oracle-specific
code generation or if you use ISO SQLJ standard code generation with
Oracle customizer, even if your code does not actually use Oracle-specific
features.
4-1
Chapter 4
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 12c Release 1 (12.1) provides client-side drivers compatible with
JDK 6 and JDK 7.
See Also:
Oracle Database JDBC Developer's Guide
Note:
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.
4-2
Chapter 4
Selection of the JDBC Driver
Note:
For backward compatibility, oci8 is still acceptable instead of oci.
See Also:
Oracle Database JDBC Developer's Guide for information about database
service names
In Oracle Database 12c Release 2 (12.2), connection strings using SIDs are
deprecated, but are still supported for backward compatibility:
jdbc:oracle:thin:@host:port:sid
Note:
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 for more information. Also,
refer to the Oracle Database Java Developer's Guide for general information
about SocketPermission and other permissions.
4-3
Chapter 4
Selection of the JDBC Driver
If your SQLJ code uses the default connection context, then SQLJ automatically uses
this driver for code running in Oracle JVM.
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.
See Also:
"Connection Options"
You will typically, but not necessarily, use the same driver that you use in your source
code for the run-time connection.
Note:
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.
4-4
Chapter 4
Connection Considerations
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"
Note:
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". For
general information about data sources, refer to the Oracle Database JDBC
Developer's Guide.
4-5
Chapter 4
Connection Considerations
Note:
If your operations will use different sets of SQL entities, then you will typically
want to declare and use additional connection context classes.
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.
Alternatively, you can specify user name, password, and URL directly:
4-6
Chapter 4
Connection Considerations
In this example, the connection will use the JDBC Thin driver to connect the HR user
with the password, hr, to a database on the computer, localhost, through port 5221,
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 12c
Release 2 (12.2)), 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.
See Also:
Oracle Database JDBC Developer's Guide for more information
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();
4-7
Chapter 4
Connection Considerations
Multiple Connections
For multiple connections, you can create and use additional instances of the
DefaultContext class, while optionally still using the default connection.
Note:
ctx could also use the HR/hr 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 };
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:5221/myservice1", "HR", "hr");
DefaultContext ctx2 = Oracle.getConnection
("jdbc:oracle:thin:@localhost1:5221/myservice1", "HR", "hr");
This creates two connection context instances that would use the same schema,
connecting to HR/hr 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:5221/myservice1", "HR", "hr");
4-8
Chapter 4
Connection Considerations
This creates two connection context instances that use Oracle JDBC Thin driver but
use different schemas. The ctx1 object connects to HR/hr 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:
• 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 };
Note:
Include the square brackets around the connection context instance
name; they are part of the syntax.
• 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 };
Note:
Because the preceding statements do not specify connection contexts,
at translation time they will all be checked against the default connection
context.
4-9
Chapter 4
Connection Considerations
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:
...
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.
Note:
It is also possible to close a connection context instance without closing the
underlying connection (in case the underlying connection is shared).
4-10
Chapter 4
Connection Considerations
See Also:
"Connection Contexts"
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.
4-11
Chapter 4
Connection Considerations
See Also:
"Basic Transaction Control" and "Single Connection or Multiple Connections
Using DefaultContext"
You can close the underlying physical connection (default behavior) as follows:
Oracle.close(ConnectionContext.CLOSE_CONNECTION);
See Also:
"Closing Shared Connections"
4-12
Chapter 4
Connection Considerations
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.
Note:
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.
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 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:HR/hr@localhost:5221/myservice"
4-13
Chapter 4
Connection Considerations
Note:
You must keep the following in mind when using connection context
constructors:
• 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".
• 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" 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" for more
information.
To close the underlying physical connection, which is the default behavior, use the
following:
defctx.close(ConnectionContext.CLOSE_CONNECTION);
4-14
Chapter 4
Connection Considerations
See Also:
"Closing Shared Connections" for more information about using these
parameters and about shared connections
See Also:
"Connection Context Concepts"
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"
4-15
Chapter 4
NULL-Handling
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, url,
and driver options to specify connection parameters for whatever customizer you are
using, as appropriate.
See Also:
4.3 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
4-16
Chapter 4
NULL-Handling
Integer object and floatValue() returns a float value from a Float object. For
example, presuming intobj is an Integer object:
int j = intobj.intValue();
Note:
You cannot use the Java primitive type float to accomplish this.
For each employee in the employee table whose salary is at least $50,000, the
employee name (FIRST_NAME) and commission (COMMISSION_PCT) are selected into the
iterator. Then each row is tested to determine if the COMMISSION_PCT field is, in fact,
null. If so, then it is processed accordingly.
#sql iterator EmployeeIter (String first_name, Double commission);
EmployeeIter ei;
#sql ei = { SELECT first_name, commission_pct FROM employees WHERE salary >=
50000 };
while (ei.next())
{
if (ei.commission_pct() == null)
System.out.println(ei.first_name() + " is not on commission.");
}
ei.close();
...
4-17
Chapter 4
Exception-Handling Basics
Note:
To execute a WHERE clause comparison against NULL, use the following SQL
syntax:
...WHERE :x IS NULL
4-18
Chapter 4
Exception-Handling Basics
} catch (SQLException e) {
System.err.println("Error running the example: " + e);
}
MyIter iter;
#sql iter = { SELECT ITEM_NAME FROM SALES };
while (iter.next()) {
System.out.println(iter.ITEM_NAME());
}
}
}
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.
4-19
Chapter 4
Exception-Handling Basics
Printing the error text, as in this example, prints the error message with some
additional text, such as SQLException.
4-20
Chapter 4
Basic Transaction Control
See Also:
"Advanced Transaction Control"
Note:
In Oracle Database 12c Release 2 (12.2), 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.
4-21
Chapter 4
Basic Transaction Control
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.
See Also:
"More About the Oracle Class"
See Also:
"More About the DefaultContext Class"
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
4-22
Chapter 4
Basic Transaction Control
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.
or:
ctx.getConnection().setAutoCommit(true);
Note:
Do not alter the auto-commit setting in the middle of a transaction.
To roll back any changes that have been executed since the last COMMIT operation, use
the SQLJ ROLLBACK statement, as follows:
#sql { ROLLBACK };
4-23
Chapter 4
Basic Transaction Control
Note:
Note:
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".
For more information about the underlying scrollable result sets, refer to the
Oracle Database JDBC Developer's Guide.
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.
4-24
Chapter 4
Basic Transaction Control
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 };
Savepoints are saved in the SQLJ execution context, which has methods that parallel
the functionality of these three statements.
See Also:
"Savepoint Methods"
Because any COMMIT operation ends the transaction, this also releases all savepoints
of the transaction.
The host expression, savepoint in this example, is a variable that specifies the name
of the savepoint as a Java String.
4-25
Chapter 4
Summary: First Steps in SQLJ Code
Note:
Oracle-specific syntax will continue to be supported for backward
compatibility. Note the following differences between Oracle syntax and ISO
SQLJ standard 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.
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.
4-26
Chapter 4
Summary: First Steps in SQLJ Code
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) {...}
}
4-27
Chapter 4
Summary: First Steps in SQLJ Code
This example declares salary and empname as Java host variables. The SQLJ clause
then selects data from the first_name and salary columns of the employees table and
places the data into the host variables. Finally, the values of salary and empname are
printed.
Note that this SELECT statement could select only one row of the employees table,
because the employee_id column in the WHERE clause is the primary key of the table.
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) {...}
}
4-28
Chapter 4
Summary: First Steps in SQLJ Code
Next, instantiate the EmpRecs class and populate it with query results.
EmpRecs employees;
Then, use the next() method of the iterator to print the results.
while (employees.next()) {
System.out.println( "Name: " + employees.first_name() );
System.out.println( "EMPNO: " + employees.employee_id() );
System.out.println( "Job: " + employees.job_id() );
System.out.println( "Manager: " + employees.manager_id) );
System.out.println( "Date hired: " + employees.hire_date() );
System.out.println( "Salary: " + employees.salary() );
System.out.println( "Commission: " + employees.commission_pct() );
System.out.println( "Department: " + employees.department_no() );
System.out.println();
}
4-29
Chapter 4
Summary: First Steps in SQLJ Code
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) {...}
}
4-30
Chapter 4
Oracle-Specific Code Generation (No Profiles)
EmpRecs employees;
// 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: " + employees.first_name() );
System.out.println( "EMPNO: " + employees.employee_id() );
System.out.println( "Job: " + employees.job_id() );
System.out.println( "Manager: " + employees.manager_id() );
System.out.println( "Date hired: " + employees.hire_date() );
System.out.println( "Salary: " + employees.salary() );
System.out.println( "Commission: " + employees.commission_pct() );
System.out.println( "Department: " + employees.department_no() );
System.out.println();
}
4-31
Chapter 4
Oracle-Specific Code Generation (No Profiles)
• You must use an Oracle11g or later version of JDBC driver, because Oracle-
specific code generation requires JDBC statement caching functionality.
• The generic SQLJ run time library, runtime, is not supported for Oracle-specific
code generation. You must have one of the following Oracle SQLJ run time
libraries in the CLASSPATH:
– runtime12.jar
– runtime12ee.jar
See Also:
"Requirements for Using the Oracle SQLJ Implementation"
or:
#sql x[i++] = { VALUES f(:INOUT (x[i++]), :OUT (f_with_sideffect())) };
4-32
Chapter 4
Oracle-Specific Code Generation (No Profiles)
• Type maps for Oracle object functionality assumes that the corresponding Java
classes implement the java.sql.SQLData interface. 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" and "Declaration WITH Clause"
Note:
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.
4-33
Chapter 4
Oracle-Specific Code Generation (No Profiles)
• setStmtCacheSize(int)
• int getStmtCacheSize()
By default, statement caching is enabled.
See Also:
"Statement Caching"
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"
4-34
Chapter 4
ISO Standard Code Generation
See Also:
"Customizer Harness Options for Connections" and "AuditorInstaller
Customizer for Debugging"
4-35
Chapter 4
ISO Standard Code Generation
• SQLJ run-time library: runtime12.jar with JDK 6 or JDK 7, and Oracle Database
12c Release 2 (12.2)
• JDBC drivers: Oracle Database 12c Release 2 (12.2)ojdbc6.jar or ojdbc7.jar
• JDK version: JDK 6 or JDK 7
See Also:
"SQLJ Translator Functionality"
• 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 the SQLJ run time
to use a JDBC driver to access the database.
See Also:
"SQLJ Run Time"SQLJ Run Time
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.
Note:
Since Oracle Database 10g Release 1, only Oracle JDBC drivers are
supported with SQLJ.
4-36
Chapter 4
ISO Standard Code Generation
translator option settings, it either serializes the profiles and puts them into binary
resource files or puts them into .class files.
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.
4-37
Chapter 4
ISO Standard Code Generation
• 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"
• 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
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"
4-38
Chapter 4
ISO Standard Code Generation
See Also:
"Translator Command Line and Properties Files"
• 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.
See Also:
"Summary of Translator Input and Output"
See Also:
"Translator Input"
4-39
Chapter 4
ISO Standard Code Generation
See Also:
"Translator Output"
• 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
...
The .ser file extension indicates that the profiles are serialized. The .ser files are
binary files.
Note:
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.
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"
• 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:
4-40
Chapter 4
ISO Standard Code Generation
_SJProfileKeys
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)"
Note:
It is not necessary to reference SQLJ profiles or the profile-keys class
directly. This is all handled automatically.
See Also:
"Output File Locations"
4-41
Chapter 4
ISO Standard Code Generation
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.
Note:
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.
See Also:
"Alternative Deployment Scenarios"
• 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
These packages are included with your Oracle installation in one of several run-
time libraries in the ORACLE_HOME/lib directory.
4-42
Chapter 4
ISO Standard Code Generation
See Also:
"Requirements for Using the Oracle SQLJ Implementation"
• 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.
Note:
This consideration does not apply to the default Oracle-specific code
generation, where no profiles are produced.
• 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
– 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
Note:
4-43
Chapter 4
Oracle-Specific Code Generation Versus ISO Standard Code Generation
Note:
Naming restrictions particular to host variables are discussed in "Restrictions
on Host Expressions".
4-44
Chapter 4
Requirements and Restrictions for Naming
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
4-45
Chapter 4
Requirements and Restrictions for Naming
Note:
Restrictions particular to the naming of iterator columns are discussed in
"Using Named Iterators".
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.
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.
4-46
Chapter 4
Considerations for SQLJ in the Middle Tier
For example, if you define the public class MySource in your source file, then your file
name must be:
MySource.sqlj
Note:
These file naming requirements follow the Java Language Specification
(JLS) and are not SQLJ-specific. These requirements do not directly apply in
Oracle Database 12c Release 2 (12.2), but it is still advisable to adhere to
them.
4-47
Chapter 4
Considerations for SQLJ in the Middle Tier
For general information about SQLJ support for data sources and connection
JavaBeans, refer to the following sections:
• "Standard Data Source Support"
• "SQLJ-Specific Data Sources"
• "SQLJ-Specific Connection JavaBeans for JavaServer Pages"
4-48
5
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
5-1
Chapter 5
Overview of SQLJ Declarations
• 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
class Outer
{
SQLJ declaration; // OK (class level scope)
class Inner
{
SQLJ declaration; // OK (nested class scope)
}
void func()
{
SQLJ declaration; // OK (method block)
}
}
Note:
As with standard Java, any public class should be declared in one of the
following ways:
• 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.
5-2
Chapter 5
Overview of SQLJ 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).
See Also:
"Multirow Query Results: SQLJ Iterators"
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 EMPLOYEES
table, a DEPARTMENTS table, and a SECURE_EMPLOYEES stored procedure.
5-3
Chapter 5
Overview of SQLJ Declarations
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" and "Connection Contexts"
Note:
The SQLJ implements clause corresponds to the Java implements clause.
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);
5-4
Chapter 5
Overview of SQLJ Declarations
See Also:
"Using the IMPLEMENTS Clause in Iterator Declarations" and "Using the
IMPLEMENTS Clause in Connection Context 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 <modifiers> context context_classname with (var1=value1,..., varN=valueN);
Note:
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 12c Release 2 (12.2) or to Oracle SQLJ run time.
Attempts to define constants other than the standard constants is legal
with Oracle Database 12c Release 2 (12.2), but might not be portable to
other SQLJ implementations and will generate a warning if you have the
-warn=portable flag enabled.
5-5
Chapter 5
Overview of SQLJ Declarations
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.
5-6
Chapter 5
Overview of SQLJ Declarations
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);
Note:
holdability is currently not supported.
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"
5-7
Chapter 5
Overview of SQLJ Executable Statements
Load RefCursorSQLJ.sqlj into Oracle Java Virtual Machine (JVM) inside the database
as follows:
% loadjava -u HR -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 HR.sqljUserRet from dual;
STR
------------------------------
sqljRetTabCol
5-8
Chapter 5
Overview of SQLJ Executable Statements
• SQLJ Clauses
• Specifying Connection Context Instances and Execution Context Instances
• Executable Statement Examples
• PL/SQL Blocks in Executable Statements
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.
5-9
Chapter 5
Overview of SQLJ Executable Statements
Table 1 lists supported SQLJ statement clauses and Table 2 lists supported SQLJ
assignment clauses. The last two entries in Table 1 are general categories for
statement clauses that use standard SQL syntax or Oracle PL/SQL syntax, as
opposed to SQLJ-specific syntax.
5-10
Chapter 5
Overview of SQLJ Executable Statements
Note:
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.
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.
You can also specify both a connection context instance and an execution context
instance:
#sql [conn_context_instance, exec_context_instance] { SQL operation };
Note:
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:
5-11
Chapter 5
Overview of SQLJ Executable Statements
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) };
#sql [execctx] { INSERT INTO emp (ename, sal) VALUES ('Joe', 43000) };
#sql [ctx, execctx] { INSERT INTO emp (ename, sal) VALUES ('Joe', 43000) };
Note:
5-12
Chapter 5
Java Host, Context, and Result Expressions
This example goes through a loop that inserts new employees in the emp table,
creating employee numbers 2001 through 2100. It presumes data other than the
employee number will be filled in later.
Simple PL/SQL blocks can also be coded in a single line as follows:
#sql { <DECLARE ...> BEGIN ... END; };
Using PL/SQL anonymous blocks within SQLJ statements is one way to use dynamic
SQL in your application. You can also use dynamic SQL directly through SQLJ
extensions provided by Oracle or through JDBC code within a SQLJ application.
See Also:
"Support for Dynamic SQL" and "SQLJ and JDBC Interoperability"
Note:
Remember that using PL/SQL in your SQLJ code would prevent portability to
other platforms, because PL/SQL is Oracle-specific.
See Also:
"Support for Dynamic SQL"
SQLJ uses Java host expressions to pass arguments between Java code and
SQL operations. This is how you pass information between Java and SQL. Host
expressions are interspersed within the embedded SQL operations in the SQLJ source
code.
The most basic kind of host expression, consisting of only a Java identifier, is referred
to as a host variable. A context expression specifies a connection context instance
or execution context instance to be used for a SQLJ statement. A result expression
specifies an output variable for query results or a function return.
5-13
Chapter 5
Java Host, Context, and Result Expressions
See Also:
"Supported Types for Host Expressions"
5-14
Chapter 5
Java Host, Context, and Result Expressions
Note:
When using the default, you can still include the mode specifier if desired.
The SQL code that surrounds a host expression can use any vendor-specific SQL
syntax. Therefore, no assumptions can be made about the syntax when parsing
the SQL operations and determining the host expressions. To avoid any possible
ambiguity, any host expression that is not a simple host variable (in other words, that is
more complex than a nondotted Java identifier) must be enclosed in parentheses.
To summarize the basic syntax:
• For a simple host variable without a mode specifier, put the host variable after the
colon, as in the following example:
:hostvar
• For a simple host variable with a mode specifier, put the mode specifier after the
colon and put white space (space, tab, newline, or comment) between the mode
specifier and the host variable, as in the following example:
:INOUT hostvar
The white space is required to distinguish between the mode specifier and the
variable name.
• For any other host expression, enclose the expression in parentheses and place it
after the mode specifier or after the colon, if there is no mode specifier, as in the
following examples:
:IN(hostvar1+hostvar2)
:(hostvar3*hostvar4)
:(index--)
White space is not required after the mode specifier in this example, because
the parenthesis is a suitable separator. However, a white space after the mode
specifier is allowed.
An outer set of parentheses is needed even if the expression already starts with a
begin-parenthesis, as in the following examples:
:((x+y).z)
:(((y)x).myOutput())
Syntax Notes
Keep the following in mind regarding the host expression syntax:
5-15
Chapter 5
Java Host, Context, and Result Expressions
• White space is always allowed after the colon as well as after the mode specifier.
Wherever white space is allowed, you can also have a comment.
You can have any of the following in the SQL namespace:
– SQL comments after the colon and before the mode specifier
– SQL comments after the colon and before the host expression if there is no
mode specifier
– SQL comments after the mode specifier and before the host expression
You can have the following in the Java namespace:
– Java comments within the host expression (inside the parentheses)
• The IN, OUT, and INOUT syntax used for host variables and expressions are not
case-sensitive. These tokens can be in uppercase, lowercase, or mixed.
• Do not confuse the IN, OUT, and INOUT syntax of SQLJ host expressions with
similar IN, OUT, and IN OUT syntax used in PL/SQL declarations to specify the
mode of parameters passed to PL/SQL stored functions and procedures.
Usage Notes
Keep the following in mind regarding the usage of host expressions:
• A simple host variable can appear multiple times in the same SQLJ statement, as
follows:
– If the host variable appears only as an input variable, then there are no
restrictions or complications.
– If at least one appearance of the host variable is as an output variable in
a PL/SQL block, then you will receive a portability warning if the translator
-warn=portability flag is set. SQLJ run-time behavior in this situation is
vendor-specific. Oracle SQLJ run time uses value semantics, as opposed to
reference semantics, for all occurrences of the host variable.
– If at least one appearance of the host variable is as an output variable in a
stored procedure call, stored function call, SET statement, or INTO-list, then
you will not receive any warning. SQLJ run-time behavior in this situation is
standardized, using value semantics.
Note:
The term output refers to OUT or INOUT variables, as applicable.
• If a host expression that is a simple host variable appears multiple times in a SQLJ
statement, then by default each appearance is treated completely independently
of the other appearances, using value semantics. However, if you use the SQLJ
translator -bind-by-identifier=true setting, then this is not the case. With a
true setting, multiple appearances of the same host variable in a given SQLJ
statement or PL/SQL block are treated as a single bind occurrence.
• When binding a string host expression into a WHERE clause for comparison against
CHAR data, be aware that there is a SQLJ option, -fixedchar, that accounts for
blank padding in the CHAR column when the comparison is made.
5-16
Chapter 5
Java Host, Context, and Result Expressions
Note:
Some of these examples use SELECT INTO statements, which are described
in "Single-Row Query Results: SELECT INTO Statements".
Example 1
In this example, two input host variables are used, one as a test value for a WHERE
clause and one to contain new data to be sent to the database.
Presume you have a database employee table emp with an ename column for employee
names and a sal column for employee salaries. The relevant Java code that defines
the host variables is as follows:
String empname = "SMITH";
double salary = 25000.0;
...
#sql { UPDATE emp SET sal = :salary WHERE ename = :empname };
As you can see, the colon (:) can immediately precede the variable when not using the
IN token, but :IN must be followed by white space before the host variable.
Example 2
This example uses an output host variable in a SELECT INTO statement, where you
want to find out the name of the employee whose employee number 28959.
String empname;
...
#sql { SELECT ename INTO :empname FROM emp WHERE empno = 28959 };
OUT is the default for an INTO-list, but you can state it explicitly as well:
#sql { SELECT ename INTO :OUT empname FROM emp WHERE empno = 28959 };
This statement looks in the empno column of the emp table for employee number 28959,
selects the name in the ename column of that row, and outputs it to the empname output
host variable, which is a Java String.
Example 3
This example uses an arithmetic expression as an input host expression. The Java
variables balance and minPmtRatio are multiplied, and the result is used to update the
minPayment column of the creditacct table for account number 537845.
float balance = 12500.0;
float minPmtRatio = 0.05;
5-17
Chapter 5
Java Host, Context, and Result Expressions
...
#sql { UPDATE creditacct SET minPayment = :(balance * minPmtRatio)
WHERE acctnum = 537845 };
Example 4
This example shows the use of the output of a method call as an input host expression
and also uses an input host variable. This statement uses the value returned by
getNewSal() to update the sal column in the emp table for the employee who is
specified by the Java empname variable. Java code initializing the host variables is also
shown.
String empname = "SMITH";
double raise = 0.1;
...
#sql {UPDATE emp SET sal = :(getNewSal(raise, empname))
WHERE ename = :empname};
5-18
Chapter 5
Java Host, Context, and Result Expressions
Note:
The following discussion and the related examples later do not apply to
Oracle-specific code generation. If you use side effects as described here,
then request ISO code generation during translation.
The following is a summary, for ISO code, of the overall order of evaluation, execution,
and assignment of Java expressions for each statement that executes during run time.
1. If there is a connection context expression, then it is evaluated immediately, before
any other Java expressions are evaluated.
2. If there is an execution context expression, then it is evaluated after any
connection context expression, but before any result expression.
3. If there is a result expression, then it is evaluated after any context expressions,
but before any host expressions.
4. After evaluation of any context or result expressions, host expressions are
evaluated from left to right as they appear in the SQL operation. As each host
expression is encountered and evaluated, its value is saved to be passed to SQL.
Each host expression is evaluated once and only once.
5. IN and INOUT parameters are passed to SQL, and the SQL operation is executed.
6. After execution of the SQL operation, the output parameters, Java OUT and INOUT
host expressions, are assigned output in order from left to right as they appear in
the SQL operation.
Each output host expression is assigned once and only once.
7. The result expression, if there is one, is assigned output last.
5-19
Chapter 5
Java Host, Context, and Result Expressions
Note:
Host expressions inside a PL/SQL block are all evaluated together before
any statements within the block are executed. They are evaluated in the
order in which they appear, regardless of the control flow within the block.
Once the expressions in a statement have been evaluated, input and input-output
host expressions are passed to SQL, and then the SQL operation is executed.
After execution of the SQL operation, assignments are made to Java output host
expressions, input-output host expressions, and result expressions as follows:
1. OUT and INOUT host expressions are assigned output in order from left to right.
2. The result expression, if there is one, is assigned output last.
Note that during run time, all host expressions are treated as distinct values, even if
they share the same name or reference the same object. The execution of each SQL
operation is treated as if invoking a remote method, and each host expression is taken
as a distinct parameter. Each input or input-output parameter is evaluated and passed
as it is first encountered, before any output assignments are made for that statement,
and each output parameter is also taken as distinct and is assigned exactly once.
It is also important to remember that each host expression is evaluated only once.
An INOUT expression is evaluated when it is first encountered. When the output
assignment is made, the expression itself is not reevaluated nor are any side-effects
repeated.
Note:
Do not count on these effects if you use Oracle-specific code generation.
Request ISO code generation during translation if you depend on such
effects.
5-20
Chapter 5
Java Host, Context, and Result Expressions
The indx variable is incremented to 2 and will have that value the next time it is
encountered, but not until after :IN (indx++) has been evaluated.
The variable indx is incremented to 2 after the first expression is evaluated, but before
the second expression is evaluated. It is incremented to 3 after the second expression
is evaluated and will have that value the next time it is encountered.
The following example consists of both prefix and postfix operators:
int indx = 1;
...
#sql { ... :OUT (array[++indx]) ... :IN (indx++) ... };
One might expect input expressions to be evaluated before output expressions, but
that is not the case. The expression :OUT (arry[n]) is evaluated first because it is
the left-most expression. Then n is incremented prior to evaluation of ++n, because it is
being operated on by a prefix operator. Then ++n is evaluated as 1. The result will be
assigned to arry[0], not arry[1], because 0 was the value of n when it was originally
encountered.
5-21
Chapter 5
Java Host, Context, and Result Expressions
All expressions in a PL/SQL block are evaluated before any are executed. In this
example, the host expressions in the second statement, :OUT z and :x, are evaluated
before the first statement is executed. In particular, the second statement is evaluated
while x still has its original value of 3, before it has been assigned the value 10.
Consider another example of how expressions are evaluated within a PL/SQL block:
int x=1, y=4, z=3;
...
#sql { BEGIN
:OUT x := :(y++) + 1;
:OUT z := :x;
END };
The following example demonstrates the difference between two statements appearing
in a PL/SQL block in one SQLJ executable statement, and the same statements
appearing in separate (consecutive) SQLJ executable statements.
First, consider the following, where two statements are in a PL/SQL block.
int y=1;
...
#sql { BEGIN :OUT y := :y + 1; :OUT x := :y + 1; END };
5-22
Chapter 5
Java Host, Context, and Result Expressions
Now, consider the situation where the same two statements are in PL/SQL blocks in
separate SQLJ executable statements.
int y=1;
#sql { BEGIN :OUT y := :y + 1; END };
#sql { BEGIN :OUT x := :y + 1; END };
After execution of the first statement, the second statement is evaluated as follows:
#sql { BEGIN :OUT x := 2 + 1; END };
This time, as opposed to the previous PL/SQL block example, y has already received
the value 2 from execution of the previous statement. Therefore, x is assigned the
value 3 after execution of the second statement.
The Java count variable will have the value 0 when it is passed to SQL, because it
is operated on by a postfix operator, as opposed to a prefix operator. It will then be
incremented to 1 and will hold that value throughout execution of this PL/SQL block.
It is evaluated only once as the SQLJ executable statement is parsed and then is
replaced by the value 1 prior to SQL execution.
Consider the following example that illustrates the evaluation of host expressions
in conditional blocks. This example demonstrates how each expression is always
evaluated, regardless of the program flow. As the block is executed, only one branch
of the IF...THEN...ELSE construct can be executed. However, before the block is
executed, all expressions in the block are evaluated in the order that the statements
appear.
5-23
Chapter 5
Java Host, Context, and Result Expressions
int x;
...
(operations on x)
...
#sql {
DECLARE
n NUMBER
BEGIN
n := :x;
IF n < 10 THEN
n := :(x++);
ELSE
n := :x * :x;
END LOOP;
END
};
Say the operations performed on x resulted in x having a value of 15. When the
PL/SQL block is executed, the ELSE branch will be executed and the IF branch will
not. However, all expressions in the PL/SQL block are evaluated before execution,
regardless of program logic or flow. Therefore, x++ is evaluated, then x is incremented,
and then each x is evaluated in the (x * x) expression. The IF...THEN...ELSE block
is evaluated as follows:
IF n < 10 THEN
n := 15;
ELSE
n := :16 * :16;
END LOOP;
After execution of this block, given an initial value of 15 for x, n will have the value 256.
Output Host Expressions Are Assigned Left to Right, Before Result Expression
Remember that OUT and INOUT host expressions are assigned in order from left to
right, and then the result expression, if any, is assigned last. If the same variable is
assigned more than once, then it will be overwritten according to this order, with the
last assignment taking precedence.
The following example contains multiple output host expressions referencing the same
variable:
#sql { CALL foo(:OUT x, :OUT x) };
If foo() outputs the values 2 and 3, respectively, then x will have the value 3 after the
SQLJ executable statement has finished executing. The right-hand assignment will be
performed last, thereby taking precedence.
The following example contains multiple output host expressions referencing the same
object:
MyClass x = new MyClass();
MyClass y = x;
...
#sql { ... :OUT (x.field):=1 ... :OUT (y.field):=2 ... };
After execution of the SQLJ executable statement, x.field will have a value of 2, and
not 1, because x is the same object as y, and field was assigned the value of 2 after
it was assigned the value of 1.
5-24
Chapter 5
Java Host, Context, and Result Expressions
The following example demonstrates the difference between having the output results
of a function assigned to a result expression and having the results assigned to an OUT
host expression. Consider the following function, with the invar input parameter, the
outvar output parameter, and a return value:
CREATE FUNCTION fn(invar NUMBER, outvar OUT NUMBER)
RETURN NUMBER AS BEGIN
outvar := invar + invar;
return (invar * invar);
END fn;
Now consider an example where the output of the function is assigned to a result
expression:
int x = 3;
#sql x = { VALUES(fn(:x, :OUT x)) };
The function will take 3 as the input, will calculate 6 as the output, and will return 9.
After execution, the :OUT x will be assigned first, giving x a value of 6. But finally the
result expression is assigned, giving x the return value of 9 and overwriting the value
of 6 previously assigned to x. So x will have the value 9 the next time it is encountered.
Now consider an example where the output of the function is assigned to an OUT host
variable instead of a result expression:
int x = 3;
#sql { BEGIN :OUT x := fn(:x, :OUT x); END };
In this case, there is no result expression and the OUT variables are simply assigned
left to right. After execution, the first :OUT x, on the left side of the equation, is
assigned first, giving x the function return value of 9. However, proceeding left to right,
the second :OUT x, on the right side of the equation, is assigned last, giving x the
output value of 6 and overwriting the value of 9 previously assigned to x. Therefore, x
will have the value 6 the next time it is encountered.
Note:
Some unlikely cases have been used in these examples to explain the
concepts of how host expressions are evaluated. In practice, it is not
advisable to use the same variable in both an OUT or INOUT host expression
or in an IN host expression inside a single statement or PL/SQL block. The
behavior in such cases is well defined in the Oracle SQLJ implementation,
but this practice is not covered in the SQLJ specification. Therefore, code
written in this manner will not be portable. Such code will generate a warning
from the SQLJ translator if the portable flag is set during semantics-
checking.
5-25
Chapter 5
Single-Row Query Results: SELECT INTO Statements
:(in)
or:
:IN(in)
Trying to use an IN or INOUT token in the INTO-list will result in an error at translation
time.
5-26
Chapter 5
Single-Row Query Results: SELECT INTO Statements
Note:
The following is an example of a SELECT INTO statement with a single host expression
in the INTO-list:
String empname;
#sql { SELECT ename INTO :enpname FROM emp WHERE empno=28959 };
...
#sql { SELECT :(firstname + " ") || emp_last_name INTO :name FROM myemp
WHERE empno=28959 };
...
5-27
Chapter 5
Multirow Query Results: SQLJ Iterators
In the second example, presume myemp is a table much like the emp table but with
an emp_last_name column instead of an ename column. In the SELECT statement,
firstname is prepended to a single space (" "), using a Java host expression and the
Java string concatenation operator (+). This result is then passed to the SQL engine,
which uses SQL string concatenation operator (||) to append the last name.
This is vendor-independent behavior that is specified in the ISO SQLJ standard. There
is no vendor-specific error code in these cases. The error code is always 0.
Additionally, Oracle offers SQLJ extensions that enable you to use SQLJ iterators and
result sets in the following ways:
• As OUT host variables in executable SQL statements
• As INTO-list targets, such as in a SELECT INTO statement
• As a return type from a stored function call
• As column types in iterator declarations (essentially, nested iterators)
Note:
To use a SQLJ iterator in any of these ways, its class must be declared as
public. If you declared it at the class level or nested-class level, then it might
be advisable to declare it as public static.
5-28
Chapter 5
Multirow Query Results: SQLJ Iterators
See Also:
"Iterator Class Implementation and Advanced Functionality"
5-29
Chapter 5
Multirow Query Results: SQLJ Iterators
For example, data from an ENAME column in a database table can be selected and
put into an iterator ename column. Alternatively, you can use an alias to map a
database column name to an iterator column name if the names differ. Also, in a
more complicated query, you can perform an operation between two columns and alias
the result to match the corresponding iterator column name.
Because SQLJ iterators are strongly typed, they offer the benefit of Java type-checking
during the SQLJ semantics-checking phase.
As an example, consider the following table:
CREATE TABLE EMPSAL (
EMPNO NUMBER(4),
ENAME VARCHAR2(10),
OLDSAL NUMBER(10),
RAISE NUMBER(10) );
This is a simple case where the iterator column names match the table column names.
Note that the order of items in the SELECT statement does not matter when you use a
named iterator. Data is matched by name, not position.
When you query to populate a positional iterator object, the data is retrieved according
to the order in which you select the columns. Data from the first column selected from
the database table is placed into the first column of the iterator, and so on. The data
types of the table columns must be convertible to the types of the iterator columns,
but the names of the database columns are irrelevant, as the iterator columns have no
names.
Given the EMPSAL table, you can declare a positional iterator as follows:
#sql iterator SalPosIter (int, String, float);
5-30
Chapter 5
Multirow Query Results: SQLJ Iterators
Note that the order of the data items in the SELECT statement must be the same as in
the iterator. The processing differs between named iterators and positional iterators.
The drawback to using result set iterators, compared to strongly typed iterators, is that
SQLJ cannot perform as much semantics-checking for your queries.
5-31
Chapter 5
Multirow Query Results: SQLJ Iterators
5. When you finish processing the results of the query, close the iterator to release its
resources.
5-32
Chapter 5
Multirow Query Results: SQLJ Iterators
necessarily involve a round trip to the server. This depends on the row-prefetch
value. This is because you are fetching data from the iterator, and not the
database. However, if the row-prefetch value is 1, then each fetch does involve
a separate trip to the database. The row-prefetch value determines how many
rows are retrieved with each trip to the database.
• Result set iterators use the same FETCH INTO syntax that is used with positional
iterators and are subject to the same restriction at run time. That is, the number of
data items in the SELECT-list must match the number of variables that are assigned
data in the FETCH statement.
• The name of each data item in the SELECT statement, either a table column
name or an alias, must match an iterator column name. However, this is not
case-sensitive. That is, ename or Ename would match ENAME).
• The data type of each iterator column must be compatible with the data type of the
corresponding data item in the SELECT statement according to standard JDBC type
mappings.
The order in which attributes are declared in the named iterator class declaration is
irrelevant. Data is selected into the iterator based on name alone.
A named iterator has a next() method to retrieve data row by row and an accessor
method for each column to retrieve the individual data items. The accessor method
names are identical to the column names. Unlike most accessor method names in
Java, accessor method names in named iterator classes do not start with get. For
example, a named iterator object with a column sal would have a sal() accessor
method.
Note:
The following restrictions apply in naming the columns of a named iterator:
• Column names cannot use Java reserved words.
• Column names cannot have the same name as utility methods
provided in named iterator classes, such as the next(), close(),
getResultSet(), and isClosed() methods. For scrollable named
iterators, this includes additional methods such as previous(), first(),
and last().
5-33
Chapter 5
Multirow Query Results: SQLJ Iterators
of the Java types and names equivalent to or compatible with the column types and
column names in a database table.
The implements clause and with clause are optional, specifying interfaces to
implement and variables to define and initialize, respectively.
See Also:
"Declaration IMPLEMENTS Clause" and "Declaration WITH Clause"
You can declare the following named iterator to use with this table:
#sql public iterator ProjIter (String projname, int id, Date deadline);
This will result in an iterator class with columns of data accessible, using the following
provided accessor methods: projname(), id(), and deadline().
Note:
As with standard Java, any public class should be declared in one of the
following ways:
• 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.
This calculates a deadline for each project by adding its duration to its start date, then
aliases the results as deadline to match the deadline iterator column. It also uses a
5-34
Chapter 5
Multirow Query Results: SQLJ Iterators
WHERE clause so that only future deadlines are processed, that is, deadlines beyond
the current system date in the database.
Similarly, you must create an alias if you want to use a function call. Suppose you have
a MAXIMUM() function that takes a DURATION entry and an integer as input and returns
the maximum of the two. For example, you could input the value 3 to ensure that each
project has at least a three-month duration in your application.
Now, presume you are declaring your iterator as follows:
#sql public iterator ProjIter2 (String projname, int id, float duration);
You could use the MAXIMUM() function in your query, with an alias for the result, as
follows:
ProjIter2 projsIter2;
Generally, you must use an alias in your query for any data item in the SELECT
statement whose name is not a legal Java identifier or does not match a column name
in the iterator.
Remember that in populating a named iterator, the number of columns you select
from the database can never be less than the number of columns in the iterator.
The number of columns you select can be greater than the number of columns in
the iterator, because unmatched columns are ignored. However, this will generate a
warning, unless you have the SQLJ -warn=nostrict option set.
• If there is another row to retrieve from the iterator, then next() retrieves the row
and returns true.
• If there are no more rows to retrieve, next() returns false.
The following is an example of how to access the data of a named iterator, repeating
the declaration, instantiation, and population code illustrated in the preceding section.
Note:
Each iterator has a close() method that you must always call when you
finish retrieving data from the iterator. This is necessary to close the iterator
and free its resources.
5-35
Chapter 5
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 Cursor1 class has a method called NAME(), and not name(). You will have to use
c1.NAME() in the System.out.println statement.
5-36
Chapter 5
Multirow Query Results: SQLJ Iterators
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.
See Also:
"Declaration IMPLEMENTS Clause" and "Declaration WITH Clause"
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.
Note:
As with standard Java, any public class should be declared in one of the
following ways:
• 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.
5-37
Chapter 5
Multirow Query Results: SQLJ Iterators
following will work, because the data items in the SELECT statement are in the same
order as the iterator columns:
EmpIter empsIter;
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.
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.
5-38
Chapter 5
Multirow Query Results: SQLJ Iterators
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);
}
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.
5-39
Chapter 5
Multirow Query Results: SQLJ Iterators
Note:
For the examples in this section, consider the following department and employee
tables:
CREATE TABLE DEPT (
DEPTNO NUMBER(2),
DNAME VARCHAR2(14) );
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.
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:
5-40
Chapter 5
Multirow Query Results: SQLJ Iterators
...
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();
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.
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;
...
System.out.println(deptname);
while (enamesIter.next())
{
System.out.println(enamesIter.ename());
}
enamesIter.close();
...
• 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.
5-41
Chapter 5
Multirow Query Results: SQLJ Iterators
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.
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 5-1 Example: Result Set Column in a Named Iterator
This example uses a column of type ResultSet in a named iterator.
while (iter.next())
{
System.out.println(iter.dname());
5-42
Chapter 5
Multirow Query Results: SQLJ Iterators
while (iter.next())
{
System.out.println(iter.dname());
ENameIter enamesIter = iter.emps();
while (enamesIter.next())
{
System.out.println(enamesIter.ename());
}
enamesIter.close();
}
iter.close();
...
5-43
Chapter 5
Assignment Statements (SET)
...
#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();
...
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.
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 };
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)) };
5-44
Chapter 5
Stored Procedure and Function Calls
...
#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.
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 HR.MYPROC().
Presume that you have defined the following PL/SQL stored procedure:
5-45
Chapter 5
Stored Procedure and Function Calls
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.
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.
Note:
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:
#sql { CALL MAX_DEADLINE };
not:
#sql { CALL MAX_DEADLINE() };
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
HR.MYFUNC().
5-46
Chapter 5
Stored Procedure and Function Calls
Note:
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.
Referring back to the example in "Calling Stored Procedures", 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;
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:
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.
5-47
Chapter 5
Stored Procedure and Function Calls
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();
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.
5-48
6
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:
Objects_ Collections_ and OPAQUE Types
See Also:
Oracle Database JDBC Developer's Guide for a complete list of legal Java
mappings for each Oracle SQL type
Note:
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.
6-1
Chapter 6
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.
6-2
Chapter 6
Supported Types for Host Expressions
Table 6-1 (Cont.) Type Mappings for Supported Host Expression Types
6-3
Chapter 6
Supported Types for Host Expressions
Table 6-1 (Cont.) Type Mappings for Supported Host Expression Types
See Also:
Oracle Database JDBC Developer's Guide for more information about Oracle
type support.
6-4
Chapter 6
Supported Types for Host Expressions
• 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 12c Release 2 (12.2) 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.
• 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:
"NULL-Handling"
• The SQLJ stream classes are required in using streams as host variables.
See Also:
"Support for Streams"
• 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:
"Custom Java Class Interface Specifications"
• For information about SQLJ support for result set and iterator host variables, refer
to "Using Iterators and Result Sets as Host Variables"Using Iterators and Result
Sets as Stored Function Returns.
The following points relate to Oracle extensions:
6-5
Chapter 6
Supported Types for Host Expressions
See Also:
Oracle Database JDBC Developer's Guide for information about these
classes and Oracle extensions
• 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.
• 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.
• 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
See Also:
Oracle Database JDBC Developer's Guide
6-6
Chapter 6
Supported Types for Host Expressions
Table 6-2 Correlation between Oracle Extensions and JDBC 2.0 Types
See Also:
"Custom Java Classes", "Support for BLOB_ CLOB_ and BFILE", and
"Support for Weakly Typed Objects_ References_ and Collections"
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.
Note:
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:
CREATE OR REPLACE TYPE arr_type IS VARRAY(20) OF NUMBER;
CREATE TABLE arr_type (arr_col1 arr_type, arr_col2
arr_type);
6-7
Chapter 6
Supported Types for Host Expressions
See Also:
Oracle Database JDBC Developer's Guide
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.
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.
6-8
Chapter 6
Support for Streams
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;
Note:
Oracle9i release 2 first added support for OPAQUE types and TIMESTAMP
types.
6-9
Chapter 6
Support for 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.
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
Note:
Starting from JDBC 2.0, the CharacterStream class replaces the
AsciiStream and UnicodeStream classes. CharacterStream shelters users
from unnecessary logistics regarding encoding.
6-10
Chapter 6
Support for Streams
See Also:
"Support for BLOB_ CLOB_ and BFILE"
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.
6-11
Chapter 6
Support for Streams
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.
Note:
Although not required, it is recommended that you close the stream after
using it.
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
6-12
Chapter 6
Support for Streams
...
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();
...
...
byte[] bytearray = new byte[100];
6-13
Chapter 6
Support for Streams
Note:
It is not necessary to use a stream as in this example. Alternatively, you can
update the database directly from a byte array.
6-14
Chapter 6
Support for Streams
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 12c Release 2 (12.2) 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.
See Also:
"Stream Class Methods" and "Examples of Retrieving and Processing
Stream Data"
6-15
Chapter 6
Support for Streams
See Also:
"Using Positional Iterators"
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.
Note:
Although not required, it is recommended that you close the local input
stream each time through the iterator processing loop.
Note:
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.
6-16
Chapter 6
Support for Streams
See Also:
"Using Positional Iterators"
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.
8. Close the iterator.
<<<[for 11g?] Use code examples. >>>
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.
Note:
This is just a matter of preference. The former approach is simpler. However,
the latter approach involves more direct and efficient data access.
• 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.
6-17
Chapter 6
Support for Streams
• 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
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.
• 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
6-18
Chapter 6
Support for Streams
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
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.
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;
6-19
Chapter 6
Support for Streams
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.
...
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;
binstream.close();
}
positer.close();
...
6-20
Chapter 6
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();
...
6-21
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
Note:
Closing the stream is recommended, but not required.
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();
...
Note:
Closing the stream is recommended, but not required.
6.3 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
6-22
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
• Other Oracle Database 12c Release 2 (12.2) 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:
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
6-23
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
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"
• "Semantics-Checking and Offline-Parsing Options"
• Oracle Database JDBC Developer's Guide
See Also:
Oracle Database JDBC Developer's Guide for more information about LOBs
and BFILEs and use of supported stream APIs.
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.
6-24
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
Note:
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.
The following example uses a CLOB as the assignment type for a return value from
the longer_clob function:
void readFromLongest(CLOB c1, CLOB c2) throws SQLException
{
CLOB longest;
#sql longest = { VALUES(longer_clob(:c1, :c2)) };
readFromClob(longest);
}
The readFromLongest() method prints the contents of the longer passed CLOB, using
the readFromClob() method defined previously.
6-25
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
The following example uses a BLOB and a CLOB as host variables that receive data
from the table defined, using a SELECT INTO statement:
...
BLOB blob;
CLOB clob;
#sql { SELECT one.b, two.c INTO :blob, :clob
FROM basic_lob_table one, basic_lob_table two
WHERE one.x='one' AND two.x='two' };
#sql { INSERT INTO basic_lob_table VALUES('three', :blob, :clob) };
...
This example selects the BLOB from the first row and the CLOB from the second
row of BASIC_LOB_TABLE. It then inserts a third row into the table using the BLOB and
CLOB selected in the previous operation.
...
NamedLOBIter iter;
#sql iter = { SELECT c FROM basic_lob_table };
if (iter.next())
CLOB c1 = iter.c();
if (iter.next())
CLOB c2 = iter.c();
iter.close();
readFromLongest(c1, c2);
...
This example uses an iterator to select two CLOBs from the first two rows of
BASIC_LOB_TABLE, then prints the larger of the two using the readFromLongest()
method.
6-26
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
LOB and BFILE Host Variables and Positional Iterator FETCH INTO Targets
Host variables of the BLOB, CLOB, and BFILE type can be used with positional
iterators and appear in the INTO-list of the associated FETCH INTO statement if the
corresponding column attribute in the iterator is of the identical type.
The following example uses the BASIC_LOB_TABLE table and the writeToBlob()
method defined in previous examples. Similar code could be written for CLOBs and
BFILEs.
#sql iterator PositionedLOBIter(BLOB);
...
PositionedLOBIter iter;
BLOB blob = null;
#sql iter = { SELECT b FROM basic_lob_table };
for (long rowNum = 1; ; rowNum++)
{
#sql { FETCH :iter INTO :blob };
if (iter.endFetch()) break;
writeToBlob(blob, 512*rowNum);
}
iter.close();
...
This example calls writeToBlob() for each BLOB in BASIC_LOB_TABLE. Each row
writes an additional 512 bytes of data.
Example 6-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 6-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) };
6-27
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
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.
clobLen = clob.length();
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 6-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;
This method reads the contents of a CLOB in chunks of 10 characters at a time. Note
that the chunk host variable is of the String type.
6-28
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
This method goes through a loop that writes to the BLOB in 10-byte chunks until the
specified BLOB length has been reached.
Example 6-8 Example: Use of DBMS_LOB Write Routines with BLOB
This example uses routines of the DBMS_LOB package to write to a BLOB.
void writeToBlob(BLOB blob, long blobLen) throws SQLException
{
byte[] chunk = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
long chunkLen = (long)chunk.length;
This method fills the contents of a BLOB in 10-byte chunks. Note that the chunk host
variable is of the byte[] type.
6-29
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
...
NamedRowidIter iter;
ROWID rowid;
#sql iter = { SELECT first_name, rowid FROM employees };
while (iter.next())
{
if (iter.first_name().equals("Peter Hall"))
{
rowid = iter.rowid();
#sql { UPDATE employees SET salary = salary + 500 WHERE rowid = :rowid };
}
}
iter.close();
...
This example increases the salary of the employee named Peter Hall by $500
according to the ROWID.
Given the preceding stored function, the following example indicates how a ROWID
object is used as the assignment type for the function return result:
ROWID rowid;
#sql rowid = { values(get_rowid('AMY FEINER')) };
#sql { UPDATE employees SET salary = salary + 500 WHERE rowid = :rowid };
This example increases the salary of the employee named Amy Feiner by $500
according to the ROWID.
This example increases the salary of the employee named Peter Hall by $500
according to the ROWID.
6-30
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
...
PositionedRowidIter iter;
ROWID rowid = null;
String ename = null;
#sql iter = { SELECT first_name, rowid FROM employees };
while (true)
{
#sql { FETCH :iter INTO :ename, :rowid };
if (iter.endFetch()) break;
if (ename.equals("PETER HALL"))
{
#sql { UPDATE employees SET salary = salary + 500 WHERE rowid = :rowid };
}
}
iter.close();
...
This example is similar to the previous named iterator example, but uses a positional
iterator with its customary FETCH INTO syntax.
In the preceding code, an iterator iter is created and used to update the employees
table.
Note:
If you want to avoid synchronization problems, then issue a SELECT ... FOR
UPDATE statement.
6-31
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
The iterators that can be used with the WHERE CURRENT OF clause have the following
limitations:
• The query used to populate the iterator should not operate on multiple tables.
• You cannot use a PL/SQL procedure returning a REF CURSOR with the iterator.
• You cannot use an iterator that has been populated from a result set. That is, an
iterator populated using the following statement, where rs is a result set:
#sql iter = {cast :rs}
for_update Option
If for_update option is set at translation time, then "FOR UPDATE" is appended to the
SELECT statements, which in turn return results into a ForUpdate iterator as follows:
% sqlj –for_update abc.sqlj
/* abc.sqlj */
#sql iterator SalByName (double sal, String ename) implements
sqlj.runtime.ForUpdate;
Now, "FOR UPDATE" is appended to the SELECT statement returning the ForUpdate
iterator salbn in the following way:
………
String theSqlTS = “SELECT rowid sjT_rowid,first_name, salary FROM employees
WHERE first_name = :1 FOR UPDATE";
………
Table 6-3 shows the plausible values for the for_update option and the corresponding
SQL statement for the preceding example:
6-32
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
Table 6-3 Plausible values for the for_update option and the corresponding
SQL statement
Note:
If the application already has FOR UPDATE in the select query, then using
these new translator options will throw warnings during online check at
translation time. If offline parsing is chosen during translation, then errors
are not detected at translation time.
Stored procedures and stored functions can return parameters of Oracle REF
CURSOR types. You must use PL/SQL to return a REF CURSOR parameter. You
cannot accomplish this using SQL alone. A PL/SQL stored procedure or function can
declare a variable of some named REF CURSOR type, execute a SELECT statement,
and return the results in the REF CURSOR variable.
6-33
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
See Also:
Oracle Database PL/SQL Language Reference
See Also:
"Using Iterators and Result Sets as Host Variables" for examples illustrating
the use of implicit REF CURSOR variables, including an example of the
CURSOR operator.
Note:
6-34
Chapter 6
Support for JDBC 2.0 LOB Types and Oracle Type Extensions
ORDER BY employee_id;
end
};
return emps;
}
Because the oracle.sql.* classes do not require conversion to Java type format,
they offer greater efficiency and precision than equivalent Java types. You would have
to convert the data to standard Java types, however, to use it with standard Java
programs or to display it to end users.
See Also:
Table 6-1
In the Oracle SQLJ implementation, however, you can map to nondefault types as
long as the data type is convertible from numeric and you use Oracle9i Database
or later version, an Oracle JDBC driver, Oracle-specific code generation or Oracle
customizer, and Oracle SQLJ run time. The CHAR, VARCHAR2, LONG, and NUMBER types
are convertible. For example, you can retrieve data from a CHAR column into a
BigDecimal variable. However, to avoid errors, you must be careful that the character
data consists only of numbers.
Note:
The BigDecimal class is in the standard java.math package.
6-35
7
Objects, Collections, and OPAQUE Types
This chapter discusses how the Oracle SQLJ implementation supports user-defined
SQL types. There is also a small section at the end regarding Oracle OPAQUE types.
The chapter consists of the following sections:
• Oracle Objects and Collections
• Custom Java Classes
• User-Defined Types
• Strongly Typed Objects and References in SQLJ Executable Statements
• Strongly Typed Collections in SQLJ Executable Statements
• Serialized Java Objects
• Weakly Typed Objects_ References_ and Collections
• Oracle OPAQUE Types
See Also:
Oracle Database SQL Language Reference and Oracle Database
Development Guide.
7-1
Chapter 7
Oracle Objects and Collections
Note that using Oracle extensions in your code requires the following:
• Use one of Oracle JDBC drivers.
• Use default Oracle-specific code generation or, for ISO code generation,
customize the profiles appropriately. For Oracle-specific generated code, no
profiles are produced so customization is not applicable. Oracle JDBC application
programming interfaces (APIs) are called directly through the generated Java
code.
Note:
Oracle recommends the use of the default customizer,
oracle.sqlj.runtime.util.OraCustomizer.
• 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.
Note:
Oracle-specific types for Oracle objects and collections are included in the
oracle.sql package.
7-2
Chapter 7
Oracle Objects and Collections
See Also:
"Connection Options" and "Semantics-Checking and Offline-Parsing Options"
See Also:
"Additional Uses for ORAData Implementations"
• The SQLData interface is intended only for custom object classes. The ORAData
interface can be used for any custom Java class.
Terminology Notes
• User-defined SQL object types and user-defined SQL collection types are referred
to as user-defined types (UDTs).
• Custom Java classes for objects, references, and collections are referred to as
custom object classes, custom reference classes, and custom collection classes,
respectively.
See Also:
Oracle Database Object-Relational Developer's Guide for general
information about Oracle object features and functionality
Oracle objects can also have methods, or stored procedures, associated with the
object type. These methods can be either static methods or instance methods and can
be implemented either in PL/SQL or Java. Their signatures can include any number
7-3
Chapter 7
Oracle Objects and Collections
of input, output, or input-output parameters. All this depends on how they are initially
defined
Note:
The elements in a VARRAY or the rows in a nested table can be of a
user-defined object type, and VARRAY and nested table types can be used
for attributes in a user-defined object type. Oracle Database 12c Release 2
(12.2) supports nesting of collection types. The elements of a VARRAY or
rows of a nested table can be of another VARRAY or nested table type, or
these elements can be of a user-defined object type that has VARRAY or
nested table attributes.
Similarly, you can define a variable-length array MYVARR as VARRAY(10) of NUMBER and
a nested table NTBL of CHAR(20). The MYVARR and NTBL collection types become Oracle
data types, and you can have table columns of either type. Each row of a MYVARR
7-4
Chapter 7
Custom Java Classes
Oracle Database 12c Release 2 (12.2) includes a set of APIs for Oracle-specific
custom Java class functionality for user-defined types: oracle.sql.ORAData and
oracle.sql.ORADataFactory.
7-5
Chapter 7
Custom Java Classes
See Also:
Oracle Database JDBC Developer’s Guide
The ORAData interface specifies a toDatum() method for data conversion from Java
format to SQL format. This method takes as input your connection object and
converts data to the appropriate oracle.sql.* representation. The connection object
is necessary so that the JDBC driver can perform appropriate type checking and type
conversions at run time. The ORAData and toDatum() specification is as follows:
interface oracle.sql.ORAData
{
oracle.sql.Datum toDatum(java.sql.Connection c) throws SQLException;
}
To complete the relationship between the ORAData and ORADataFactory interfaces, you
must implement a static getORADataFactory() method in any custom Java class that
implements the ORAData interface. This method returns an object that implements the
ORADataFactory interface and that, therefore, can be used to create instances of your
custom Java class. This returned object can itself be an instance of your custom Java
class, and its create() method is used by Oracle JDBC driver to produce further
instances of your custom Java class, as necessary.
SQLData Specification
Standard JDBC 2.0 supplies the java.sql.SQLData interface to use in mapping and
converting structured object types to Java classes. This interface is intended for
mapping structured object types only, not object references, collections or arrays, or
other SQL types.
The SQLData interface is a JDBC 2.0 standard, specifying a readSQL() method to read
data into a Java object and a writeSQL() method to write to the database from a Java
object.
For additional information about standard SQLData functionality, refer to the Sun
Microsystems JDBC 2.0 or later API specification.
7-6
Chapter 7
Custom Java Classes
Note:
Custom Java classes for user-defined types are often referred to in this
manual as "wrapper classes".
7-7
Chapter 7
Custom Java Classes
Note:
The OracleTypes class simply defines a type code, which is an
integer constant, for each Oracle data type. For standard SQL types,
the OracleTypes entry is identical to the entry in the standard
java.sql.Types type definitions class.
See Also:
"Serialized Java Objects"
• For custom Java classes with _SQL_TYPECODE of STRUCT, REF, or ARRAY, that is, for
custom Java classes that represent objects, object references, or collections, the
class has a constant that indicates the relevant user-defined type name. This is as
follows:
– Custom object classes and custom collection classes must have a String
constant, _SQL_NAME, initialized to the SQL name you declared for the user-
defined type, as follows:
public static final String _SQL_NAME = UDT name;
For example, the custom object class for a user-defined PERSON object will
have the constant:
public static final String _SQL_NAME = "PERSON";
The same can be specified along with the schema, if appropriate, as follows:
public static final String _SQL_NAME = "HR.PERSON";
The custom collection class for a collection of PERSON objects, which you have
declared as PERSON_ARRAY, will have the constant:
public static final String _SQL_NAME = "PERSON_ARRAY";
– Custom reference classes must have a String constant, _SQL_BASETYPE,
initialized to the SQL name you declared for the user-defined type being
referenced, as follows:
public static final String _SQL_BASETYPE = UDT name;
7-8
Chapter 7
Custom Java Classes
The custom reference class for PERSON references will have the constant:
public static final String _SQL_BASETYPE = "PERSON";
7-9
Chapter 7
Custom Java Classes
• The connection context type must have been declared using the
with attribute typeMap that specifies an associated class implementing
java.util.PropertyResourceBundle. In the preceding example, SDContext may
be declared as follows:
#sql public static context SDContext with (typeMap="SDMap");
• The type map resource must provide the mapping from SQL object types to
corresponding Java classes that implement the java.sql.SQLData interface. This
mapping is specified with entries of the following form:
class.java_class_name=STRUCT sql_type_name
The STRUCT keyword can also be omitted. In the example, the SDMap.properties
resource file may contain the following entries:
class.Address=STRUCT HR.ADDRESS
class.pack.Person=PERSON
class.pack.Manager$InnerPM=STRUCT PRODUCT_MANAGER
Although the period (.) separates package and class name, you must use the
dollar sign ($) to separate an inner class name.
Note:
If you used the default Oracle-specific code generation in this example, then
any iterator that is used for a statement whose context type is SDContext
must also have been declared with the same associated type map, SDMap,
such as in the following example:
#sql public static iterator SDIter with (typeMap="SDMap");
...
SDContext sdctx = ...
SDIter sditer;
#sql [sdctx] sditer = { SELECT ...};
This is to ensure that proper code is generated for the iterator class.
7-10
Chapter 7
Custom Java Classes
for registerOutParameter() by Oracle JDBC driver. Also, for OUT parameter type
registration, the SQL type is "frozen in" by the type map in effect during translation.
• The SQLJ type map is independent of any JDBC type map you may be using on
the underlying connection. Thus, you must be careful when you are mixing SQLJ
and JDBC code if both use SQLData wrappers. However, you can easily extract the
type map in effect on a given SQLJ connection context:
ctx.getTypeMap();
• The Java class declares the String constant _SQL_NAME, which defines the name
of the SQL type that is being wrapped by the Java class. In the example, the
Address class would have the following field declaration:
public static final String _SQL_NAME="HR.ADDRESS";
Note:
7-11
Chapter 7
Custom Java Classes
Note:
This discussion assumes you are creating .java files for your custom objects
and collections, not .sqlj files. Any .sqlj files must be included in the SQLJ
command line.
For example, if ObjectDemo.sqlj uses the ADDRESS and PERSON Oracle object types
and you have produced custom Java classes for these objects, then you can run SQLJ
as follows.
• If -checksource=true and the classpath includes the custom Java source location:
% sqlj ObjectDemo.sqlj
• If -checksource=false (this is a single wraparound line):
% sqlj ObjectDemo.sqlj Address.java AddressRef.java Person.java
PersonRef.java
You also have the choice of using your Java compiler to compile custom .java source
files directly. If you do this, then you must do it prior to translating .sqlj files.
Note:
Because ORAData implementations rely on Oracle-specific features, SQLJ will
report numerous portability warnings if you do not use the -warn=noportable
translator portability setting, which is the default.
7-12
Chapter 7
Custom Java Classes
accomplish this with classes that implement ORAData, but not SQLData, as in the
following examples:
• Perform encryption and decryption or validation of data.
• Perform logging of values that have been read or are being written.
• Parse character columns, such as character fields containing URL information,
into smaller components.
• Map character strings into numeric constants.
• Map data into more desirable Java formats, such as mapping a DATE field to
java.util.Date format.
• Customize data representation, for example, data in a table column is in feet, but
you want it represented in meters after it is selected.
• Serialize and deserialize Java objects, for example, into or out of RAW fields.
Note:
This sort of functionality is not possible through the SQLData interface, as
SQLData implementations can wrap only structured object types.
See Also:
"Serialized Java Objects"
Note:
This is not a complete application. There is no main() method.
import java.util.Date;
import oracle.sql.ORAData;
import oracle.sql.DATE;
import oracle.sql.ORADataFactory;
import oracle.jdbc.OracleTypes;
7-13
Chapter 7
Custom Java Classes
7-14
Chapter 7
Custom Java Classes
(sb.charAt(offset)- '0') * 10 +
(sb.charAt(offset+1)- '0');
} else {
y = (sb.charAt(offset)- '0') * 1000 +
(sb.charAt(offset+1)- '0') * 100 +
(sb.charAt(offset+2)- '0') * 10 +
(sb.charAt(offset+3)- '0');
}
retval[0]=y;
retval[1]=m;
retval[2]=d;
// System.out.println("Constructing date from string as: "+d+"/"+m+"/"+y);
return retval;
}
private BetterDate(int [] stuff) {
this(stuff[0], stuff[1], stuff[2]);
}
// takes a string in the format: "mm-dd-yyyy" or "mm/dd/yyyy" or
// "mm-dd-yy" or "mm/dd/yy" (which assumes the current century)
public BetterDate(String s) {
this(BetterDate.deconstructString(s));
}
7-15
Chapter 7
User-Defined Types
Where typename is the desired name of your object type, attrname1 through
attrnameN are the desired attribute names, and datatype1 through datatypeN are
the attribute data types.
The remainder of this section provides an example of creating user-defined object
types in Oracle Database 12c Release 1 (12.1).
In this example, the following items are created using SQL:
• Two object types, PERSON and ADDRESS
• A typed table for PERSON objects
• An EMPLOYEES table that includes an ADDRESS column and two columns of PERSON
references
7-16
Chapter 7
User-Defined Types
7-17
Chapter 7
User-Defined Types
Note:
Use of a table alias, such as p in the example, is a recommended general
practice in the Oracle SQL implementation, especially in accessing tables
with user-defined types. It is required syntax in some cases where object
attributes are accessed. Even when not required, it helps in avoiding
ambiguities. Refer to the Oracle Database SQL Language Reference for
more information about table aliases.
The typename designation is the desired name of your VARRAY type, n is the desired
maximum number of elements in the array, and datatype is the data type of the array
elements. For example:
CREATE TYPE myvarr IS VARRAY(10) OF INTEGER;
SQL commands to create nested table types are of the following form:
CREATE TYPE typename AS TABLE OF datatype;
The typename designation is the desired name of your nested table type and datatype
is the data type of the table elements. This can be a user-defined type as well as a
standard data type. A nested table is limited to one column, although that one column
type can be a complex object with multiple attributes. The nested table, as with any
database table, can have any number of rows. For example:
CREATE TYPE person_array AS TABLE OF person;
This command creates a nested table where each row consists of a PERSON object.
The rest of this section provides an example of creating a user-defined collection type,
as well as object types, in Oracle Database 12c Release 2 (12.2).
The following items are created and populated using SQL:
• Two object types, PARTICIPANT_T and MODULE_T
• A collection type, MODULETBL_T, which is a nested table of MODULE_T objects
• A PROJECTS table that includes a column of PARTICIPANT_T references and a
column of MODULETBL_T nested tables
• A collection type PHONE_ARRAY, which is a VARRAY of VARCHAR2(30)
• PERSON and ADDRESS objects (repeating the same definitions used earlier)
• An EMPLOYEES table, which includes a PHONE_ARRAY column
The script for creating these items is as follows:
7-18
Chapter 7
User-Defined Types
SHOW ERRORS
CREATE TYPE PHONE_ARRAY IS VARRAY (10) OF varchar2(30)
/
7-19
Chapter 7
Strongly Typed Objects and References in SQLJ Executable Statements
)
/
And the following definition of the EMPADDRS table, which includes an ADDRESS column
and an ADDRESS reference column:
CREATE TABLE empaddrs
( name VARCHAR(60),
home ADDRESS,
loc REF ADDRESS );
Once you create a custom Java class, Address, and custom reference class,
AddressRef, corresponding to the ADDRESS Oracle object type, you can use Address
and AddressRef in a named iterator as follows:
#sql iterator EmpIter (String name, Address home, AddressRef loc);
7-20
Chapter 7
Strongly Typed Objects and References in SQLJ Executable Statements
...
EmpIter ecur;
#sql ecur = { SELECT name, home, loc FROM empaddrs };
while (ecur.next()) {
Address homeAddr = ecur.home();
// Print out the home address.
System.out.println ("Name: " + ecur.name() + "\n" +
"Home address: " + homeAddr.getStreet() + " " +
homeAddr.getZip());
// Now update the loc address zip code through the address reference.
AddressRef homeRef = ecur.loc();
Address location = homeRef.getValue();
location.setZip(new BigDecimal(98765));
homeRef.setValue(location);
}
...
The ecur.home() method call extracts an Address object from the home column of the
iterator and assigns it to the homeAddr local variable (for efficiency). The attributes of
that object can then be accessed using standard Java dot syntax:
homeAddr.getStreet()
Use the getValue() and setValue() methods to manipulate the location address (in
this case its zip code).
Address addr;
Address new_addr;
int empnum = 1001;
try {
#sql {
SELECT office_addr
INTO :addr
FROM employees
WHERE empnumber = :empnum };
System.out.println("Current office address of employee 1001:");
printAddressDetails(addr);
7-21
Chapter 7
Strongly Typed Objects and References in SQLJ Executable Statements
try {
#sql {
UPDATE employees
SET office_addr = :addr
WHERE empnumber = :empnum };
System.out.println
("Updated employee 1001 to new address at Oracle Parkway.");
try {
#sql {
SELECT office_addr
INTO :new_addr
FROM employees
WHERE empnumber = :empnum };
Note the use of the setStreet() accessor method of the Address object.
This example uses the printAddressDetails() utility. The source code for this
method is as follows:
static void printAddressDetails(Address a) throws SQLException
{
if (a == null) {
System.out.println("No Address available.");
return;
}
7-22
Chapter 7
Strongly Typed Objects and References in SQLJ Executable Statements
...
// Inserting an object
try {
#sql {
7-23
Chapter 7
Strongly Typed Collections in SQLJ Executable Statements
SELECT deref(manager)
INTO :manager
FROM employees e
WHERE empnumber = :empnum };
}
...
Note:
This example uses table alias syntax (p) as discussed previously. Also, the
REF syntax is required in selecting a reference through the object to which
it refers, and the DEREF syntax is required in selecting an object through a
reference. Refer to the Oracle Database SQL Language Reference for more
information about table aliases, REF, and DEREF.
Note:
In the Oracle SQLJ implementation, VARRAY types and nested table types
can be retrieved only in their entirety. This is as opposed to the Oracle SQL
implementation, where nested tables can be selectively queried.
7-24
Chapter 7
Strongly Typed Collections in SQLJ Executable Statements
When you see TABLE used as it is here, realize that it is referring to a single nested
table that has been selected from a column of an outer table.
Note:
This example uses table alias syntax (a for projects, b for the nested table,
and p for employees) as discussed previously.
First, the scalar values are set (id, name, start_date, duration), then the nested table
values are set. This involves an extra level of abstraction, because the nested table
elements are objects with multiple attributes. In setting the nested table values, each
attribute value must be set for each MODULE_T object in the nested table. Finally, the
owner values, initially set to null, are set in a separate statement.
7-25
Chapter 7
Strongly Typed Collections in SQLJ Executable Statements
try {
#sql { UPDATE Projects pr
SET owner=(SELECT ref(pa) FROM participants pa WHERE pa.empno = 7698)
WHERE pr.id=600 };
} catch ( Exception e) {
System.out.println("Error:insertProject2:update");
e.printStackTrace();
}
}
try {
#sql {SELECT modules INTO :mymodules
FROM projects WHERE id=:projId };
showArray(mymodules);
} catch(Exception e) {
System.out.println("Error:getModules2");
e.printStackTrace();
}
}
7-26
Chapter 7
Strongly Typed Collections in SQLJ Executable Statements
+a.length());
ModuleT[] modules = a.getArray();
These methods use table alias syntax, as discussed previously. In this case, m is used
for the nested table, and p is used for the participants table.
/* assignModule
Illustrates accessing the nested table using the TABLE construct
and updating the nested table row
*/
public static void assignModule(int projId, String moduleName,
String modOwner) throws Exception
{
System.out.println("Update:Assign '"+moduleName+"' to '"+ modOwner+"'");
try {
#sql {UPDATE TABLE(SELECT modules FROM projects WHERE id=:projId) m
SET m.module_owner=
(SELECT ref(p) FROM participants p WHERE p.ename= :modOwner)
WHERE m.module_name = :moduleName };
} catch(Exception e) {
System.out.println("Error:insertModules");
e.printStackTrace();
}
}
/* deleteUnownedModules
// Demonstrates deletion of the Nested table element
*/
7-27
Chapter 7
Strongly Typed Collections in SQLJ Executable Statements
try {
#sql { DELETE TABLE(SELECT modules FROM projects WHERE id=:projId) m
WHERE m.module_owner IS NULL };
} catch(Exception e) {
System.out.println("Error:deleteUnownedModules");
e.printStackTrace();
}
}
The CURSOR syntax is part of the nested SELECT statement that populates the nested
iterators. Once the data has been selected, it is output to the user through the iterator
accessor methods.
This example uses required table alias syntax, as discussed previously. In this case, a
for the projects table and b for the nested table.
...
...
7-28
Chapter 7
Strongly Typed Collections in SQLJ Executable Statements
while (projs.next()) {
System.out.println( "\n'" + projs.name() + "' Project Id:"
+ projs.id() + " is owned by " +"'"+ projs.owner() +"'"
+ " start on "
+ projs.start_date());
// Notice the modules from the ProjIter are assigned to the module
// iterator variable
mods = projs.modules();
System.out.println ("Modules in this Project are : ");
while(mods.next()) {
System.out.println (" "+ mods.moduleId() + " '"+
mods.moduleName() + "' owner is '" +
mods.moduleOwner()+"'" );
} // end of modules
mods.close();
} // end of projects
projs.close();
}
7-29
Chapter 7
Serialized Java Objects
phone_nums phone_array
)
/
And presume that you created a PhoneArray custom collection class to map from the
PHONE_ARRAY SQL type.
The following method selects a row from this table, placing the data into a host
variable of the PhoneArray type:
private static void selectVarray() throws SQLException
{
PhoneArray ph;
#sql {select phone_nums into :ph from employees where empnumber=2001};
System.out.println(
"there are "+ph.length()+" phone numbers in the PhoneArray. They are:");
7-30
Chapter 7
Serialized Java Objects
In some cases, however, you may want to store Java objects "as-is" and retrieve them
later, using database columns of the RAW or BLOB type. There are different ways to
accomplish this:
• You can map a serializable Java class to RAW or BLOB columns by using a
nonstandard extension to the type map facility or by adding a type code field to the
serializable class, so that instances of the serializable class can be stored as RAW
or BLOB.
• You can use the ORAData facility to define a serializable wrapper class whose
instances can be stored in RAW or BLOB columns.
Serializing in any of these ways works for any Oracle SQLJ run-time library.
This section covers the following topics:
• Serializing Java Classes to RAW and BLOB Columns
• SerializableDatum: an ORAData Implementation
• SerializableDatum in SQLJ Applications
• SerializableDatum (Complete Class)
You must use the classes only in statements that use explicit connection context
instances of a declared connection context type, such as SerContext in the following
example:
SAddress a =...;
pack.SPerson p =...;
pack.Manager.InnerSPM pm =...;
SerContext ctx = new SerContext(url,user,pwd,false);
#sql [ctx] { ... :a ... :OUT p ... :INOUT pm ... };
7-31
Chapter 7
Serialized Java Objects
Although the period (.) separates package and class names, you must use the
dollar sign ($) to separate an inner class name.
Note that this Oracle-specific extension can be placed in the same type map resource
as standard SQLData type map entries.
Note:
Using the type map facility supersedes manually adding the _SQL_TYPECODE
field to the class.
RAW columns are limited in size. You might experience run-time errors if the actual size
of the serialized Java object exceeds the size of the column.
Column size is much less restrictive for BLOB columns. Writing a serialized Java object
to a BLOB column is supported by Oracle JDBC Oracle Call Interface (OCI) driver
and Oracle JDBC Thin driver. Retrieving a serialized object from a BLOB column is
supported by all Oracle JDBC drivers since Oracle9i.
7-32
Chapter 7
Serialized Java Objects
Finally, treating serialized Java objects this way is an Oracle-specific extension and
requires Oracle SQLJ run time as well as either the default Oracle-specific code
generation (-codegen=oracle during translation) or, for ISO standard code generation
(-codegen=iso), Oracle-specific profile customization.
10iProd: Note that future versions of Oracle might support SQL types that directly
encapsulate Java serialized objects. These are described as JAVA_OBJECT SQL
types in JDBC 2.0. At that point, you can replace each of the BLOB and RAW
designations by the names of their corresponding JAVA_OBJECT SQL types, and you
can drop the oracle- prefix on the entries.
Note:
The implementation of this particular serialization mechanism does not use
JDBC type maps. The map (to BLOB or to RAW) is hardcoded in the Oracle
profile customization at translation time, or is generated directly into Java
code.
An example of such a situation is if you want to serialize and deserialize Java objects
into and out of RAW fields, with a custom Java class that maps to the oracle.sql.RAW
type. This could apply equally to BLOB fields, with a custom Java class that maps to the
oracle.sql.BLOB type.
Note:
This application uses classes from the java.io, java.sql, oracle.sql, and
oracle.jdbc packages. The import statements are not shown here.
7-33
Chapter 7
Serialized Java Objects
{
return FACTORY;
}
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(m_data);
oos.close();
return new RAW(os.toByteArray());
} catch (Exception e) {
throw new SQLException("SerializableDatum.toDatum: "+e.toString()); }
4. Implement data conversion from an oracle.sql.RAW object to a
SerializableDatum object. This step deserializes the data.
7-34
Chapter 7
Serialized Java Objects
new ORADataFactory()
{
public ORAData create(Datum d, int sqlCode) throws SQLException
{
if (sqlCode != _SQL_TYPECODE)
{
throw new SQLException
("SerializableDatum: invalid SQL type "+sqlCode);
}
return (d==null) ? null : new SerializableDatum((RAW)d);
}
};
...
PersonIter pcur;
7-35
Chapter 7
Serialized Java Objects
// Implementation of toDatum()
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(m_data);
oos.close();
return new RAW(os.toByteArray());
} catch (Exception e) {
throw new SQLException("SerializableDatum.toDatum: "+e.toString()); }
}
7-36
Chapter 7
Weakly Typed Objects, References, and Collections
new ORADataFactory()
{
public ORAData create(Datum d, int sqlCode) throws SQLException
{
if (sqlCode != _SQL_TYPECODE)
{
throw new SQLException(
"SerializableDatum: invalid SQL type "+sqlCode);
}
return (d==null) ? null : new SerializableDatum((RAW)d);
}
};
7-37
Chapter 7
Oracle OPAQUE Types
7-38
Chapter 7
Oracle OPAQUE Types
• It can be used as the data type of a column in a table or view. XMLType can store
any content but is designed to optimally store XML content. An instance of it can
represent an XML document in SQL.
• It has a SQL API with built-in member functions that operate on XML content. For
example, you can use XMLType functions to create, query, extract, and index XML
data stored in an Oracle Database 12c Release 1 (12.1) instance.
• It can be used in stored procedures for parameters, return values, and variables.
• Its functionality is also available through APIs provided in PL/SQL, Java, and C
(OCI).
See Also:
Oracle XML DB Developer's Guide
7-39
8
Advanced Language Features
This chapter discusses advanced SQLJ language features for use in coding your
application. For more basic topics, refer to Basic Language Features.
The following topics are discussed:
• Connection Contexts
• Execution Contexts
• Multithreading in SQLJ
• Iterator Class Implementation and Advanced Functionality
• Advanced Transaction Control
• SQLJ and JDBC Interoperability
• Support for Dynamic SQL
• Using Stored Outlines
• Using Plan Baselines
See Also:
"Connection Considerations" for an overview of connection basics, focusing
on situations where you are using just a single set of SQL entities and a
single connection context class.
8-1
Chapter 8
Connection Contexts
See Also:
"Connection Options"
If you have SQLJ statements that use a broad and perhaps unrelated group of SQL
entities, but you use only a single connection context class for these statements, then
the exemplar schema you provide must be very general. It must contain all the tables,
views, and stored procedures used throughout all the statements. Alternatively, if all
the SQLJ statements using a given connection context class use a tight, presumably
interrelated, set of SQL entities, then you can provide a more specific exemplar
schema that enables more thorough and meaningful semantics-checking.
8-2
Chapter 8
Connection Contexts
Note:
When you construct a connection context instance, specify a particular schema and a
particular session and transaction in which SQL operations will execute. You typically
accomplish this by specifying a user name, password, and database URL as input
to the constructor of the connection context class. The connection context instance
manages the set of SQL operations performed during the session.
In each SQLJ statement, you can specify a connection context instance to use. The
following example shows basic declaration and use of a connection context class,
MyContext, to connect to two different schemas. For typical usage, assume these
schemas include a set of SQL entities with common names and data types.
#sql context MyContext;
...
MyContext mctx1 = new MyContext
("jdbc:oracle:thin:@localhost:5221/myservice", "HR", "hr", false);
MyContext mctx2 = new MyContext
("jdbc:oracle:thin@localhost:5221/myservice", "brian", "mypasswd", false);
8-3
Chapter 8
Connection Contexts
would not see changes to the database made from the other until the changes
are committed. The only exception to this would be if both connection context
instances were created from the same underlying Java Database Connectivity (JDBC)
connection instance. One of the constructors of any connection context class takes a
JDBC connection instance as input.
Note:
• 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. For more information, refer to "Basic
Transaction Control".
• If a connection context class is declared with a data source with clause,
then it incorporates a different set of constructors. Refer to "Standard
Data Source Support" for more information.
This results in the SQLJ translator generating a class that implements the
sqlj.runtime.ConnectionContext interface and extends some base class, probably
an abstract class, that also implements the ConnectionContext interface. This base
class would be a feature of the particular SQLJ implementation you are using. The
implements clause and with clause are optional, specifying additional interfaces to
implement and variables to define and initialize, respectively.
8-4
Chapter 8
Connection Contexts
See Also:
"Declaration IMPLEMENTS Clause" and "Declaration WITH Clause"
The following is an example of what the SQLJ translator generates (with method
implementations omitted):
For example:
OrderEntryCtx myOrderConn = new OrderEntryCtx
("jdbc:oracle:thin:@localhost:5221/myservice", "HR", "hr", true);
Note:
8-5
Chapter 8
Connection Contexts
Specify the connection context instance inside square brackets following the #sql
token. For example, in the following SQLJ statement, the connection context instance
is myOrderConn from the previous example:
#sql [myOrderConn] { UPDATE TAB2 SET COL1 = :w WHERE :v < COL2 };
In this way, you can specify an instance of either the DefaultContext class or any
declared connection context class.
In closing a connection context instance that shares the underlying connection with
another connection instance, you might want to keep the underlying connection open.
class MultiSchemaDemo
{
public static void main(String[] args) throws SQLException
{
// set the default connection to the URL, user, and password
// specified in your connect.properties file
Oracle.connect(MultiSchemaDemo.class, "connect.properties");
new MultiSchemaDemo().printEmployees(deptCtx);
deptCtx.close();
}
8-6
Chapter 8
Connection Contexts
Note:
Extending connection context classes is not permitted in the SQLJ
specification and is not supported by the Oracle SQLJ implementation.
ConnectionContext Interface
Each connection context class implements the sqlj.runtime.ConnectionContext
interface.
Basic methods specified by this interface include the following:
• close(boolean CLOSE_CONNECTION/KEEP_CONNECTION): Releases all resources
used in maintaining this connection and closes any open connected profiles.
It may close the underlying JDBC connection, depending on whether
CLOSE_CONNECTION or KEEP_CONNECTION is specified. These are static boolean
constants of the ConnectionContext interface.
• getConnection(): Returns the underlying JDBC connection object for this
connection context instance.
• getExecutionContext(): Returns the default ExecutionContext instance for this
connection context instance.
8-7
Chapter 8
Connection Contexts
See Also:
"Execution Contexts"
...
MyContext myctx1 = new MyContext(url, user, password, autocommit);
...
MyContext.setDefaultContext(myctx1);
...
#sql [MyContext.getDefaultContext()] { SQL operations };
...
Additionally, each connection context class defines methods for control of SQLJ
statement caching. The following are the static methods:
• setDefaultStmtCacheSize(int)
• int getDefaultStmtCacheSize()
The following are the instance methods:
• setStmtCacheSize(int)
• int getStmtCacheSize()
By default, statement caching is enabled.
8-8
Chapter 8
Connection Contexts
You can create an interface called HasConnection, for example, that specifies a
getConnection() method, but does not specify other methods found in a connection
context class. You can then declare a connection context class but expose only the
getConnection() functionality by assigning a connection context instance to a variable
of the HasConnection type, instead of to a variable that has the type of your declared
connection context class.
Assuming HasConnection is in the mypackage package, the declaration will be as
follows:
#sql public context MyContext implements mypackage.HasConnection;
For example:
HasConnection myConn = new MyContext
("jdbc:oracle:thin:@localhost:5221/myservice", "HR", "hr", true);
8-9
Chapter 8
Connection Contexts
Note:
Remember that the exemplar schema you specify in your translator option
settings does not specify the schema to be used at run time. The exemplar
schema furnishes the translator only with a set of SQL entities to compare
against the entities you use in your SQLJ executable statements.
See Also:
Oracle Database JDBC Developer’s Guide
Any connection context class that you declare with a dataSource property provides
additional constructors. To continue the EmpCtx example, the following constructors are
provided:
• EmpCtx(): Looks up the data source for jdbc/EmpDB and then calls the
getConnection() method on the data source to obtain a connection.
8-10
Chapter 8
Connection Contexts
• EmpCtx(String user, String password): Looks up the data source for jdbc/
EmpDB and calls the getConnection(user,password) method on the data source to
obtain a connection.
• EmpCtx(ConnectionContext ctx): Delegates to ctx to obtain a connection.
Any connection context class declared with a dataSource property also omits a
number of DriverManager-based constructors. Continuing the EmpCtx example, the
following constructors are omitted:
• EmpCtx(Connection conn)
• EmpCtx(String url, String user, String password, boolean autoCommit)
• EmpCtx(String url, boolean autoCommit)
• EmpCtx(String url, java.util.Properties info, boolean autoCommit)
• EmpCtx(String url, boolean autoCommit)
Note:
Be aware of the following points related to the auto-commit status of the
connections you establish:
• If you use the Oracle class, then auto-commit is off unless you turn it on
explicitly.
• If you use DefaultContext or a connection context class with
DriverManager-style constructors, then the auto-commit setting must
always be specified explicitly.
• If you use the data source mechanism, then the auto-commit setting
is inherited from the underlying data source. In most environments, the
data source object originates from JDBC and the auto-commit option
is on. To avoid unexpected behavior, always check the auto-commit
setting.
8-11
Chapter 8
Connection Contexts
This mechanism provides a portable means to define and install a default JDBC
connection for the default SQLJ connection context.
8-12
Chapter 8
Connection Contexts
See Also:
Oracle Database JDBC Developer's Guide
8-13
Chapter 8
Connection Contexts
Note:
The OracleSqljDataSource class implements the java.io.Serializable
interface. It is therefore serializable and can be used in clustered
environments, such as Oracle9i Application Server Containers for J2EE
(OC4J).
Note:
8-14
Chapter 8
Connection Contexts
• oracle.sqlj.runtime.SqljConnBean
• oracle.sqlj.runtime.SqljConnCacheBean
8-15
Chapter 8
Connection Contexts
ConnBean and ConnCacheBean include methods that return JDBC connection objects.
SqljConnBean and SqljConnCacheBean extend this functionality to support a bean
property called ContextClass of type String and to return SQLJ connection context
instances.
Note:
The SqljConnBean class implements the java.io.Serializable interface. It
is therefore serializable and can be used in clustered environments, such as
OC4J.
Once a connection context instance has been created and stored, the behavior of
subsequent getDefaultContext() or getContext() calls will depend on the type of
the stored connection context and, for getContext(), on the connection context type
specified in the ContextClass property, as follows:
8-16
Chapter 8
Connection Contexts
type). This becomes the new connection context instance stored in the
SqljConnBean instance.
• For subsequent getContext() calls:
– If the stored connection context instance is of the same type as that specified
by the ContextClass property: The method will keep returning that instance.
– If the stored connection context instance is not of the same type as that
specified by ContextClass: The method will close the stored connection
context instance and reuse the underlying JDBC connection to create and
return a new connection context instance, an instance of what is specified in
ContextClass. This becomes the new connection context instance stored in
the SqljConnBean instance.
Note:
When SqljConnBean closes a connection context instance, it does so with
the KEEP_CONNECTION setting, leaving the underlying JDBC connection intact.
8-17
Chapter 8
Connection Contexts
Note:
This example uses the ContextClass property for illustrative purposes.
However, be aware that DefaultContext is the default value anyway and
if you want to use DefaultContext, then the value of ContextClass is
irrelevant, if you use getDefaultContext() instead of getContext().
8-18
Chapter 8
Connection Contexts
Note:
Oracle
Database Other
Resource
8-19
Chapter 8
Connection Contexts
Note:
The following is not a complete example and contains only relevant codes to
create and use an XADatasource.
8-20
Chapter 8
Connection Contexts
8-21
Chapter 8
Connection Contexts
}
} //end class
The following examples explain the different SQLJ methods that can accept a JDBC
connection obtained from an OracleXADatasource.
8-22
Chapter 8
Connection Contexts
System.out.print(iter.id());
System.out.print(" ");
System.out.println(iter.name());
}
}
catch (Exception e){
System.out.println(e);
e.printStackTrace();
}
}
8-23
Chapter 8
Connection Contexts
8-24
Chapter 8
Execution Contexts
See Also:
Oracle Database Backup and Recovery User’s Guide for more information
about configuring the services to connect to various pluggable databases
8-25
Chapter 8
Execution Contexts
Note:
There is only one execution context class, unlike connection context classes
where you declare additional classes as desired. Every execution context is
an instance of the ExecutionContext class. So while the term connection
context usually refers to a class that you have declared, the term execution
context always refers to an instance of the ExecutionContext class. This
document specifies connection context class, connection context instance,
and execution context instance to avoid confusion.
8-26
Chapter 8
Execution Contexts
threaded and you want the same set of SQL control parameters to apply to all the
connection context instances.
See Also:
"Execution Context Methods"
To use different execution context instances with a single connection context instance,
you must create additional instances of the ExecutionContext class and specify them
appropriately with your SQLJ statements.
You can then specify this execution context instance for use with any particular SQLJ
statement, much as you would specify a connection context instance. The general
syntax is as follows:
#sql [<conn_context><, ><exec_context>] { SQL operation };
For example, if you also declare and instantiate a connection context class,
MyConnCtxClass, and create an instance, myConnCtx, then you can use the following
statement:
#sql [myConnCtx, myExecCtx] { DELETE FROM employees WHERE salary > 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 employees WHERE salary > 30000 };
Note:
8-27
Chapter 8
Execution Contexts
See Also:
"Multithreading in SQLJ"
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.
8-28
Chapter 8
Execution Contexts
See Also:
"Execution Context Update Counts"
8-29
Chapter 8
Execution Contexts
See Also:
"Canceling a Batch"
8-30
Chapter 8
Execution Contexts
See Also:
Oracle Database JDBC Developer’s Guide
8-31
Chapter 8
Execution Contexts
Note:
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.
8-32
Chapter 8
Multithreading in SQLJ
ExecutionContext execCtx =
DefaultContext.getDefaultContext().getExecutionContext();
System.out.println
("removed " + execCtx.getUpdateCount() + " employees");
Note:
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.
8-33
Chapter 8
Multithreading in SQLJ
• 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
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"
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.
Note:
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.
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;
8-34
Chapter 8
Multithreading in SQLJ
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();
8-35
Chapter 8
Iterator Class Implementation and Advanced Functionality
try {
sleep((long)Math.abs(randomizer.nextInt()/10000000));
} catch (InterruptedException e) {}
}
}
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.
8-36
Chapter 8
Iterator Class Implementation and Advanced Functionality
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:
\
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:
Oracle Database JDBC Developer’s Guide
Note:
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.
8-37
Chapter 8
Iterator Class Implementation and Advanced Functionality
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.
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
8-38
Chapter 8
Iterator Class Implementation and Advanced Functionality
iterator will also close the result set, but closing the result set will not close the result
set iterator.
Note:
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.
See Also:
Oracle Database JDBC Developer's Guide
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);
The code that the SQLJ translator generates for the MyScrIter class will automatically
support all the methods of the Scrollable interface.
8-39
Chapter 8
Iterator Class Implementation and Advanced Functionality
Note:
The implements clause must precede the with clause.
The SQLJ standard also allows a setting of ASENSITIVE, which means accepting
the default sensitivity of the Database. But, in Oracle, if you set sensitivity to
ASENSITIVE, then it results in the default setting INSENSITIVE being used.
See Also:
Oracle Database JDBC Developer's Guide for information about scrollable
result sets
8-40
Chapter 8
Iterator Class Implementation and Advanced Functionality
• boolean isAfterLast(): Indicates whether the iterator object is after the last row
in the result set.
Note:
Additional methods for navigation, also defined in the Scrollable interface,
are available as well.
See Also:
"Using Named Iterators"
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.
8-41
Chapter 8
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.
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 12c Release 1
(12.1) SQLJ translator will also accept FETCH PREVIOUS.
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 };
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.
8-42
Chapter 8
Iterator Class Implementation and Advanced Functionality
Note:
Alternatively, you can navigate through a scrollable positional iterator through
a combination of the navigation methods and the FETCH CURRENT syntax.
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 };
8-43
Chapter 8
Iterator Class Implementation and Advanced Functionality
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...
}
You can use a SQLJ result set iterator in writing equivalent code, as follows:
sqlj.runtime.ResultSetIterator rsi;
#sql rsi = { SELECT first_name, employee_id FROM employees };
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 first_name, employee_id FROM employees };
srsi.afterLast();
while (srsi.previous()) {
#sql { FETCH CURRENT FROM :srsi INTO :x, :y };
}
srsi.close();
8-44
Chapter 8
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.
See Also:
"Basic Transaction Control"
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 };
8-45
Chapter 8
Advanced Transaction Control
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.
8-46
Chapter 8
SQLJ and JDBC Interoperability
See Also:
Oracle Database Development Guide
See Also:
Oracle Database JDBC Developer's Guide
8-47
Chapter 8
SQLJ and JDBC Interoperability
Note:
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.
...
DefaultContext ctx = new DefaultContext
("jdbc:oracle:thin:@localhost:5221/myservice", "HR", "hr", true);
...
(SQLJ operations through SQLJ ctx connection context instance)
...
Connection conn = ctx.getConnection();
...
(JDBC operations through JDBC conn connection instance)
...
8-48
Chapter 8
SQLJ and JDBC Interoperability
method. This method implicitly creates the instance and makes it the default
connection.
See Also:
"Connection Considerations" and "More About the Oracle Class"
Following is an example:
import java.sql.*;
...
Connection conn = Oracle.connect
("jdbc:oracle:thin:@localhost:5221/myservice",
"HR", "hr").getConnection();
...
(JDBC operations through JDBC conn connection instance)
...
See Also:
Oracle Database JDBC Developer's Guide and "Support for Dynamic SQL"
import java.sql.*;
8-49
Chapter 8
SQLJ and JDBC Interoperability
8-50
Chapter 8
SQLJ and JDBC Interoperability
Note:
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.
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);
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.
Note:
8-51
Chapter 8
SQLJ and JDBC Interoperability
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.
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
8-52
Chapter 8
SQLJ and JDBC Interoperability
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.
Note:
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.
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.*;
...
MyIterator iter;
...
#sql iter = { SELECT * FROM employees };
ResultSet rs = iter.getResultSet();
...
(process result set)
...
iter.close();
...
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.
8-53
Chapter 8
Support for Dynamic SQL
• 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.
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.
Note:
Using JDBC code is still an option for dynamic SQL in Oracle Database 12c
Release 1 (12.1) 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.
8-54
Chapter 8
Support for Dynamic SQL
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.
8-55
Chapter 8
Support for Dynamic SQL
Note:
There can be no mode specifiers, IN, OUT, or INOUT, within a Java bind
expression or between : and { of the meta bind expression.
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.
8-56
Chapter 8
Support for Dynamic SQL
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) };
...
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='HR'} };
...
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<5; i++)
{
#sql { UPDATE :{"emp"+i :: emp}
SET :{col :: sal} = :{col :: sal} * :raise :{whereQuery ::} };
}
...
8-57
Chapter 8
Support for Dynamic SQL
SQLJ can perform online semantics-checking against a schema that has an emp table.
There is no WHERE clause during translation, because the SQL replacement code is
empty.
During run time, the SQL operation is executed five times, becoming:
UPDATE emp0 SET comm = comm * 1.12 WHERE comm IS NOT null;
UPDATE emp1 SET comm = comm * 1.12 WHERE comm IS NOT null;
UPDATE emp2 SET comm = comm * 1.12 WHERE comm IS NOT null;
UPDATE emp3 SET comm = comm * 1.12 WHERE comm IS NOT null;
UPDATE emp4 SET comm = comm * 1.12 WHERE comm IS NOT null;
Example 4
...
double raise = 1.12;
String col = "comm";
String whereQuery = "WHERE "+col+" IS NOT null";
for (int i=0; i<10; i++)
{
#sql { UPDATE :{"emp"+i}
SET :{col :: sal} = :{col :: sal} * :raise :{whereQuery ::} };
}
...
ResultSetIterator rsi;
String andClause = (dueThisMonth) ?
" AND to_char(start_date + duration, 'fmMonth' ) "
+ " = to_char(sysdate, 'fmMonth') "
: "";
#sql rsi = { SELECT name, start_date + duration FROM projects
WHERE start_date + duration >= sysdate :{andClause :: } };
while (rsi.next())
{
String name = null;
java.sql.Date deadline = null;
#sql { FETCH CURRENT FROM :rsi INTO :name, :deadline };
System.out.println("Project: " + name + "Deadline: " + deadline);
}
rsi.close();
}
8-58
Chapter 8
Using Stored Outlines
Note:
Starting from Oracle Database 12c Release 2 (12.2), this feature is
deprecated, and replaced with SQL Plan Management (SPM). Oracle
recommends that you take advantage of the new feature, which is more
powerful and offers better performance. For more information about SPM,
refer to "Using Plan Baselines".
If you run the risk of any performance changes in the application due to change
in the environment, then you may use the outline feature of Oracle. An outline is
implemented as a set of optimizer hints that are associated with the SQL statement.
If the use of the outline is enabled for the statement, Oracle automatically considers
the stored hints and tries to generate an execution plan in accordance with those hints.
You can group outlines into categories, that is, whether they are default or as specified
by the client, and control the category of outlines Oracle uses to simplify outline
administration and deployment. The hints in the outlines are used during the execution
of respective statements if you have set USE_STORED_OUTLINES to the category name
or to TRUE.
See Also:
Oracle Database SQL Language Referencefor more information about
outlines.
When you translate the file with the new outline option set to true or the category
name, then:
1. A separate SQL file is created containing the CREATE OUTLINE statements for all
the SQL statements present in the input SQLJ file.
2. A log file containing the SQL statements, outline name, outline SQL statement,
outline category, and status information is generated.
3. If you specify the -runoutline option, then the SQL file generated is run at the
end of successful translation of the input file.
SQL statements that can be used to create outlines are:
• SELECT
• DELETE
• UPDATE
• INSERT ... SELECT
• CREATE TABLE ... AS SELECT
You have the following restrictions on creating outlines:
8-59
Chapter 8
Using Stored Outlines
Note:
The outline options are valid only if online checking is done.
Consider the SQLJ program abc.sqlj contains the following code snippet:
{
#sql iter = {SELECT * FROM employees WHERE employee_id=:var;}
#sql iter1 = {SELECT * FROM departments};
}
The generated SQL file abc_sqlj.sql for the above SQLJ code snippet looks as
follows:
CREATE OR REPLACE OUTLINE abccat_abc_sqlj_0001 FOR CATEGORY abccat ON SELECT *
FROM employees WHERE employee_id=:B1
/* abccat_abc_sqlj_0001 */;
Note:
The filename is not included in the outline name or comment when a prefix
is given. In this section, you will see examples with and without using prefix.
For more information on prefix, refer to "sqlj.outlineprefix".
The option -outline generates two files at the end of successful translation: a SQL file
and a LOG file. The generated SQL file name has the following format:
<filename>_<filetype>.sql
For example, the generated SQL file for filename abc.sqlj is abc_sqlj.sql.
The format of the unique identifier used as outline name and comment is:
<categoryname >_<filename>_<filetype>_<sequence no.>
where, the sequence number is a four-digit sequence number ranging from 0001 to
9999. If the SQLJ program contains more than 9999 SQL statements, then you get the
8-60
Chapter 8
Using Stored Outlines
"Max sequence number exceeded for outlines" error. For example, the format of the
unique identifier generated for abc.sqlj is abccat_abc_sqlj_0001, where, abccat is
the name of the category.
Note:
The same comment is added to the SQLs in the generated java or class file
that is used at runtime.
If you set outline to true, then the default category will be used to store the outlines:
%sqlj -user=HR -url=jdbc:oracle:oci8:@ -outline=true abc.sqlj
Password: password
You can use the following command to set the outline name to a particular prefix:
%sqlj -user=HR -url=jdbc:oracle:oci8:@ -outline=abccat -outlineprefix=pref1
abc.sqlj
Password: password
Note:
If you set the -outlineprefix option, then you can pass only one SQLJ file
to the translator.
Note:
To translate multiple files with the outlineprefix option, you can do the
following:
%sqlj -outline=abccat -outlineprefix=pref1,pref2,pref3 abc.sqlj
def.sqlj fgh.sqlj
8-61
Chapter 8
Using Stored Outlines
Currently, the upper limit on the length of the outline name is 30 bytes. Hence, if
the generated outline name exceeds 30 bytes, a SQLJ error "Outline name exceeds
maximum limit. Use -outlineprefix option" is thrown. In such cases, if you want
to use the -outline option, you need to call -outlineprefix option as shown in the
preceding example. If you want database server to generate the outline names instead
of the SQLJ generated outline names, then you can set the -outlineprefix option to
none. For example:
%sqlj -user=HR -url=jdbc:oracle:oci8:@ -outline=abccat -outlineprefix=none
abc.sqlj
Password: password
If you want to translate multiple files with the -outlineprefix option, then you can use
the following command:
%sqlj -user=HR -url=jdbc:oracle:oci8:@ -outline=abccat -
outlineprefix=pref1,pref2 abc.sqlj def.sqlj
Password: password
If the SQLJ file is part of a package and you have not specified the -outlineprefix
option, then the package name is appended to the outline name and is added
to the comment. For example, if abc.sqlj is part of xyz.def.fgh package, then
generated SQL file abc_sqlj.sql, for the command %sqlj -url=jdbc:oracle:oci8:@
-user=HR/password -outline=abccat abc.sqlj looks as follows:
CREATE OR REPLACE OUTLINE abccat_xyz$def$fgh$abc_sqlj_0001 FOR CATEGORY abccat
ON SELECT * FROM employees WHERE employee_id=:B1
/* abccat_xyz$def$fgh$abc_sqlj_0001 */;
If you want the generated SQL file to be executed by the translator at the end of
successful translation, then you can set the runoutline option to true. By default it is
false. For example:
%sqlj -user=HR -url=jdbc:oracle:oci8:@ -outline=default -runoutline=true abc.sqlj
Password: password
Now, if you want to retrieve the outline name for exporting or for modifying the plan
of the SQL code, then you can retrieve the same from the OL$ table, either manually
or by using a tool. You can use the comment in the SQL query to search for the
appropriate SQL statement to identify the outline name because the comment uniquely
identifies the SQL statement.
Table 8-1 shows all the options and values you can pass to the translator for
generating outlines.
8-62
Chapter 8
Using Stored Outlines
Table 8-1 Table showing the options and values for generating outlines
See Also:
Oracle Database Reference for more information about outlines.
The generated log file for the preceding code snippet is as follows:
CATERGORY abccat
Source SQL_1
SELECT * FROM employees WHERE employee_id=:B1
OUTLINE NAME
abccat_abc_sqlj_0001
OUTLINE SQL_1
CREATE OR REPLACE OUTLINE abccat_abc_sqlj_0001 FOR CATEGORY abccat ON SELECT *
FROM employees WHERE employee_id = :B1
/* abccat_abc_sqlj_0001 */
STATUS success
Source SQL_2
SELECT * FROM departments
OUTLINE NAME
abccat_abc_sqlj_0002
OUTLINE SQL_2
CREATE OR REPLACE OUTLINE abccat_abc_sqlj_2 FOR abccat ON SELECT * FROM
departments
/* abccat_abc_sqlj_2 */
STATUS fail
8-63
Chapter 8
Using Stored Outlines
Configuration Files
You can set the different command-line options in the configuration file as follows:
sqlj.outline
• Parameter Name: outline
• Parameter Type: String
• Allowable Values: {true|category_name}
• Default Value: true
• Description: Indicates that outline SQL file needs to be generated for the SQL
statements and it should be in:
– DEFAULT category if the value is default, that is, true
– The category name if category_name is mentioned
Outline SQL file is not generated if this option is not used.
• Dependency on other parameters: Online check should be full when this option is
turned on
sqlj.runoutline
• Parameter Name: runoutline
• Parameter Type: boolean
• Allowable Values: {true|false}
• Default Value: false
• Description: If runoutline=true then the generated SQL file should be executed
by the translator at the end of successful translation.
• Dependency on other parameters: Online check should be full when this option is
turned on, and the outline option should be set.
sqlj.outlineprefix
• Parameter Name: outlineprefix
• Parameter Type: String
• Allowable Values: {prefix name}, none
• Description: If this option is set, the outline name in the generated SQL is set
to <prefix>_<seqno>. When this option is set to any value apart from none in
the properties file, only one SQLJ file may be passed to the translator. If the
option is set to none, outline name is generated by the system when the create
outline statement is executed in the server. Also, you may pass multiple files to
the translator when –outlineprefix is set to none.
• Dependency on other parameters: Online check should be full when this option is
turned on, and the outline option should be set.
8-64
Chapter 8
Using Plan Baselines
See Also:
Oracle Database SQL Tuning Guide for more information about plan
baselines
Parameters
When specifying plan baseline options, SQLJ generates SQL files with calls to the
dbms_spm_internal.create_sql_plan_baseline procedure. This procedure has the
following parameters:
Parameter Description
SQL_TEXT Specifies the SQL text for which the plan baseline needs to be
created.
PARSING_SCHEMA Specifies the schema that is used for semantic checking of the
SQL text passed.
PLAN_NAME Specifies the name of the plan baseline. This parameter is
optional. If this parameter is not specified, then the default plan
name is default.
ENABLED Specifies whether the plan is to be enabled or not. Default value is
yes.
FIXED Specifies whether the plan will be a fixed plan or not. Default value
is no.
8-65
Chapter 8
Using Plan Baselines
Note:
• To generate and execute the plan baseline SQL statements, you must
have the Execute privilege on the DBMS_SPM_INTERNAL package and the
Administer SQL Management Object privilege.
• The plan baseline options are valid only if online semantic checking
is done. If you specify these options with offline semantic checking,
then the options are ignored and a warning is thrown informing that the
options should be used with online semantic checking only.
Note:
The generated files specify the appropriate user to run the files. For example,
the following statements in a generated file specify that HR can run the file:
var ORA_SPM_PARSE_SCHEMA varchar2(30);
exec :ORA_SPM_PARSE_SCHEMA:='HR';
8.9.2.1 plan_baseline
Use the plan_baseline option to specify whether baseline plans should be generated
for all the SQL statements in the SQL file or not. If you set this option to true, then
default is used as the baseline name. The baseline name is the equivalent to the
category name when you use outlines. The value you provide for this option is used as
the module name when running the SQL file.
The name of the SQL file is translated with a sequence number and the combination is
used to uniquely identify each SQL statement in the SQL file. This combination is also
used as the name of the plan. The sequence number can vary from 0 to 9999. The
format of the plan name is as follows:
<filename>_<filetype>_<sequence_no>
Syntax
In command-line, the plan_baseline option is specified as the following:
-plan_baseline= <true/false/module_name>
8-66
Chapter 8
Using Plan Baselines
Default Value
The default value for the plan_baseline option is false, in which case the plan
baselines are not generated. If you specify the value true for this option, the module
name is default.
Example
sqlj test.sqlj –plan_baseline=true -user=HR/hr
If the test.sqlj is a part of a package named mypackage and contains only the
following two SQL statements:
Select first_name from employees;
Select employee_id from employees;
BEGIN
BEGIN
d := SYS.DBMS_SPM.DROP_SQL_PLAN_BASELINE( PLAN_NAME =>
'mypackage_test_sqlj_0000') ;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
c:=SYS.DBMS_SPM_INTERNAL.CREATE_SQL_PLAN_BASELINE(
'Select first_name from employees /*mypackage_test_sqlj_0000*/',
:ORA_SPM_PARSE_SCHEMA,
'mypackage_test_sqlj_0000',
'no',
'no');
END ;
/
BEGIN
BEGIN
d := SYS.DBMS_SPM.DROP_SQL_PLAN_BASELINE( PLAN_NAME =>
'mypackage_test_sqlj_0001') ;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
c:=SYS.DBMS_SPM_INTERNAL.CREATE_SQL_PLAN_BASELINE(
'Select employee_id from employees /*mypackage_test_sqlj_0001*/',
:ORA_SPM_PARSE_SCHEMA,
'mypackage_test_sqlj_0001',
'no',
'no');
END ;
/
8-67
Chapter 8
Using Plan Baselines
BEGIN
BEGIN
d := SYS.DBMS_SPM.DROP_SQL_PLAN_BASELINE( PLAN_NAME =>
'mypackage_test_sqlj_0000') ;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
c:=SYS.DBMS_SPM_INTERNAL.CREATE_SQL_PLAN_BASELINE(
'Select first_name from employees /*mypackage_test_sqlj_0000*/',
:ORA_SPM_PARSE_SCHEMA,
'mypackage_test_sqlj_0000',
'no',
'no');
END ;
/
BEGIN
BEGIN
d := SYS.DBMS_SPM.DROP_SQL_PLAN_BASELINE( PLAN_NAME =>
'mypackage_test_sqlj_0001') ;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
c:=SYS.DBMS_SPM_INTERNAL.CREATE_SQL_PLAN_BASELINE(
'Select employee_id from employees /*mypackage_test_sqlj_0001*/',
:ORA_SPM_PARSE_SCHEMA,
'mypackage_test_sqlj_0001',
'no',
'no');
END ;
/
8.9.2.2 plan_prefix
Use the plan_prefix option to specify a name for the plan. This corresponds to the
PLAN_NAME argument of the create_sql_plan_baseline procedure. If you do not use
this option, then a plan name is generated automatically.
Syntax
In command-line, the plan_prefix option is specified as the following:
-plan_prefix=<name>
8-68
Chapter 8
Using Plan Baselines
Default Value
The value for the plan_prefix option is none. If you specify any other value for this
option, then the format of the plan name becomes the following:
<name>_<sequence_no>
Example
sqlj test.sqlj –plan_baseline=mybaseline true -user=HR/hr –
plan_prefix=myprefix
8.9.2.3 plan_run
Use the plan_run option to specify if you want SQLJ to execute the generated SQL file
at the end of translation.
8-69
Chapter 8
Using Plan Baselines
Note:
You must have the following privileges to execute the generated SQL file:
• Execute privilege on the DBMS_SPM_INTERNAL package
• Administer SQL Management Object privilege
Syntax
In command-line, the plan_run option is specified as the following:
-plan_run=<yes|no>
Default Value
This default value for the plan_run option is yes.
8.9.2.4 plan_fixed
Use the plan_fixed option to specify whether the generated baseline should be fixed
or not.
Syntax
In command-line, the plan_fixed option is specified as the following:
-plan_fixed = <yes|no>
Default Value
This default value for this option is yes.
8.9.2.5 plan_enabled
Use the plan_enabled option to specify whether the generated baseline should be
enabled or not.
Syntax
In command-line, the plan_enabled option is specified as the following:
-plan_enabled = <yes|no>
8-70
Chapter 8
Using Plan Baselines
Default Value
This default value for this option is yes.
For SQLJ, the file type is always .sqlj. So, the name of the SQL file is always in the
following format:
<filename>_sqlj_bln.sql
8-71
Chapter 8
Using Plan Baselines
/
BEGIN
BEGIN
d := SYS.DBMS_SPM.DROP_SQL_PLAN_BASELINE( PLAN_NAME => 'myprefix_0001') ;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
c:=SYS.DBMS_SPM_INTERNAL.CREATE_SQL_PLAN_BASELINE(
'Select employee_id from employees /*myprefix_0001*/',
:ORA_SPM_PARSE_SCHEMA,
'myprefix_0001',
'no',
'no');
END ;
Note:
• The sequence number 0000 and 0001 are used to uniquely identify the
plan name for each SQL statement.
• If you specify a value other than none with the plan_prefix option, then
the prefix value is used instead of the value that is specified with the
–plan_baseline option.
For SQLJ, the file type is always .sqlj. So, the name of the SQL file is always in the
following format:
<filename>_sqlj_bln.log
8-72
Chapter 8
Using Plan Baselines
/******************************************/
/******************************************/
MODULE default
SOURCE SQL_1
select manager_id from employees
PLAN NAME
mypackage_test_sqlj_0001
STATUS Success
/******************************************/
/******************************************/
/******************************************/
MODULE default
SOURCE SQL_1
select manager_id from employees
PLAN NAME
myprefix_0001
STATUS Success
/******************************************/
Then the generated Java file has an identifier appended to the SQL statement as
follows:
8-73
Chapter 8
Using Plan Baselines
try {
String theSqlTS = "select first_name from employees /
*mybaseline_test_sqlj_0001*/";
__sJT_st = __sJT_ec.prepareOracleStatement(__sJT_cc,"0Select",theSqlTS);
// execute query
iter = new Iter(new
sqlj.runtime.ref.OraRTResultSet(__sJT_ec.oracleExecuteQuery(),__sJT_st,"0Select",
null));
} finally { __sJT_ec.oracleCloseQuery(); }
8-74
9
Translator Command Line and Options
Once you have written your source code, you must translate it using the SQLJ
translator. This chapter covers the SQLJ translator command line options and
properties files. The following topics are covered:
• Translator Command Line and Properties Files
• Basic Translator Options
• Advanced Translator Options
• Translator Support and Options for Alternative Environments
The optionlist is a list of SQLJ option settings separated by spaces. There are also
prefixes to mark options to pass to the Java interpreter, compiler, and customizer.
The filelist is the list of files, delimited by spaces, to be processed by the SQLJ
translator. The files can be .sqlj, .java, .ser, or .jar files. The * wildcard entry can
be used in file names. For example, Foo*.sqlj would find Foo1.sqlj, Foo2.sqlj, and
Foobar.sqlj.
Note:
• All options need not precede the file list. Options may appear anywhere
in the command line and are processed in order.
• All command-line options apply to all files being translated. It is not
possible to have file-specific option settings.
Do not include .class files in the file list, but ensure that your classpath is set so that
the SQLJ translator can find any classes it must have for type resolution of variables
in your SQLJ source files. If the -checksource flag is enabled, which is the default
setting, then the SQLJ translator can also find classes it needs in uncompiled .java
files in the classpath.
9-1
Chapter 9
Translator Command Line and Properties Files
Note:
If you run the script by entering only sqlj, you will receive a synopsis of the
most frequently used SQLJ options. In fact, this is true whenever you run the
script without specifying any files to process. This is equivalent to using the
-help flag setting.
9-2
Chapter 9
Translator Command Line and Properties Files
9-3
Chapter 9
Translator Command Line and Properties Files
9-4
Chapter 9
Translator Command Line and Properties Files
9-5
Chapter 9
Translator Command Line and Properties Files
9-6
Chapter 9
Translator Command Line and Properties Files
See Also:
"Command-Line Syntax and Operations"
• Omit the -password argument. In this case, you will be prompted on the command
line to enter the password. Then the password argument will not be visible to the
operating system.
• Place the password setting into a properties file, and instruct the SQLJ translator
to use this properties file. Thus it is possible to script SQLJ translation without
exposing the password to the operating system.
• Use SQLJ under JDeveloper. This does not expose the password to the operating
system.
9-7
Chapter 9
Translator Command Line and Properties Files
• -e (for -encoding)
• -h (for -help)
• -p (for -password)
• -u (for -user)
• -v (for verbose message output; equivalent to -status)
To maintain full consistency with loadjava syntax, you can use a space instead of
equal sign (=) in setting these options, as in the following example:
-u HR -v -e SJIS
Note:
This alternative option syntax is recognized only on the command line or in
the SQLJ_OPTIONS environment variable, not in properties files.
See Also:
Oracle Database Java Developer’s Guide
9-8
Chapter 9
Translator Command Line and Properties Files
Note:
Refer to javac documentation for additional information about javac option settings
and functionality.
9-9
Chapter 9
Translator Command Line and Properties Files
• If you want to set different classpath values for the Java compiler and for the JVM
that runs SQLJ, then you must use separate settings, one with a -C prefix and one
with a -J prefix. Otherwise, no prefix is required.
• Do not use the -C prefix to specify the -d or -encoding compiler options. Note
that this also means that SQLJ and the compiler use the same settings for -d and
-encoding.
• You can optionally use the -C prefix for -depend, -deprecation, -g, -nowarn, -O,
and -verbose.
• All javac options, aside from those that are also SQLJ options (-classpath, -d,
and -encoding) require the compile. prefix if you set them in a properties file.
• For consistency, it is advisable to use an equal sign (=) for options that take
values, but a space also works when using a compiler prefix (-C on the command
line or compile. in a properties file).
Example
The following example, which is a single wraparound command line, uses the -C-
bootclasspath, -C-extdirs, and -C-target options.
% sqlj -vm=/usr/local/packages/jdk6/bin/java
-compiler-executable=/usr/local/packages/jdk6/bin/javac
-C-bootclasspath=/usr/local/packages/jdk6/jre/lib/rt.jar
-C-extdirs="" -C-target=1.1.8 Demo.sqlj
When the sqlj script invokes a JVM, it passes all of its command-line arguments to
the JVM, which later passes them elsewhere, such as to the Java compiler or profile
customizer, as appropriate.
Use an equal sign (=) to specify option and flag settings, although for simplicity you
do not have to specify =true to turn on a flag. Typing the flag name alone will suffice.
However, you must specify =false to turn a flag off. A flag will not toggle from its
previous value. For example:
-linemap=true or just -linemap to enable line-mapping
9-10
Chapter 9
Translator Command Line and Properties Files
Note:
If the same option appears more than once on the command line or in the
properties file, then the last value is used.
If you want to set different classpath values for the Java compiler and for the JVM
that runs SQLJ, you must use separate settings, one with a -C prefix and one with
a -J prefix.
• Options designated by the -C prefix are Java compiler options and are passed to
the compiler as the JVM invokes it. Compiler options taking values require special
support, which has been implemented for javac options. You can use an equal
sign for these, as follows (though a space also works):
-C-bootclasspath=/usr/local/packages/jdk6/jre/lib/rt.jar
• Options designated by the -P prefix are SQLJ profile customizer options and are
passed to the customizer as the JVM invokes it (relevant only for ISO standard
code generation, -codegen=iso). As with translator options, use an equal sign (=)
in setting the option, such as:
-P-user=HR
See Also:
Customization and Specialized Customizers
9-11
Chapter 9
Translator Command Line and Properties Files
• The .ser profiles and .jar files are processed only by the profile customizer
(relevant only for -codegen=iso).
Note that you can specify .sqlj files together with .java files on the command
line, or you can specify .ser files together with .jar files, but you cannot mix the
two categories. If you have .sqlj files and .java files with interdependencies, each
requiring access to code in the others, then enter them all on the command line for a
single execution of SQLJ. You cannot specify them for separate executions of SQLJ,
because then SQLJ would be unable to resolve all the types.
Note:
As an alternative to entering .java file names on the command line, you can
enable the -checksource option and then ensure that the .java files are in
the classpath.
These both refer to the same file, so the translator discards /myhome/mypackage/
Foo.sqlj from the command line.
% sqlj Foo.sqlj Foo.java
The translator discards Foo.java from the command line. Otherwise, this command
line would result in the translator writing and reading from Foo.java in the same
execution.
% sqlj Foo.*
Again, the translator discards Foo.java from the command line. Otherwise, the
translator would find both Foo.sqlj and Foo.java, which again would cause it to write
and read from Foo.java in the same execution.
% sqlj -dir=outdir -d=outclasses Foo.sqlj Foo.java
This is fine, because the generated Foo.java will be in the outdir subdirectory,
while the Foo.java being read is in the /myhome/mypackage directory. Presuming that
Foo.java and Foo.sqlj define classes in different packages, the .class files created
by Java compilation will be placed in different subdirectories under the outclasses
directory hierarchy.
9-12
Chapter 9
Translator Command Line and Properties Files
This processing of the command line means that you can, for example, type the
following command and have it execute without difficulty (with file references being
automatically discarded as necessary):
% sqlj *.sqlj *.java
The sqlj script invokes a JVM, passes it the class name of the SQLJ translator, then
passes it the command-line arguments. The JVM passes the SQLJ options to the
translator and compiler. If there are any options for the JVM, as designated by -J,
then the script passes them to the JVM ahead of the translator class file name (just
as you would type Java options prior to typing the class file name if you were invoking
Java manually). There is no customization in this example, because it uses the default
Oracle-specific code generation.
After these steps are completed, the results are equivalent to the user having
typed the following (presuming SushiBar.sqlj, DiveBar.sqlj, FooBar.java, and
FooBaz.java were all in the current directory):
% java -Duser.language=ja -prof sqlj.tools.Sqlj -warn=none -encoding=SJIS
SushiBar.sqlj DiveBar.sqlj FooBar.java FooBaz.java
You cannot use properties files to set the following SQLJ options, flags, and prefixes:
• -classpath
• -help, -help-long, -help-alias, -C-help, -P-help
• -J
• -n
9-13
Chapter 9
Translator Command Line and Properties Files
• -passes
• -props
• -version, -version-long
• -vm
It is not possible to use properties files to specify options to the JVM, for example,
because properties files are read after the JVM is invoked.
Also note that in properties files you cannot use option abbreviations recognized on
the command line for compatibility with loadjava (-e, -h, -p, -u, -v).
See Also:
Customization and Specialized Customizers
9-14
Chapter 9
Translator Command Line and Properties Files
Note:
For consistency, it is best to always use the equal sign (=) in a properties
file for options that take values, even though there are some circumstances
where a space also works.
These entries are equivalent to having the following on the SQLJ command line:
% sqlj -user=HR -driver=oracle.jdbc.OracleDriver -C-verbose
# Warning settings
sqlj.warn=all
# Cache
sqlj.cache=on
9-15
Chapter 9
Translator Command Line and Properties Files
See Also:
"Order of Precedence of Option Settings"
You can use the SQLJ_OPTIONS variable to set any SQLJ option, but it is intended
especially for option settings to be passed to the JVM. And it is particularly useful
for command-line-only options, such as -classpath, that you use repeatedly with the
same setting.
Following is an example of a SQLJ_OPTIONS setting:
-vm=jview -J-verbose
When you use SQLJ_OPTIONS, SQLJ effectively inserts the SQLJ_OPTIONS settings, in
order, at the beginning of the SQLJ command line, prior to any other command-line
option settings.
Note:
Generally, syntax in SQLJ_OPTIONS is the same as on the command line, but
this may depend on your operating system. There can be operating system
specific restrictions. For example, on Microsoft Windows 95 you use the
Environment tab in the System control panel. Additionally, because Windows
95 does not support the equal sign (=) in variable settings, SQLJ supports
the use of # instead of = in setting SQLJ_OPTIONS. Refer to your operating
system documentation.
9-16
Chapter 9
Basic Translator Options
6. It looks for option settings on the command line and sets options as specified
there. As SQLJ processes the command line, it looks in any file specified by the
-props option and sets options as specified there.
Note:
• At each step, SQLJ overrides any previous settings for any given option.
• In the sqlj.properties files, SQLJ reads option settings from top to
bottom, with later entries taking precedence over earlier entries.
• If there is a properties file specified by the -props option on the
command line, SQLJ effectively inserts the option settings of the file into
the position on the command line where the -props option was specified.
• SQLJ reads options on the command line, with options from a -props
file inserted, in order from left to right. Any later (right-hand) setting takes
precedence over earlier (left-hand) settings.
Example
Presume SQLJ is run as follows:
% sqlj -user=HR -props=myprops.properties -dir=/home/java
And presume the file myprops.properties is in the current directory and contains the
following entries:
sqlj.user=tony
sqlj.dir=/home/myjava
These settings are processed as if they were inserted into the command line where
the -props option was specified. Therefore, the tony entry takes precedence over
the HR entry for the user option, but the /home/java entry takes precedence over the /
home/myjava entry for the dir option.
9-17
Chapter 9
Basic Translator Options
See Also:
• -props
• -classpath
• -help, -help-long, -help-alias, -P-help, -C-help
• -version, -version-long
• -n
These options cannot be specified in properties files. The command-line-only flags
(-help, -version, and -n) do not support =true syntax. Enable them by typing only the
flag name, as follows:
sqlj -version-long
Note:
Additionally, there are advanced options, flags, and prefixes that can be set
only on the command line or in SQLJ_OPTIONS: -J, -passes, and -vm.
For example:
-props=myprops.properties
9-18
Chapter 9
Basic Translator Options
-classpath= .:$ORACLE_HOME/jdbc/lib/ojdbc6.jar:$ORACLE_HOME/sqlj/lib/
translator.jar:$ORACLE_HOME/sqlj/lib/runtime12.jar
The -classpath option sets the Java classpath for both the JVM and the Java
compiler. If you do not want to use the same classpath for both, then set them
separately using the SQLJ -J and -C prefixes.
See Also:
"Prefixes that Pass Option Settings to Other Executables"
Note:
As with other options described in this chapter, if you use = in setting the
-classpath option, then it is stripped out when the option string is passed
to the JVM and compiler, because JVMs and compilers do not support the =
syntax in their option settings.
For example:
sqlj -classpath=$ORACLE_HOME/jdbc/lib/ojdbc6.jar:$ORACLE_HOME/sqlj/lib/
translator.jar:$ORACLE_HOME/sqlj/lib/runtime12.jar
% sqlj -help-long
% sqlj -help-alias
No input-file translation is performed when you use the -help flag in any of these
forms, even if you include file names and other options on the command line as well.
SQLJ assumes that you either want to run the translator or you want help, but not
both.
9-19
Chapter 9
Basic Translator Options
You can also receive information about the profile customizer or Java compiler,
requesting help through the -P and -C prefixes, as in the following examples. As with
the -help flag, no translation is performed if you request customizer or compiler help.
% sqlj -P-help
% sqlj -C-help
As with other command-line-only flags, -help (as well as -P-help and -C-help) does
not support =true syntax. Enable it by typing only the desired flag setting.
Note:
The most basic level of help is achieved by specifying the -help setting. This provides
the following:
• A synopsis of the most frequently used SQLJ options
• A listing of the additional -help flag settings available
The -help-long setting provides a complete list of SQLJ option information, including
the following for each option:
• Option name
• Option type (the Java type that the option takes as input, such as int or String)
• Description
• Current value
• How the current value was set (from the command line, from a properties file, or
by default)
Note:
It is often useful to include other option settings on the command line with
a -help-long option, especially with complex options, such as -warn, or
combinations of options, so that you can see what option settings resulted
from your actions.
9-20
Chapter 9
Basic Translator Options
For example:
sqlj -help
sqlj -help -help-alias
sqlj -help-long
sqlj -warn=none,null -help-long
sqlj -help-alias
% sqlj -version-long
No input-file translation is performed when you use the -version option, even if
you include file names and other options on the command line. SQLJ assumes that
you either want to run the translator or you want version information, but not both.
Properties files and anything else you type on the command line are ignored. As with
other command-line-only flags, -version does not support the =true syntax. Enable it
by typing only the flag name.
The -version setting displays the SQLJ release number, as follows:
sqlj -version
Oracle SQLJ Release 12.1.0.1.0 Production
Copyright © 1997, 2012, Oracle Corporation. All Rights Reserved.
The -version-long setting displays information about the SQLJ and SQLJ run-time
library release, the JDBC driver release number if one can be found, and the Java
environment. For example, if an Oracle JDBC driver is used, this option would display
something as follows:
sqlj -version-long
Oracle SQLJ Release 12.1.0.1.0 Production
Copyright © 1997, 2012, Oracle Corporation. All Rights Reserved.
JDBC version: Oracle JDBC driver version 12.1 (12.1.0.1.0)
Java version: 1.6 (1.6.0_04)
This flag offers a good way to check your SQLJ installation and the JDBC and JDK
versions you are using. The command-line syntax is as follows:
sqlj version_flag_settings
For example:
9-21
Chapter 9
Basic Translator Options
sqlj -version
sqlj -version -version-long
sqlj -version-long
Note:
9-22
Chapter 9
Basic Translator Options
-n
For example:
-n
-encoding SJIS
When this option is specified, it is also passed to the Java compiler, unless the
-compiler-encoding-flag is off, which uses it to specify encoding for .java files
processed by the compiler.
Note the following:
• As with the -classpath and -d options, if you do use an = in setting the -encoding
option, then it is stripped out when the option string is passed to the JVM and
compiler. This is because JVMs and compilers do not support the = syntax in their
option settings.
• For compatibility with the loadjava utility, -e is recognized as equivalent to -
encoding when specified on the command line.
• The -encoding option does not apply to Java properties files, such as
sqlj.properties and connect.properties. Properties files always use the
encoding 8859_1. This is a feature of Java in general, not SQLJ in particular.
However, you can use Unicode escape sequences in a properties file. You can use
the native2ascii utility to create escape sequences for a natively encoded file.
See Also:
Translator and Run-Time Functionality
9-23
Chapter 9
Basic Translator Options
For example:
-encoding=SJIS
The syntax for a properties file entry for this option is as follows:
sqlj.encoding=Java_character_encoding
For example
sqlj.encoding=SJIS
Whenever a directory is specified, the output files are generated under this directory
according to the package name, if applicable. For example, if you have source files
in the a.b.c package and specify directory, /mydir, output files will be placed in the /
mydir/a/b/c directory. If you specify a relative directory path, then this will be from
your current directory.
For compatibility with javac, you can use either a space or = in setting this option on
the command line, as in the following examples (both of which make /root the root
directory for generated profile files):
-d=/root
-d /root
However, if setting -d in a properties file, then use =, not a space. For example:
sqlj.d=/root
If your current directory is /root/home/mydir and you set the -d option to the
relative directory path, mysubdir/myothersubdir, as follows, then /root/home/mydir/
mysubdir/myothersubdir will be the root directory for the generated profile files:
-d=mysubdir/myothersubdir
You can also use standard syntax, such as a period for the current directory or two
periods to go up a level, as follows:
-d=.
-d=../paralleldir
If the -d option is empty or not specified, then a generated .class file is placed in the
same directory as the corresponding .java file, which is according to the -dir option
for a .java file generated by SQLJ, and a generated .ser file is placed in the same
directory as the corresponding .sqlj file.
9-24
Chapter 9
Basic Translator Options
Note:
For example:
-d=/topleveldir/mydir
The syntax for a properties file entry for this option is as follows:
sqlj.d=directory_path
For example:
sqlj.d=/topleveldir/mydir
Consider that your current directory is /root/home/mydir and you set the -dir option
to the relative directory path mysubdir/myothersubdir as follows:
-dir=mysubdir/myothersubdir
9-25
Chapter 9
Basic Translator Options
You can also use standard syntax, such as a period for the current directory or two
periods to go up a level, as follows:
-dir=.
-dir=../paralleldir
If the -dir option is not specified, then files are generated under the same directory as
the original .sqlj source file (not under the current directory). If you specifically want
the output directory to be the same as your .sqlj source directory (perhaps overriding
other -dir settings, such as in properties files), then you can use the -dir option as
follows:
-dir=
Note:
If you specify the -dir option but not the -d option, then generated .class
files will also be placed in the directory specified by -dir, but generated .ser
files will be placed in the directory of the .sqlj file.
For example:
-dir=/topleveldir/mydir
The syntax for a properties file entry for this option is as follows:
sqlj.dir=directory_path
For example:
sqlj.dir=/topleveldir/mydir
9-26
Chapter 9
Basic Translator Options
source code can be independent of the connection information in the SQLJ options.
In fact, the deployment environment might be unavailable during development and
testing.
Note that there is no other flag to enable or disable online semantics-checking. SQLJ
enables or disables it according to the presence or absence of the -user option.
Note:
• Some settings of the SQLJ -parse option will disable online semantics-
checking, overriding the effect of the -user option.
• For compatibility with the loadjava utility, -u is recognized as equivalent
to -user when specified on the command line.
• User names cannot contain the characters / or @.
• You are allowed to use a space instead of = in a user name setting on
the command line, as in the following examples:
-user HR/password
-user@CtxClass HR/password
-u HR/password
-u@CtxClass HR/password
• If a password contains the character @, then you cannot set the
password through the -user option. You must use separate -user and
-password settings.
• If your login name is a member of the DBA group, you may have special
privilege to connect as SYSDBA to the SYS schema. In this case, you can
specify the user name SYS or INTERNAL.
• For ISO code generation, the translator -user setting is forwarded to the
profile customizer, but can be overridden by the customizer user setting.
9-27
Chapter 9
Basic Translator Options
When you are using only the default connection or other instances of the
DefaultContext class, such a setting will apply to all your SQLJ executable
statements. This example results in online checking against the HR schema.
You can also specify the password, URL, or both along with the user name, using
syntax as in the following examples (with / preceding the password and @ preceding
the URL):
-user=HR/password
-user=HR@jdbc:oracle:oci:@
-user=HR/password@jdbc:oracle:oci:@
Otherwise, the URL can be specified through the -url option, and the password can
be specified interactively or through the -password option.
You can disable online semantics-checking by setting the -user option to an empty
string, as follows:
-user=
Again, when you are using only the default connection or other instances of the
DefaultContext class, this will apply to all your SQLJ executable statements.
There is also a special user name, URL.CONNECT, which you can use when the URL
specifies the user and password as well as the other details of the connection.
If you declare and use additional connection context classes in your application, then
you can specify -user settings for the testing of SQLJ executable statements that
use instances of those classes. Specify a user name for online checking against a
particular connection context class, for example, CtxClass, as follows:
-user@CtxClass=HR
This results in online checking against the HR schema for any of your SQLJ executable
statements that specify a connection context instance of CtxClass.
As with the default connection context class, you can also specify the password or
URL in your -user setting for a particular connection context class, as in the following
example:
-user@CtxClass=HR/password@jdbc:oracle:oci:@
The CtxClass connection context class must be declared in your source code or
previously compiled into a .class file.
Use the -user option separately for each connection context class for which you want
to enable online checking and set a user name. These settings have no influence on
each other. For example:
-user@CtxClass1=user1 -user@CtxClass2=user2 -user@CtxClass3=user3
When you are using multiple connection context classes in your application, a -user
setting that does not specify a class will apply to the DefaultContext class as well
9-28
Chapter 9
Basic Translator Options
as to all classes for which you do not otherwise specify a -user setting. Presumably,
though, you will specify a -user setting for each connection context class, given that
different connection context classes are typically intended for use with different sets of
SQL objects.
Consider a situation where you have declared connection context classes CtxClass1,
CtxClass2, and CtxClass3 and you set -user as follows:
-user@CtxClass2=HR/password -user=bill/lion
Any statement in your application that uses an instance of CtxClass2 will be checked
against the HR schema. Any statement that uses an instance of DefaultContext,
CtxClass1, or CtxClass3 will be checked against the bill schema.
In addition, once you enable online checking by setting the -user option, you can
disable online checking for a particular connection context by setting the -user option
again with an empty user name for that connection context. For example, consider the
following setting:
-user@CtxClass2=
This disables online semantics-checking for any SQLJ executable statements that
specify a connection object that is an instance of CtxClass2.
You can disable online semantics-checking for the default connection context class
and any other connection context classes for which you do not specify a user name as
follows:
-user=
For example:
-user=HR
-user=HR/password
-user=HR@jdbc:oracle:oci:@
-user=HR/password@jdbc:oracle:oci:@
-user=
-user=URL.CONNECT
-user@CtxClass=HR/password
-user@CtxClass=
The syntax for a properties file entry for this option is as follows:
sqlj.user<@conn _context_class>=username</password><@url>
For example:
sqlj.user=HR
sqlj.user=HR/password
sqlj.user=HR@jdbc:oracle:oci:@
sqlj.user=HR/password@jdbc:oracle:oci:@
sqlj.user=
sqlj.user=URL.CONNECT
sqlj.user@CtxClass=HR/password
sqlj.user@CtxClass=
9-29
Chapter 9
Basic Translator Options
This option does not have a default value. By default, there is no online-semantics
checking.
Note:
Be aware of the difference in format between specifying user, password, and
URL in the user option and specifying them in the -url option. In the -url
option, the user name and password are included in the URL, immediately
following the JDBC driver type. In the -user option they precede the URL.
For the most part, functionality of the -password option parallels that of the -user
option. That is, if your application uses only the default connection or other instances
of DefaultContext, then the following will set the password for the schema to be used
in checking all of your SQLJ statements:
-password=password
If you declare and use additional connection context classes, CtxClass1 for example,
then you will presumably use the -user option to specify additional exemplar schemas
to use in testing statements that use those connection context classes. Similarly, use
the -password option to specify passwords for those schemas, as in the following
example:
-password@CtxClass1=password
A connection context class without a password setting, either through the -password
setting or the -user setting, uses the password setting for the default connection
context class. If you set no password for the default connection context class, then
SQLJ prompts you interactively for that password. If you also set no password for a
user-defined connection context class, then SQLJ prompts you interactively for that
password as well. An exception to this discussion is where user name URL.CONNECT is
used. In this case, user name and password are determined from the string specified
in the -url setting and any setting of the -password option is ignored.
You can specifically set an empty password to override other settings of the -password
option, such as in a properties file, and be prompted interactively. You can do this
for the DefaultContext class or any particular connection context class, as in the
following examples:
-password=
-password@CtxClass1=
If you actually want to use an empty password to log in, specify EMPTY.PASSWORD as in
the following examples:
9-30
Chapter 9
Basic Translator Options
-password=EMPTY.PASSWORD
-password@CtxClass2=EMPTY.PASSWORD
However, Oracle Database 12c Release 1 (12.1) does not permit an empty password.
Note:
For example:
-password=password
-password=
-password=EMPTY.PASSWORD
-password@CtxClass=password
The syntax for a properties file entry for this option is as follows:
sqlj.password<@conn_context_class>=user_password
For example:
sqlj.password=hr
sqlj.password=
sqlj.password=EMPTY.PASSWORD
sqlj.password@CtxClass=hr
This option does not have a default value. Either the password for DefaultContext is
used or the user is prompted.
9-31
Chapter 9
Basic Translator Options
You can also specify the URL as part of the -user option setting. Do not use the -url
option for a connection context class if you have already set its URL in the -user
option, which takes precedence.
For the most part, functionality of the -url option parallels that of the -user option.
That is, if your application uses only the default connection or other instances of
DefaultContext, then the following example would set the URL to use for the
connection for checking all your SQLJ statements:
-url=jdbc:oracle:oci:@
Alternatively, to include the host name, port number, and service name:
-url=jdbc:oracle:thin:@myhost:5221/myservice
If you do not begin a URL setting with jdbc:, then the setting is assumed to be of
the form host:port/servicename and, by default, is automatically prefixed with the
following:
jdbc:oracle:thin:@
You can remove or alter this default prefix with the -default-url-prefix option.
You can specify the user and password in the -url setting, instead of in the -user and
-password settings. In such a case, set -user to URL.CONNECT, as follows:
-url=jdbc:oracle:oci:HR/hr@ -user=URL.CONNECT
If you declare and use additional connection context classes, CtxClass1 for example,
you will presumably specify additional exemplar schemas to use in testing statements
that use those connection context classes. You can use the -url option to specify
URLs for those schemas, as in the following example:
-url@CtxClass1=jdbc:oracle:oci:@
Any connection context class without a URL setting, either through the -url setting
or the -user setting, uses the URL setting for the default connection context class,
presuming a URL has been set for the default context class.
Note:
• Remember that any connection context class with a URL setting must
also have a user name setting for online checking to occur.
• You are allowed to use a space instead of = in a URL setting on the
command line, as in the following examples:
-url jdbc:oracle:oci:@
-url@CtxClass jdbc:oracle:oci:@
• For ISO code generation, the translator -url setting is forwarded to the
profile customizer, but can be overridden by the customizer url setting.
9-32
Chapter 9
Basic Translator Options
For example:
-url=jdbc:oracle:oci:@
-url=jdbc:oracle:thin:@hostname:5221/myservice
-url=jdbc:oracle:oci:HR/password@
-url=hostname:5221/myservice
-url@CtxClass=jdbc:oracle:oci:@
The syntax for a properties file entry for this option is as follows:
sqlj.url<@conn_context_class>=URL
For example:
sqlj.url=jdbc:oracle:oci:@
sqlj.url=jdbc:oracle:thin:@hostname:5221/myservice
sqlj.url=jdbc:oracle:oci:HR/hr@
sqlj.url=hostname:5221/myservice
sqlj.url@CtxClass=jdbc:oracle:oci:@
Note:
Be aware of the difference in format between specifying user, password, and
URL in the -user option and specifying them in the -url option. In the -url
option, the user name and password are included in the URL, immediately
following the JDBC driver type. In the -user option, they precede the URL.
This enables you to use a shorthand in specifying a URL setting, either in the -user
option or the -url option. It is permissible to specify only the host, port, and service
name (or SID, which is deprecated) of the database. As an example, presume you set
a URL as follows:
-url=myhost:5221/myservice
-user=HR/hr@myhost:5221/myservice
If you specify a full URL that starts with jdbc:, then the default prefix will not be used.
9-33
Chapter 9
Basic Translator Options
However, if you want your URL settings to default to the JDBC Oracle Call Interface
(OCI) driver, for example, instead of the JDBC Thin driver, then set the default prefix
as follows:
-default-url-prefix=jdbc:oracle:oci:@
If you do not want any prefix, then set the -default-url-prefix option to an empty
string, as follows:
-default-url-prefix=
For example
-default-url-prefix=jdbc:oracle:oci:@
-default-url-prefix=
The syntax for a properties file entry for this option is as follows:
sqlj.default-url-prefix=url_prefix
For example:
sqlj.default-url-prefix=jdbc:oracle:oci:@
sqlj.default-url-prefix=
For example:
-driver=oracle.jdbc.OracleDriver
-driver=oracle.jdbc.OracleDriver,sun.jdbc.odbc.JdbcOdbcDriver
The syntax for a properties file entry for this option is as follows:
sqlj.driver=driver1<,driver2,driver3,...>
For example:
sqlj.driver=oracle.jdbc.OracleDriver
sqlj.driver=oracle.jdbc.OracleDriver,sun.jdbc.odbc.JdbcOdbcDriver
9-34
Chapter 9
Basic Translator Options
If you do not set this property in the properties file, then the default value for this
property is "SQLJ". You can set this property in the following way:
sqlj.driver_name=MYDRIVER
Note:
This attribute can be set only through the properties file and does not have
an equivalent command-line option.
9-35
Chapter 9
Basic Translator Options
The verbose/noverbose flag works differently from the others. It does not enable
a particular test but enables output of general informational messages about the
semantics-checking.
Note:
Do not confuse -warn=verbose with the -status flag. The -status
flag provides real-time informational messages about all aspects of
SQLJ translation: translation, semantics-checking, compilation, and profile
customization, if applicable. The -warn=verbose flag results in additional
reporting about the translation phase only.
The global all/none flag takes priority over default settings. You can use it to enable
or disable all flags, or to serve as an initialization to ensure that all flags are off before
you turn selected flags on, or all flags are on before you turn selected flags off.
The all setting is equivalent to the following:
cast,precision,nulls,portable,strict,verbose
9-36
Chapter 9
Basic Translator Options
There is no default for all/none. There are only defaults for individual flags.
Separate settings of the -warn option in properties files and on the command line
are not cumulative. Only the last setting is processed. In the following example, the
-warn=portable setting is ignored. That flag and all other flags besides nulls/nonulls
are set according to their defaults:
-warn=portable -warn=nonulls
Note:
The cast, precision, nullability, and strictness tests are part of online
semantics-checking and require a database connection.
For example:
-warn=none,nulls,precision
The syntax for a properties file entry for this option is as follows:
sqlj.warn=comma-delimited_list_of_flags
For example:
sqlj.warn=none,nulls,precision
9-37
Chapter 9
Basic Translator Options
Note:
• Do not confuse -warn=verbose with the -status flag. The -status flag
provides real-time informational messages about all aspects of SQLJ
translation. The -warn=verbose flag results in additional reporting about
the translation phase only.
• For compatibility with the loadjava utility, -v is recognized as equivalent
to -status when specified on the command line.
For example:
-status
The syntax for a properties file entry for this option is as follows:
sqlj.status<=true|false>
For example:
sqlj.status
For example:
-explain
The syntax for a properties file entry for this option is as follows:
sqlj.explain<=true|false>
For example:
9-38
Chapter 9
Basic Translator Options
sqlj.explain
The SQLJ translator modifies the .class file to implement the -linemap option,
replacing line numbers and the file name from the generated .java file with
corresponding line numbers and the file name from the original .sqlj file. This process
is known as instrumenting the class file.
In performing this, SQLJ takes the following into account:
• The -d option setting, which determines the root directory for .class files
• The -dir option setting, which determines the root directory for generated .java
files
Note:
• If you are processing a .sqlj file and the compilation step is skipped
due to error, then no line-mapping can be performed either, because
no .class file is available for mapping.
• When the Java compiler is invoked from SQLJ, it always reports
compilation errors using line numbers of the original .sqlj source file,
not the generated .java file. No option needs to be set for this mapping.
• Anonymous classes in a .sqlj file will not be instrumented.
• If you are using the Sun Microsystems jdb debugger, then use the
-jdblinemap option instead of the -linemap option.
For example:
-linemap
The syntax for a properties file entry for this option is as follows:
sqlj.linemap<=true|false>
9-39
Chapter 9
Basic Translator Options
For example:
sqlj.linemap
• Overwrites the contents of the .java file generated by the translator with the
contents of the original .sqlj file
• Preserves the .java file name, instead of the .sqlj file name, in the
generated .class file
In this way, the SQLJ source code is accessible to jdb.
For example:
-jdblinemap
The syntax for a properties file entry for this option is as follows:
sqlj.jdblinemap<=true|false>
For example:
sqlj.jdblinemap
See Also:
"SQLJ Support for Oracle Performance Monitoring"
9-40
Chapter 9
Basic Translator Options
Now consider the following example, for an application name of stock and the
package com.acme:
% sqlj -instrument=com.acme/stock Stock.sqlj Trading.sqlj
Note:
A setting of -instrument is equivalent to -instrument=true.
For example:
-instrument=com.acme/stock
9-41
Chapter 9
Basic Translator Options
The syntax for a properties file entry for this option is as follows:
sqlj.instrument<=true|false|application_name>
For example:
sqlj.instrument=com.acme/stock
See Also:
"SQLJ Run-Time Commands and Properties File Settings for DMS"
Note that any components that are not instrumented during translation cannot be
monitored during run time, regardless of what is specified in the properties file.
The -components option supports either of the following settings:
For example:
-components=com.acme.Stock,com.acme.Trading
The syntax for a properties file entry for this option is as follows:
sqlj.components=all|list_of_components
For example:
9-42
Chapter 9
Basic Translator Options
sqlj.components=com.acme.Stock,com.acme.Trading
The default is Oracle-specific SQLJ code generation, but you can also explicitly
specify this as follows:
-codegen=oracle
9-43
Chapter 9
Basic Translator Options
Note:
When codegen=iso, translator settings for -user, -password, -url, -
optparams, -optparamdefaults, and -fixedchar are forwarded to the profile
customizer as well. However, if you want to override these settings for
customization, particularly for -user, -password, and -url, then you can do
so by setting the customizer options directly.
For example:
-codegen=iso
The syntax for as properties file entry for this option is as follows:
sqlj.codegen=iso|oracle
For example:
sqlj.codegen=iso
See Also:
"Column Definitions"
Note:
This translator option is equivalent to the optcols Oracle customizer option
and was created for the default Oracle-specific code generation scenario,
where there are no profiles. But it is also applicable for ISO standard code
generation. In this case, setting the translator option will automatically set the
customizer option as well.
You can enable or disable this flag on the SQLJ command line or in a properties file.
9-44
Chapter 9
Basic Translator Options
or:
-optcols=true
This flag is disabled by default, but you can also disable it explicitly. Disable it on the
command line as follows:
-optcols=false
Note:
• Because definitions are created for all columns that you select, it is
advisable in your SQL operations to explicitly select the columns you will
use, rather than using the SELECT * syntax, if you may not actually use
all the columns selected. A situation where you select more than you
need exposes you to a greater risk of run-time errors, if any changes
were made to the table between customization and run time, especially
when you have customized with column definitions. You may want to
translate with the SQLJ -warn=strict flag set, which will warn you if
additional (unwanted) columns will be selected by your query.
• Column definitions are not possible for any iterator or result set that
includes one or more object or collection columns.
• An error will be generated if you enable the -optcols option without
setting the user name, password, and URL for a database connection.
• The translator 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 example:
-optcols
The syntax for a properties file entry for this option is as follows:
sqlj.optcols<=true|false>
For example:
sqlj.optcols
9-45
Chapter 9
Basic Translator Options
See Also:
"Column Definitions"
Note:
This translator option is equivalent to the optparams Oracle customizer
option. It was created for the default Oracle-specific code generation
scenario, where there are no profiles. But it is also applicable for ISO
standard code generation. In this case, setting the translator option will
automatically set the customizer option as well.
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:
-optparams
or:
-optparams=true
This flag is disabled by default, but you can also disable it explicitly. Disable it on the
command line as follows:
-optparams=false
Note:
Unlike the -optcols option, the -optparams option does not require a
database connection, because you are providing the size specifications
yourself.
9-46
Chapter 9
Basic Translator Options
For example:
-optparams
The syntax for a properties file entry for this option is as follows:
sqlj.optparams<=true|false>
For example:
sqlj.optparams
If a host variable has a source code hint to specify its size, then that takes precedence
over the corresponding data type default size set with this option. If there is no source
code hint or corresponding data type default size for a particular host variable, then
resource allocation for that variable is determined by the JDBC driver, just as it would
be if -optparams were not enabled.
See Also:
"Parameter Size Definitions"
Note:
This translator option is equivalent to the optparamdefaults Oracle
customizer option. It was created for the default Oracle-specific code
generation scenario, where there are no profiles. But it is also applicable
for ISO standard code generation. In this case, setting the translator option
will automatically set the customizer option as well.
9-47
Chapter 9
Basic Translator Options
You can set the -optparamdefaults flag on the command line or in a SQLJ properties
file.
Set it on the command line as follows:
-optparamdefaults=datatype1(size1),datatype2(size2),...
All sizes are in bytes. Do not include any white space. Use empty parentheses for a
null setting.
For example, the following will set sizes of 30 bytes for VARCHAR2 and 1000 bytes
for RAW, and will specify a null size setting for CHAR. So, for any host variable
corresponding to the CHAR data type, if there is no source code hint, then the JDBC
driver is left to allocate the resources.
-optparamdefaults=VARCHAR2(30),RAW(1000),CHAR()
• CHAR
• VARCHAR, VARCHAR2 (synonymous)
• LONG, LONGVARCHAR (synonymous)
• BINARY, RAW (synonymous)
• VARBINARY
• LONGVARBINARY, LONGRAW (synonymous)
The -optparamdefaults option also recognizes group names and wildcards, as
follows:
• CHAR_TYPE covers CHAR, VARCHAR/VARCHAR2, and LONG/LONGVARCHAR.
• RAW_TYPE covers BINARY/RAW, VARBINARY, and LONGVARBINARY/LONGRAW.
• A percent sign (%) by itself covers all recognized data types or appended to a
partial name, covers a subset of data types. For example, VAR% includes all data
types that start with "VAR".
The -optparamdefaults setting is processed from left to right. When using group
names or wildcards, you can override a group setting for particular data types.
The following example sets a general default size of 50 bytes, overrides that with a
setting of 500 bytes for raw types, then overrides the raw type group setting with a null
setting for VARBINARY (leaving that to JDBC for corresponding host variables with no
source code hints):
-optparamdefaults=%(50),RAW_TYPE(500),VARBINARY()
9-48
Chapter 9
Basic Translator Options
Note:
If at run time the actual size exceeds the registered size of any parameter,
then run-time errors will occur.
For example:
-optparamdefaults=VAR%(50),LONG%(500),RAW_TYPE()
The syntax for a properties file entry for this option is as follows:
sqlj.optparamdefaults=defaults_string
For example
sqlj.optparamdefaults=VAR%(50),LONG%(500),RAW_TYPE()
Note:
9-49
Chapter 9
Basic Translator Options
-fixedchar<=true|false>
For example:
-fixedchar
The syntax for a properties file entry for this option is as follows:
sqlj.fixedchar<=true|false>
For example:
sqlj.fixedchar
Note:
For example:
-ncharconv
The syntax for a properties file entry for this option is as follows:
sqlj.ncharconv<=true|false>
For example:
sqlj.ncharconv
9-50
Chapter 9
Advanced Translator Options
false
After stripping the -J prefix, the sqlj script passes the -Duser.language=ja argument
as is to the JVM. In the Sun Microsystems JDK, the
-Duser.language=ja flag sets the user.language system property to the value ja
(Japanese), but specific flags are dependent on the actual Java executable you are
using and are not interpreted or acted upon by the sqlj script in any way.
You cannot pass options to the JVM from a properties file, because properties files are
read after the JVM is invoked.
9-51
Chapter 9
Advanced Translator Options
Note:
For example:
-J-Duser.language=ja
After stripping the -C prefix, the sqlj script passes the -nowarn argument as is to the
compiler.
Generally, compiler options are passed without change, but when you use an equal
sign (=) to set a compiler option that takes a value, such as for -bootclasspath,
-extdirs, or -target, the equal sign is stripped out when the option is passed to the
compiler. Consider the following example:
% sqlj -C-bootclasspath=/usr/local/packages/jdk6/jre/lib/rt.jar myfile.sqlj
Also note that if the Java compiler runs in its own JVM, then you can pass options to
that JVM through the compiler. Accomplish this by prefixing the JVM option with
-C-J with no spaces between this prefix combination and the option. For example:
-C-J-Duser.language=de
9-52
Chapter 9
Advanced Translator Options
• Do not use -C-d to specify an output directory for .class files. Instead, use the
SQLJ -d option, which specifies the output directory for generated profile files
(.ser), and is also passed to the Java compiler. This will ensure that .class files
and .ser files are in the same directory.
Note:
For example:
-C-nowarn
The syntax for a properties file entry for this option is as follows:
compile.Java_compiler_option
For example:
compile.nowarn
9-53
Chapter 9
Advanced Translator Options
-P-backup
The -backup flag is a generic customizer option to backup the previous customization
before generating a new one.
Following is an example of a vendor-specific customizer option (in this case, Oracle-
specific):
-P-Csummary
The summary flag is an Oracle customizer option that prints a summary of the
customizations performed.
Note:
For example:
-P-driver=oracle.jdbc.OracleDriver
-P-Csummary
The syntax for a properties file entry for this option is as follows:
profile.<C>profile_customizer_option
For example:
profile.driver=oracle.jdbc.OracleDriver
profile.Csummary
9-54
Chapter 9
Advanced Translator Options
• -compile
• -profile
The -ser2class flag, for ISO code generation, directs SQLJ to convert profiles from
serialized resource (.ser) files to class files after customization.
When you process a .sqlj file with -compile=false, you are responsible for
compiling and customizing it later as necessary.
Setting -compile=false also implicitly sets -profile=false. In other words, whenever
-compile is false, both compilation and customization are skipped. If you set -
compile=false and -profile=true, then your -profile setting is ignored.
Note:
There are situations where it is sensible for -compile to be set to false even
when .java files must be accessed for type resolution. You may do this,
for example, if you are translating a .sqlj file and want to specify one or
more .java files on the command line for type resolution during translation,
but want to compile all your .java files later using a particular compiler.
Note, however, that the -checksource option can simplify the type resolution
process by eliminating the need to enter .java files for resolution on the
SQLJ command line.
For example:
-compile=false
The syntax for a properties file entry for this option is as follows:
sqlj.compile<=true|false>
For example:
sqlj.compile=false
9-55
Chapter 9
Advanced Translator Options
true
This option acts differently than the -compile option for files specified on the command
line. Any .ser and .jar files specified on the command line are still customized if
-profile=false. However, .java files specified on the command line are not compiled
if -compile=false. The reason for this is that you may want other operations, such as
line mapping, to be performed on a .java file. There are, however, no other operations
that can be performed on a .ser or .jar file specified on the command line.
When you process a .sqlj file with -profile=false, you are responsible for
customizing it later, as necessary.
Note:
• Set this option to false if you do not want your application to require
Oracle SQLJ run time and an Oracle JDBC driver when it runs.
Or accomplish this by specifying a nondefault customizer, using the
-default-customizer option. If no customization is performed, then the
generic SQLJ run time will be used when your application runs.
• Setting -compile=false also implicitly sets -profile=false. In other
words, whenever -compile is false, both compilation and customization
are skipped. If you set -compile=false and -profile=true, then your
-profile setting is ignored.
• This option is not applicable for the default Oracle-specific code
generation, where no profiles are produced and so no customization is
performed.
For example:
-profile=false
The syntax for a properties file entry for this option is as follows:
sqlj.profile<=true|false>
For example:
sqlj.profile=false
9-56
Chapter 9
Advanced Translator Options
true
This also simplifies the naming of schema objects for your profiles in situations where
you are translating a SQLJ program on a client and then loading classes and resource
files into the server. Loaded class schema objects have a simpler naming convention
than loaded resource schema objects.
The conversion is performed after profile customization so that it includes your
customizations. The base names of converted files are identical to those of the original
files. The only difference in the file name is .ser being replaced by .class. For
example, consider the following:
Foo_SJProfile0.ser
Note:
For example:
-ser2class
The syntax for a properties file entry for this option is as follows:
sqlj.ser2class<=true|false>
For example
sqlj.ser2class
9-57
Chapter 9
Advanced Translator Options
Note:
This applies only to Java types that appear in #sql statements, not
elsewhere in your Java code. Therefore, you should always explicitly provide
the names of any required .sqlj files on the SQLJ command line.
For example:
-checksource=false
The syntax for a properties file entry for this option is as follows:
sqlj.checksource=<=true|false>
For example:
sqlj.checksource=false
Because separate bind reference names are created for the two occurrences of
bind_var, this results in a SQL exception at run time. When the differing bind names
are detected, the SQL engine concludes that the GROUP BY clause is not part of the
SELECT-list.
9-58
Chapter 9
Advanced Translator Options
To avoid such problems, Oracle extends standard functionality with the -bind-by-
identifier flag. A setting of true results in all bind occurrences of the same
identifier in a given SQLJ statement or PL/SQL block being treated as a single bind
occurrence. A SQLJ statement with four bind operations, :x, :x, :y, :x, would be
bound as :1, :1, :2, :1 instead of :1, :2, :3, :4.
Note:
The -bind-by-identifier flag applies only to host expressions that are
simple host variables.
For example:
-bind-by-identifier
The syntax for a properties file entry for this option is as follows:
sqlj.bind-by-identifier=<=true|false>
For example:
sqlj.bind-by-identifier
9-59
Chapter 9
Advanced Translator Options
Note:
Online semantics-checking is enabled by setting the translator -user option.
However, the setting of the -parse option, which is used to enable or disable
offline parsing, can override this.
Database Release JDBC Release Chosen Online Checker Other Legal Online
Checkers
Oracle10g, 9i, or 8i Oracle11g Oracle8JdbcChecker Oracle8To7JdbcChecker
9-60
Chapter 9
Advanced Translator Options
Online checking offers the primary advantage of verifying SQL and PL/SQL operations
against the database schema. This includes verifying that column types match SQL
operations and verifying the existence of called stored procedures. It requires a
database connection during translation, however, which may be problematic in some
circumstances. It also performs no verification of DDL operations.
Offline parsing offers the advantage of SQL syntax-checking without a database
connection during translation, and also includes DDL operations in its syntax
verifications.
Note that neither mode performs DDL semantics-checking against the database
schema.
Note:
• If both offline parsing and online checking are enabled, some types of
errors will be reported twice.
• Problems detected by either the offline parser or the online checker are
reported at a warning or advisory level, not a fatal level.
• Do not confuse offline parsing with offline semantics-checking. Offline
checking consists of basic semantics-checking steps that always occur,
regardless of whether online checking is enabled and regardless of
whether offline parsing is enabled: analysis of the types of Java
expressions in your SQLJ executable statements, and categorization of
embedded SQL operations according to keyword, such as SELECT.
• Compatibility of data corresponding to weakly typed host expressions is
never checked.
• Mode compatibility of expressions in PL/SQL anonymous blocks is never
checked.
9-61
Chapter 9
Advanced Translator Options
The following example shows how to select Oracle8 offline checker for a particular
connection context (CtxClass):
-offline@CtxClass=oracle.sqlj.checker.Oracle8OfflineChecker
The CtxClass connection context class must be declared in your source code
or previously compiled into a .class file. (See "Connection Contexts" for more
information.)
Use the -offline option separately for each connection context offline checker you
want to specify; these settings have no influence on each other. For example:
-offline@CtxClass2=oracle.sqlj.checker.Oracle8OfflineChecker
-offline@CtxClass3=sqlj.semantics.OfflineChecker
To specify the offline checker for the default connection context and any other
connection contexts for which you do not specify an offline checker:
-offline=oracle.sqlj.checker.Oracle8OfflineChecker
Any connection context without an offline checker setting uses the offline checker
setting of the default connection context, presuming an offline checker has been set for
the default context.
The command-line syntax for this option is as follow:
-offline<@conn_context_class>=checker_class
For example:
-offline=oracle.sqlj.checker.Oracle8OfflineChecker
-offline@CtxClass=oracle.sqlj.checker.Oracle8OfflineChecker
The syntax for a properties file entry for this option is as follows:
sqlj.offline<@conn_context_class>=checker_class
For example:
sqlj.offline=oracle.sqlj.checker.Oracle8OfflineChecker
sqlj.offline@CtxClass=oracle.sqlj.checker.Oracle8OfflineChecker
9-62
Chapter 9
Advanced Translator Options
Note:
Some settings of the SQLJ -parse option will disable online semantics-
checking, overriding the effect of the -user option.
You can specify different online checkers for different connection contexts, and you
can list multiple checkers (separated by commas) for any given context. In cases
where multiple checkers are listed for a single context, SQLJ uses the first checker
(reading from left to right in the list) that accepts the database connection established
for online checking. At analysis time, a connection is passed to each online checker
and the checker decides whether it recognizes the database.
The default OracleChecker, a front-end class, will serve your needs unless you want to
specify a particular checker that would not be chosen by OracleChecker.
The following example shows how to select Oracle8 online checker for the
DefaultContext class and any other connection context classes without a specified
setting:
-online=oracle.sqlj.checker.Oracle8JdbcChecker
To specify a list of drivers and allow the proper class to be selected depending on what
kind of database is being accessed:
-online=oracle.sqlj.checker.Oracle8JdbcChecker,sqlj.semantics.JdbcChecker
The CtxClass connection context class must be declared in your source code or
previously compiled into a .class file.
9-63
Chapter 9
Advanced Translator Options
Use the -online option separately for each connection context online checker you
want to specify. These settings have no influence on each other:
-online@CtxClass2=oracle.sqlj.checker.Oracle8JdbcChecker
-online@CtxClass3=sqlj.semantics.JdbcChecker
Any connection context without an online checker setting uses the online checker
setting of the default connection context.
The command-line syntax for this option is as follows:
-online<@conn_context_class>=checker_class(list)
For example:
-online=oracle.sqlj.checker.Oracle8JdbcChecker
-online=oracle.sqlj.checker.Oracle8JdbcChecker,sqlj.semantics.JdbcChecker
-online@CtxClass=oracle.sqlj.checker.Oracle8JdbcChecker
The syntax for a properties file entry for this option is as follows:
sqlj.online<@conn_context_class>=checker_class(list)
For example:
sqlj.online=oracle.sqlj.checker.Oracle8JdbcChecker
sqlj.online=oracle.sqlj.checker.Oracle8JdbcChecker,sqlj.semantics.JdbcChecker
sqlj.online@CtxClass=oracle.sqlj.checker.Oracle8JdbcChecker
For example:
-cache
The syntax for a properties file entry for this option is as follows:
sqlj.cache<=true|false>
For example:
sqlj.cache
9-64
Chapter 9
Advanced Translator Options
• both (default): Enable the offline parser and allow online checking. In this case,
online checking is determined by the -user option.
• online-only: Disable the offline parser and allow online checking. Again, online
checking is determined by the -user option.
• offline-only: Enable the offline parser and disallow online checking. This
overrides any -user option setting that would otherwise enable online checking.
• none: Disable the offline parser and disallow online checking, Again, this overrides
any -user option setting that would otherwise enable online checking.
• parserclassname: Specify the name of a Java class that implements
an alternative SQL parser. The class must implement the
sqlj.framework.checker.SimpleChecker interface. This setting enables the
specified parser, and only that parser is used for SQL-checking. The standard
offline parser and online checking are both disabled.
FUTURE: Document the SimpleChecker interface.
The offline-only and none settings are offered for completeness, but are not typical
modes of operation. It is best to let the -user option determine online checking. It is
also not typical to specify your own parser.
Note:
In modes where both offline parsing and online checking are enabled, there
may be duplicate reporting of some problems.
For example:
-parse=online-only
The syntax for a properties file entry for this option is as follows:
sqlj.parse=both|online-only|offline-only|none|parserclassname
For example:
sqlj.parse=online-only
9-65
Chapter 9
Translator Support and Options for Alternative Environments
Note:
Be aware of the limitations of any operating system and environment you
use. In particular, the complete, expanded SQLJ command line must not
exceed the maximum command-line size. Consult your operating system
documentation.
9-66
Chapter 9
Translator Support and Options for Alternative Environments
breaking SQLJ processing into a two-pass process. You can also pass options directly
to the particular JVM or compiler you use, through the -J and -C prefixes.
Note:
The -vm option, -passes option, and -J prefix cannot be used in a properties
file. You can set them on the command line or, more conveniently, in the
SQLJ_OPTIONS environment variable.
Note:
Special functionality of this option, -vm=echo, is supported. This is equivalent
to the -n option, instructing the sqlj script to construct the full command line
that would be passed to the SQLJ translator, and echo it to the user without
having the translator execute it.
For example:
-vm=/myjavadir/myjavavm
9-67
Chapter 9
Translator Support and Options for Alternative Environments
• It will understand the SQLJ -d option, which determines the root directory for class
files.
• It must return a nonzero exit code to the operating system whenever a compilation
error occurs.
• The line information that it provides in any errors or messages must be in one of
the following formats (items in <> brackets being optional):
– Sun Microsystems javac format
filename.java:line<.column><-line<.column>>
Note:
For a compiler that does not support an -encoding option, disable the
-compiler-encoding-flag.
For example:
-compiler-executable=/myjavadir/myjavac
The syntax for a properties file entry for this option is as follows:
sqlj.compiler-executable=Java_compiler_path+name
For example:
sqlj.compiler-executable=myjavac
9-68
Chapter 9
Translator Support and Options for Alternative Environments
-compiler-encoding-flag<=true|false>
For example:
-compiler-encoding-flag=false
The syntax for a properties file entry for this option is as follows:
sqlj.compiler-encoding-flag<=true|false>
For example:
sqlj.compiler-encoding-flag=false
Note:
You cannot use this option if you enable -passes, which requires output to
STDOUT.
For example:
-compiler-output-file=/myjavadir/mycmploutput
The syntax for a properties file entry for this option is as follows:
sqlj.compiler-output-file=output_file_path+name
For example:
sqlj.compiler-output-file=/myjavadir/mycmploutput
Note:
This option is relevant only for JDK 1.2.x.
9-69
Chapter 9
Translator Support and Options for Alternative Environments
By default, the Java compiler writes errors and message output to STDERR. However,
if the error messages from the Java compiler should also be redirected to the same
file as specified with the -compiler-output-file option, then set this flag to true.
This option is meaningful only if used in conjunction with the -compiler-output-file
option.
If SQLJ sets the javac.pipe.output system property to true, which is the SQLJ
default behavior when it invokes the Java compiler, then compiler error and message
output will be sent to STDOUT. However, you can specify -compiler-pipe-output-
flag=false to instruct SQLJ to not set this system property when it invokes the Java
compiler. You should do this, for example, if the Java compiler you are using does not
support the javac.pipe.output system property.
You can set this flag in a properties file, as well as on the command line or in the
SQLJ_OPTIONS environment variable.
Note:
For a Java compiler that originates from Sun Microsystems and writes its
output to STDERR by default, you must leave -compiler-pipe-output-flag
enabled, if you enable -passes, which requires output to STDOUT.
For example, while compiling a file called MyDemo.sqlj, for which the Java compiler
messages and error messages are to be redirected to the same file, the following
syntax should be used:
sqlj -compiler-output-file=/myjavadir/mycmploutput
-compiler-pipe-output-flag=true MyDemo.sqlj
The syntax for a properties file entry for this option is as follows:
sqlj.compiler-pipe-output-flag<=true|false>
Note:
If this flag is set to false, then the error messages from the Java compiler will
be directed to STDERR.
9-70
Chapter 9
Translator Support and Options for Alternative Environments
The -checkfilename flag instructs SQLJ whether to verify that the SQLJ source file
name matches the name of the public class, if any, defined there. Some compilers,
such as the standard javac, require this to be the case, while others do not.
To maximize portability of your code, this flag should be enabled, which it is by default.
Note:
If you are translating in the server, where there is no equivalent naming
requirement, there is no -checkfilename option and the translator executes
no such check.
For example:
-checkfilename=false
The syntax for a properties file entry for this option is as follows:
sqlj.checkfilename<=true|false>
For example:
sqlj.checkfilename=false
1. The sqlj script invokes your JVM, which runs the SQLJ translator.
2. The translator completes the semantics-checking and translation of your .sqlj
files, generating translated .java files.
3. The translator invokes your Java compiler, which compiles the generated .java
files.
4. The translator processes the compiler output.
5. If any profile files were generated, then the translator invokes a profile customizer
to customize them.
For some JVM and compiler configurations, however, the compiler invocation in Step 3
might not return, in which case your translation will suspend.
If you encounter this situation, the solution is to instruct SQLJ to run in two passes,
with the compilation step in between. To accomplish this, you must enable the two-
pass execution flag as follows:
-passes
9-71
Chapter 9
Translator Support and Options for Alternative Environments
The -passes option must be specified on the command line or, equivalently, in the
SQLJ_OPTIONS environment variable. It cannot be specified in a properties file.
Note:
With -passes enabled, the following occurs when you invoke the sqlj script:
1. The sqlj script invokes your JVM, which runs the SQLJ translator for its first pass.
2. The translator completes the semantics-checking and translation of your .sqlj
files, generating translated .java files.
3. The JVM is terminated.
4. The sqlj script invokes the Java compiler, which compiles the generated .java
files.
5. The sqlj script invokes your JVM again, which runs the SQLJ translator for its
second pass.
6. The translator processes compiler output.
7. If any profile files were generated, the JVM runs your profile customizer to
customize them.
With this sequence, you circumvent any problems the JVM might have in invoking the
Java compiler.
The command-line syntax for this option is as follows:
-passes
For example:
-passes
9-72
Chapter 9
Translator Support and Options for Alternative Environments
Note:
If you use the default Oracle-specific code generation, then SQLJ generates
no profiles and, therefore, performs no customization. In that case, these
options do not apply.
In particular, use this option if you are not using Oracle Database. This option takes a
fully qualified Java class name as its argument.
Note:
You can override this option with the -P-customizer option in your SQLJ
command line or properties file.
For example:
-default-customizer=sqlj.myutil.MyCustomizer
The syntax for a properties file entry for this option is as follows:
sqlj.default-customizer=customizer_classname
For example:
sqlj.default-customizer=sqlj.myutil.MyCustomizer
Note:
When you use Oracle Database and ISO code generation, Oracle
recommends that you use the default OraCustomizer for your profile
customization.
9-73
10
Translator and Run-Time Functionality
This chapter discusses internal operations and functionality of Oracle SQLJ translator
and run time.
The following topics are covered:
• Internal Translator Operations
• Functionality of Translator Errors_ Messages_ and Exit Codes
• SQLJ Run Time
• Globalization Support in the Translator and Run Time
10-1
Chapter 10
Internal Translator Operations
See Also:
"Connection Options" and "Semantics-Checking and Offline-Parsing Options"
Note:
For ISO code generation, semantics-checking can also be performed on a
profile that was produced during a previous execution of the SQLJ translator.
Refer to "SQLCheckerCustomizer for Profile Semantics-Checking".
10-2
Chapter 10
Internal Translator Operations
The myCtx variable, which might be used to specify a connection context instance
or execution context instance for this statement, must actually resolve to a SQLJ
connection context type or execution context type.
Now consider the following example:
#sql { UPDATE employees SET salary = :newSal };
Note:
Semantics-checking of Java types is performed only for Java
expressions within SQLJ executable statements. Such errors in your
standard Java statements will not be detected until compilation by the
Java compiler.
2. SQLJ tries to categorize your embedded SQL operations. Each operation must
have a recognizable keyword, such as SELECT or INSERT, so that SQLJ knows
what kind of operation it is. For example, the following statement will generate an
error:
#sql { foo };
3. If either online checking or offline parsing (or both) is enabled, then SQLJ analyzes
and verifies the syntax of embedded SQL and PL/SQL operations.
4. If either online checking or offline parsing (or both) is enabled, then SQLJ checks
the types of Java expressions in SQLJ executable statements against SQL types
of corresponding columns in the database and SQL types of corresponding
arguments and return variables of stored procedures and functions.
In the process of doing this, SQLJ verifies that the SQL entities used in your SQLJ
executable statements, such as tables, views, and stored procedures, actually
exist in the database. SQLJ also checks nullability of database columns whose
data is being selected into iterator columns of Java primitive types, which cannot
process null data. However, nullability is not checked for stored procedure and
function output parameters and return values.
10-3
Chapter 10
Internal Translator Operations
Note:
No profiles or profile-keys class are generated if you use the default Oracle-
specific code generation mode.
With ISO code generation, there are no profiles or profile-keys class if you do
not use any SQLJ executable statements in your code.
See Also:
"Output Directory for Generated .java Files (-dir)"
Note:
If you use the default Oracle-specific code generation, no profiles or profile-
keys classes are generated.
The profile-keys class is defined in the same .java output file that has your translated
application source code, with a class name based on the base name of your .sqlj
source file as follows:
Basename_SJProfileKeys
10-4
Chapter 10
Internal Translator Operations
For example, translating Foo.sqlj defines the following profile-keys class in the
generated .java file:
Foo_SJProfileKeys
Note:
If you use the default Oracle-specific code generation, then information about
the SQL operations is embedded in the generated code, which calls Oracle
JDBC driver directly. In this case, SQLJ does not generate profiles.
Profiles are generated in .ser serialized resource files. However, if you enable the
SQLJ -ser2class option, then the profiles are automatically converted to .class
files as part of the translation. In this case, no further customization of the profile
is possible. You would have to delete the .class file and rerun the SQLJ translator to
regenerate the profile.
Profile base names are generated similarly to the profile-keys class name. They are
fully qualified with the package name, followed by the .sqlj file base name, followed
by the string:
_SJProfilen
Where n is a unique number, starting with 0, for each profile generated for a
particular .sqlj input file.
Again using the example of the Foo.sqlj input file, if two profiles are generated, then
they will have the following base names (presuming no package):
Foo_SJProfile0
Foo_SJProfile1
If Foo.sqlj is in the a.b package, then the profile base names will be:
a.b.Foo_SJProfile0
a.b.Foo_SJProfile1
Physically, a profile exists as a Java serialized object contained within a resource file.
Resource files containing profiles use the .ser extension and are named according to
the base name of the profile (excluding package names). Resource files for the two
previously mentioned profiles will be named as follows:
10-5
Chapter 10
Internal Translator Operations
Foo_SJProfile0.ser
Foo_SJProfile1.ser
See Also:
"Conversion of .ser File to .class File (-ser2class)"
The location of these files depends on how the SQLJ -d option is set, which
determines where all generated .ser and .class files are placed.
See Also:
"Output Directory for Generated .ser and .class Files (-d)"
Table 10-1 Steps for Generated Calls, ISO Standard Versus Oracle-Specific
Steps for ISO Standard Code Generation Steps for Oracle Code Generation
Get a SQLJ statement object, using Get an Oracle JDBC statement object.
information stored in the associated profile
entry.
Bind inputs into the statement, using Bind inputs using Oracle JDBC statement
setXXX() methods of the statement object. methods and, if necessary, register output
parameters.
Execute the statement, using the Execute the Oracle statement.
executeUpdate() or executeQuery()
method of the statement object.
Create iterator instances, if applicable. Create iterator instances, if applicable.
Retrieve outputs from the statement, using Retrieve outputs from the statement using
getXXX() methods of the statement object. appropriate JDBC getter methods.
Close the SQLJ statement object (by default, Close the JDBC statement object (by default,
recycling it through the SQLJ statement recycling it through the JDBC statement
cache). cache).
A SQLJ run time uses SQLJ statement objects that are similar to JDBC statement
objects, although a particular implementation of SQLJ might or might not use JDBC
statement classes directly. SQLJ statement classes add functionality particular to
SQLJ. For example:
10-6
Chapter 10
Internal Translator Operations
• Standard SQLJ statement objects raise a SQL exception if a null value from the
database is to be output to a primitive Java type, such as int or float, which
cannot take null values.
• Oracle SQLJ statement objects allow user-defined object and collection types to
be passed to or retrieved from Oracle Database.
In addition, so that SQLJ and the Java compiler will use the same encoding,
SQLJ passes its -encoding option to the Java compiler unless the SQLJ -compiler-
encoding-flag is turned off. If the -encoding option is not set, then SQLJ and
the compiler will use the setting in the Java virtual machine (JVM) file.encoding
property.
By default, SQLJ invokes the standard javac compiler of the Sun Microsystems Java
Development Kit (JDK), but other compilers can be used instead. You can request
that an alternative Java compiler be used by setting the SQLJ -compiler-executable
option.
Note:
If you are using the SQLJ -encoding option but using a compiler that does
not have an -encoding option, then turn off the SQLJ -compiler-encoding-
flag. Otherwise, SQLJ will attempt to pass the -encoding option to the
compiler.
10-7
Chapter 10
Internal Translator Operations
Note:
If you use the default Oracle-specific code generation, then SQLJ produces
no profiles and skips the customization step. Your code will support
Oracle-specific features through direct calls to Oracle JDBC application
programming interfaces (APIs).
If you want to check for the options already set on the customizer, then you can make
use of the following command:
% sqlj -P-print *.ser
For more information about profile print option, refer to "Specialized Customizer:
Profile Print Option (print)".
To accomplish customization, SQLJ invokes a front end called the customizer harness,
which is a Java class that functions as a command-line utility. The harness, in turn,
invokes a particular customizer, either the default Oracle customizer or a customizer
that you specify through SQLJ option settings.
During customization, profiles are updated in the following ways:
• To enable your application to use any vendor-specific database types or features,
if applicable
• To tailor the profiles so that your application is as efficient as possible in using
features of the relevant database environment
Without customization, you can access and use only standard JDBC types.
For example, Oracle customizer can update a profile to support a SQL PERSON type
that you had defined. You could then use PERSON as you would any other supported
data type.
You must also customize with Oracle customizer to use any of the oracle.sql type
extensions.
10-8
Chapter 10
Functionality of Translator Errors, Messages, and Exit Codes
Note:
Be aware of the following regarding profile customization:
• Oracle SQLJ run time and an Oracle JDBC driver will be required by
your application whenever you use Oracle customizer during translation,
even if you do not use Oracle extensions in your code.
• The generic SQLJ run time will be used if your application has no
customizations, or none suitable for the connection.
• You can customize previously created profiles by specifying .ser files,
or .jar files containing .ser files, on the command line. But you cannot
do this in the same running of SQLJ where translations are taking place.
You can specify .ser/.jar files to be customized or .sqlj/.java files to
be translated, compiled, and customized, but not both categories. For
more information about how .jar files are used, refer to "JAR Files for
Profiles".
10-9
Chapter 10
Functionality of Translator Errors, Messages, and Exit Codes
• A condition that would result in a run-time error if the code were executed (for
example, the code attempts to fetch a VARCHAR into a java.util.Vector, using an
Oracle JDBC driver)
If errors are encountered during SQLJ translation, then no output is produced and
compilation and customization are not executed.
Nonsuppressible warning messages, prefixed by Warning:, indicate that one of the
following has been encountered:
• A condition that would probably, but not necessarily, result in a run-time error if
the code were executed (for example, a SELECT statement whose output is not
assigned to anything)
• A condition that compromises the ability of SQLJ to verify run-time aspects of your
source code (for example, not being able to connect to the database you specify
for online checking)
• A condition that presumably resulted from a coding error or oversight
SQLJ translation will complete if a nonsuppressible warning is encountered, but you
should analyze the problem and determine if it should be fixed before running the
application. If online checking is specified but cannot be completed, then offline
checking is performed instead.
Note:
For logistical reasons, the parser that the SQLJ translator uses to analyze
SQL operations is not the same top-level SQL parser that will be used at run
time. Therefore, errors might occasionally be detected during translation that
will not actually cause problems when your application runs. Accordingly,
such errors are reported as nonsuppressible warnings, rather than fatal
errors.
10-10
Chapter 10
Functionality of Translator Errors, Messages, and Exit Codes
See Also:
"Real-Time Status Messages (-status)"
10-11
Chapter 10
SQLJ Run Time
Note:
• If you issue the -help or -version option, then the SQLJ exit code is 0.
• If you run SQLJ without specifying any files to process, then SQLJ
issues help output and returns exit code 1.
See Also:
"Oracle-Specific Code Generation (No Profiles)"
When SQLJ translates SQLJ source code using ISO standard code generation,
embedded SQL commands in your Java application are replaced by calls to the SQLJ
run time. Run-time classes act as wrappers for equivalent JDBC classes, providing
special SQLJ functionality. When the end user runs the application, the SQLJ run time
acts as an intermediary, reading information about your SQL operations from your
profile and passing instructions along to the JDBC driver.
Generally speaking, however, a SQLJ run time can be implemented to use any
JDBC driver or vendor-proprietary means of accessing the database. Oracle SQLJ
run time requires a JDBC driver, but can use any standard JDBC driver. To use
Oracle-specific data types and features, however, you must use an Oracle JDBC
10-12
Chapter 10
SQLJ Run Time
driver. For the purposes of this document, it is generally assumed that you are using
Oracle Database and one of Oracle JDBC drivers.
Note:
For ISO standard SQLJ code generation, Oracle SQLJ run time and an
Oracle JDBC driver will be required by your application whenever you
use Oracle customizer during translation, even if you do not use Oracle
extensions in your code. The generic SQLJ run time will be used if your
application has no customizations, or none suitable for the connection.
Note:
These packages are included in the run-time libraries runtime12,
runtime12ee, and runtime.
10-13
Chapter 10
SQLJ Run Time
Note:
Packages whose names begin with oracle are for Oracle-specific SQLJ
features.
Depending on where the error came from, there might be meaningful information
you can retrieve from an exception using the getSQLState(), getErrorCode(), and
getMessage() methods. SQLJ errors, for example, include meaningful SQL states and
messages.
10-14
Chapter 10
Globalization Support in the Translator and Run Time
If errors are generated by Oracle JDBC driver or RDBMS at run time, look at the prefix
and consult the appropriate documentation:
• Oracle Database JDBC Developer's Guide for JDBC errors
• Oracle error message documentation for RDBMS errors (see "Related
Documents")
Note:
Some prior knowledge of Oracle Globalization Support is assumed,
particularly regarding character encoding and locales. For information, refer
to:
Oracle Database Globalization Support Guide
10-15
Chapter 10
Globalization Support in the Translator and Run Time
This determines which translations of error and status message lists are used
when SQLJ outputs messages to the user, either during SQLJ translation or at
SQLJ run time.
Globalization support at run time is transparent to the user, presuming your SQLJ
source code and SQL character data use only characters that are within the database
character set. SQL character data is transparently mapped into and out of Unicode.
Note that for multi-language applications, it is advisable to use one of the following
options:
• Use a database whose character set supports Unicode.
• Even if your database character set does not support Unicode, specify that the
national language character set supports Unicode. (Refer to the Oracle Database
Globalization Support Guide.) In this case, you will typically use the SQLJ Unicode
character types described in "SQLJ Extended Globalization Support".
Note:
• The SQLJ translator fully supports Unicode 2.0 and Java Unicode
escape sequences. However, the SQLJ command-line utility does not
support Unicode escape sequences. You can use only native characters
supported by the operating system. Command-line options requiring
Unicode escape sequences can be entered in a SQLJ properties file
instead, because properties files do support Unicode escape sequences.
• Encoding and conversion of characters in your embedded SQL
operations and characters read or written to the database, are handled
by JDBC directly. SQLJ does not play a role in this. If online semantics-
checking is enabled during translation, however, then you will be warned
if there are characters within the text of your SQL data manipulation
language (DML) operations that might not be convertible to the database
character set.
• For information about JDBC globalization support functionality, refer to
the Oracle Database JDBC Developer's GuideOracle Database JDBC
Developer’s Guide.
10-16
Chapter 10
Globalization Support in the Translator and Run Time
Note:
Do not alter the file.encoding system property to specify encodings for
source files. This might impact other aspects of your Java operation and
might offer only a limited number of encodings, depending on platform or
operating system considerations.
The system character-encoding setting also determines how SQLJ error and status
messages are represented when output to the user, either during translation or during
run time when the end user is running the application. This is set according to the
file.encoding property and is unaffected by the SQLJ -encoding option.
For source file encoding, you can use the -encoding option to specify any character
encoding supported by your Java environment. If you are using the Sun Microsystems
JDK, then these are listed in the native2ascii documentation, which you can find at
the following Web site:
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/native2ascii.html
Dozens of encodings are supported by the Sun Microsystems JDK. These include
8859_1 through 8859_9 (ISO Latin-1 through ISO Latin-9), JIS (Japanese), SJIS (shift-
JIS, Japanese), and UTF8.
10-17
Chapter 10
Globalization Support in the Translator and Run Time
Note:
Java locale settings can support country and variant extensions in addition
to language extensions. For example, consider ErrorMessages_de_CH_var1,
where CH is the Swiss country extension of German and var1 is an additional
variant. SQLJ, however, currently supports only language extensions (de in
this example), ignoring country and variant extensions.
10.4.2 SQLJ and Java Settings for Character Encoding and Language
Support
The Oracle SQLJ implementation provides syntax that enables you to set the
following:
• The character encoding used by the SQLJ translator and Java compiler in
representing source code
Use the SQLJ -encoding option.
• The character encoding used by the SQLJ translator and run time in representing
error and status messages
Use the SQLJ -J prefix to set the Java file.encoding property.
• The locale used by the SQLJ translator and run time for error and status
messages
Use the SQLJ -J prefix to set the Java user.language property.
This option can be set on the command line or SQLJ_OPTIONS environment variable, as
in the following example:
-encoding=SJIS
If the encoding option is not set, then both the translator and compiler will use the
encoding specified in the JVM file.encoding property. This can also be set through
the SQLJ command line.
10-18
Chapter 10
Globalization Support in the Translator and Run Time
See Also:
"Encoding for Input and Output Source Files (-encoding)" and "Compiler
Encoding Support (-compiler-encoding-flag)"Encoding for Input and Output
Source Files (-encoding)
Note:
If your -encoding is to be set routinely to the same value, then it is most
convenient to specify it in a properties file, as in the second example.
Note:
Only a limited number of encodings might be available, depending on
platform or operating system considerations.
Set the locale as in the following example (which specifies Japanese locale):
-J-Duser.language=ja
The -J prefix can be used on the command line or SQLJ_OPTIONS environment variable
only. It cannot be used in a properties file, because properties files are read after the
JVM is invoked.
10-19
Chapter 10
Globalization Support in the Translator and Run Time
Note:
See Also:
"Command-Line Syntax and Operations" and "Options to Pass to the Java
Virtual Machine"
This example uses the SQLJ -encoding option to specify 8859_1 (Latin-1) for source
code representation during SQLJ translation. This encoding is used by the translator
in reading the .sqlj input file and in generating the .java output file. The encoding is
then passed to the Java compiler to be used in reading the generated .java file. The
-encoding option, when specified, is always passed to the Java compiler unless the
SQLJ -compiler-encoding-flag is disabled.
For error and status messages output during translation of Foo.sqlj, the SQLJ
translator uses the SJIS encoding and the ja locale.
10-20
Chapter 10
Globalization Support in the Translator and Run Time
national language character set that does support Unicode, that you will typically use
these types (for columns that use the national language character set).
Table 10-3 JDBC and SQLJ Types and Corresponding Globalization Types
In situations where your application must handle national language character strings,
either inserting them into or selecting them from national language character set
columns, use the globalization support types instead of the corresponding general-use
types.
Note:
10-21
Chapter 10
Globalization Support in the Translator and Run Time
To insert a row in this table through a SQLJ application, use a code similar to the
following:
...
String v_a = "\uFF5E";
NString v_nb = "\uFF5E";
#sql {INSERT INTO Tbl1 (ColA, NColB) VALUES (:v_a, :v_nb)};
...
Since Oracle Database 11g Release 1, SQLJ applications can use String variables to
bind NCHAR columns. Therefore, the preceding example can be rewritten as follows:
...
String v_a = "\uFF5E";
String v_nb = "\uFF5E";
#sql {INSERT INTO Tbl1 (ColA, NColB) VALUES (:v_a, :v_nb)};
...
However, if you want to use String host variable to bind to NCHAR columns, then you
must translate the SQLJ file with the -ncharconv SQLJ translator option, as follows:
sqlj -ncharconv [-options] app.sqlj
In the preceding command, options can be other SQLJ options and app.sqlj is the
SQLJ file that contains the code.
When this option is used, the setFormOfUse method will be generated for all binds to
character columns, that is, CHAR or NCHAR columns.
Note:
When the SQLJ file is compiled with the -ncharconv option, the
setFormOfUse method is used in the generated code for codegen=oracle.
For codegen=iso, this option information is passed to Oracle SQLJ run time,
which internally uses SetFormOfUse for bind at run time.
10-22
Chapter 10
Globalization Support in the Translator and Run Time
The SQLJ application can use String host variable to retrieve data from the server
without using the -ncharconv option, because the information about the column type
is fetched at the client-side and JDBC internally sets the form for the appropriate
columns.
Note:
There may be a small difference in the performance when using the -
ncharconv option, depending on the database character set and national
charster set and the number of character columns in the table.
• NString as IN argument
This example uses an NString instance as an input parameter to the database.
import oracle.sql.NString;
...
NString nc_name = new NString("Name with strange characters");
#sql { update PEOPLE
set city = :(new NString("\ufff2")), name = :nc_name
where num= :n };
...
• NString as OUT argument
This example uses an NString instance as an output parameter from the
database.
import oracle.sql.NString;
...
NString nstr;
#sql { call foo(:out nstr) };
System.out.println("Result is: "+nstr);
// or, explicitly: System.out.println("Result is: "+nstr.toString());
...
• NString as Result Set column
This example uses the NString type for an iterator column. Such usage is
superfluous, given that the underlying network protocol supports national language
characters implicitly, but harmless. This example also shows use of one of the
String methods, substring(), that is carried over to NString.
import oracle.sql.NString;
import oracle.sql.NCLOB;
...
#sql iterator NIter(NString title, NCLOB article);
NIter nit;
#sql nit = { SELECT article, title FROM page_table };
while (nit.next())
{
System.out.println("<TITLE>"+nit.title()+"</TITLE>");
...
10-23
Chapter 10
Globalization Support in the Translator and Run Time
Note:
Using the NCHAR type instead of the NString type for the preceding examples
requires the following changes:
• Use the appropriate NCHAR constructor. NCHAR constructors mirror CHAR
constructors, such as the following:
NCHAR(String str, oracle.sql.CharacterSet charset)
• Although you have the option of using either toString() or getString()
to retrieve the underlying String instance from an NString instance, for
an NCHAR instance you must use the getString() method. When using
the NString type, the toString() method is used automatically for string
concatenation.
10-24
Chapter 10
Globalization Support in the Translator and Run Time
Note:
To use SQLJ to translate source created by native2ascii, ensure that the
JVM that invokes SQLJ has a file.encoding setting that supports some
superset of 7-bit ASCII. This is not the case with settings for EBCDIC or
Unicode encoding.
Standard input or standard output are used if you omit the input file or output file. Two
options are supported:
• -reverse (Reverse the conversion. Convert from Latin-1 or Unicode to native
encoding)
• -encoding <encoding>
For example:
% native2ascii -encoding SJIS Foo.sqlj Temp.sqlj
10-25
11
Performance and Debugging
This chapter discusses features, utilities, and tips to enhance performance of your
SQLJ application and to debug your SQLJ source code at run time. The following
topics are discussed:
• Performance Enhancement Features
• SQLJ Debugging Features
• SQLJ Support for Oracle Performance Monitoring
See Also:
Oracle Database JDBC Developer's Guide
Your application will likely benefit from the default Oracle-specific code generation.
The generated code will be optimized with direct calls to Oracle Java Database
Connectivity (JDBC) driver, eliminating the overhead of intermediate calls to the SQLJ
run time, which in turn would call JDBC.
See Also:
"Oracle-Specific Code Generation (No Profiles)"
11-1
Chapter 11
Performance Enhancement Features
Note:
The Oracle SQLJ implementation does not support batch fetches, which is
the fetching of sets of rows into arrays of values. However, you may be
able to use Oracle row prefetching to obtain some of the benefits of batch
fetching.
In addition to the preceding SQLJ performance enhancements, you can use optimizer
hints in the SQL operations within a SQLJ program, as you can in any Oracle SQL
operations.
The Oracle SQL implementation enables you to tune your SQL statements by using
"/*+" or "--+" comment notation to pass hints to Oracle SQL optimizer. The SQLJ
translator recognizes and supports these optimizer hints, passing them at run time as
part of your SQL statement.
You can also define cost and selectivity information for a SQLJ stored function, as
for any other stored function, using the extensibility features for SQL optimization in
Oracle Database 12c Release 2 (12.2). During SQL execution, the optimizer invokes
the cost and selectivity methods for the stored function, evaluates alternate strategies
for execution, and chooses an efficient execution plan.
See Also:
Oracle Database SQL Language Reference for more information
Note that using Oracle performance extensions in your code requires the following:
• Use one of Oracle JDBC drivers.
• Use the default Oracle-specific code generation, or customize profiles
appropriately.
For ISO standard code generation, 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 by your application
whenever you customize profiles with Oracle customizer, even if you do not actually
use Oracle extensions in your code.
11-2
Chapter 11
Performance Enhancement Features
The following is an example of setting the prefetch size to 20 by getting the default
execution context instance of the default connection context instance and calling the
setFetchSize() method:
DefaultContext.getDefaultContext().getExecutionContext().setFetchSize(20);
It is also possible to set the prefetch size directly on the underlying OracleConnection
object using the JDBC application programming interface (API), but in SQLJ this is
discouraged.
To specify the number of rows to prefetch for queries that use a given connection
context instance, use the underlying JDBC connection, cast to an OracleConnection
instance. Following is an example that sets the prefetch value to 20 for your default
connection:
((OracleConnection)DefaultContext.getDefaultContext().getConnection()).setDefault
RowPrefetch(20);
Also, please note that the prefetch size set on the SQLJ connection context overrides
the prefetch size set on the underlying JDBC connection.
Each additional connection context instance you use must be set separately, as
desired.The prefetch value needs to be setup on each individual connection context.
For example, if ctx is an instance of a declared connection context class, set its
prefetch value as follows:
((Connection)ctx.getConnection()).setDefaultRowPrefetch(20);
ctx.getExecutionContext().setFetchSize(20);
11-3
Chapter 11
Performance Enhancement Features
See Also:
Oracle Database JDBC Developer's Guide
For ISO code generation, SQLJ has its own statement caching mechanism through
functionality of the SQLJ run time. With ISO code, statement caching is controlled
through the Oracle customizer stmtcache option.
Note:
For Oracle-specific code generation, explicit caching is the only statement
caching mechanism that can be manipulated through SQLJ APIs. For the
discussion in this document, it will be referred to as SQLJ/explicit statement
caching.
In Oracle Database 12c Release 1 (12.1), the default statement cache size is set
to 5, provided the JDBC connection is being created by the connection context. If a
connection context is created using an already available JDBC connection or data
source, then the statement cache size will be set to that of the JDBC connection or the
data source.
11-4
Chapter 11
Performance Enhancement Features
Note:
setDefaultStmtCacheSize(int) affects the statement cache size only
for the connections that are created using the SQLJ connection contexts.
It does not affect the statement cache size for the connections that are
created using JDBC connections.
Consider the following two code snippets:
Example 1:
...
MyContext.setDefaultStmtCacheSize(10);
OracleConnection conn = DriverManager.getConnection(url, user,
passwd);
myctx = new MyContext(conn);
Example 2:
...
MyContext.setDefaultStmtCacheSize(10);
myctx = new MyContext(url, user, passwd,true);
In the preceding two examples, the statement cache size will be set
to 10 only in the second example. In the first example, the statement
cache size corresponding to this connection will not be affected because
the connection is created using the getConnection method of the
DriverManager interface from JDBC specification.
Note:
If SQLJ/explicit caching is already disabled, then setting the size to 0 leaves
it disabled. If it is already enabled, then setting the size to 0 leaves it
enabled, but renders it nonfunctional.
• int getStmtCacheSize()
This verifies whether SQLJ/explicit statement caching is enabled for the underlying
connection of the connection context. If so, it returns the current statement cache
size. It can also return either of the following integer constants:
static int STMT_CACHE_NOT_ENABLED
static int STMT_CACHE_EXCEPTION
11-5
Chapter 11
Performance Enhancement Features
You can explicitly disable SQLJ/explicit statement caching or JDBC implicit caching,
through JDBC connection APIs. Because SQLJ/explicit caching and JDBC implicit
caching use the same cache size, there might sometimes be reason to do so. The
following methods are available through the OracleConnection class:
• void setExplicitCachingEnabled(boolean)
• boolean getExplicitCachingEnabled()
• void setImplicitCachingEnabled(boolean)
• boolean getImplicitCachingEnabled()
You have access to these methods if you retrieve the OracleConnection instance from
within a SQLJ connection context instance.
See Also:
"SQLJ Connection Context and JDBC Connection Interoperability"
11-6
Chapter 11
Performance Enhancement Features
Note:
In SQLJ, JDBC implicit caching is disabled by default and remains disabled
unless you explicitly enable it through the setImplicitCachingEnabled()
method.
11-7
Chapter 11
Performance Enhancement Features
You can alter the statement cache size as desired, or effectively disable statement
caching with a cache size of 0, through the Oracle customizer stmtcache option. This
is set as -P-Cstmtcache=n, where n is an integer.
See Also:
"Oracle Customizer Statement Cache Size Option (stmtcache)"
If you use multiple connection context classes and, therefore, have multiple profiles,
you can set their statement cache sizes individually by running SQLJ (actually, the
customizer) separately for each profile.
At run time, the appropriate SQLJ profile determines the statement cache size for a
connection. This would be the profile that corresponds to the first connection context
class instantiated for this connection. Its statement cache size setting, if any, is
determined according to how you set the Oracle customizer stmtcache option when
you customized the profile. The run-time statement cache size for a connection is set
when the first statement on that connection is executed.
In this case, each of the following three code instructions has the effect that whenever
a new SQLJ connection context instance is subsequently created, it will not try to
enable SQLJ/explicit statement caching:
sqlj.runtime.ref.DefaultContext.setDefaultStmtCacheSize(0);
CtxtA.setDefaultStmtCacheSize(0);
CtxtB.setDefaultStmtCacheSize(0);
11-8
Chapter 11
Performance Enhancement Features
Note:
If a SQLJ connection context instance is created on an underlying
JDBC pooled connection, then SQLJ will not be able to change
the JDBC statement cache size. For Oracle-specific code, you
can retrieve the resulting exception through the connection context
getStmtCacheException() method. In this case, the desired JDBC
statement cache size must be set explicitly on the underlying physical
connections. For data sources, the cache size is set through vendor-specific
data source attributes.
SQLJ/explicit caching and JDBC implicit caching functionality have different semantics
and behaviors. As noted earlier, SQLJ statement caching applies only to single
statements used repeatedly, such as in a loop or through repeated calls to the same
method. Consider the following example:
...
#sql { same SQL operaton }; // occurrence #1
...
Java code
...
#sql { same SQL operaton }; // occurrence #2
...
Java code
...
#sql { same SQL operaton }; // occurrence #3
...
Assume the three SQL operations are identical, including white space.
SQLJ caching would consider these three occurrences of the same SQL operation
to be three different statements. They will occupy three separate slots in the cache.
JDBC implicit caching, however, would recognize these as identical statements, using
only a single cache slot for all three. The statement would be reused for occurrence #2
and occurrence #3.
11-9
Chapter 11
Performance Enhancement Features
Note:
Be aware of the following for update batching:
• You must use the default Oracle-specific code generation or, for ISO
code generation, customize your application with Oracle customizer.
• It is highly advisable to disable auto-commit mode. This gives you control
of what to commit and what to roll back in case of an error during batch
execution.
11-10
Chapter 11
Performance Enhancement Features
or:
...
ExecutionContext ec = new ExecutionContext();
ec.setBatching(false);
...
Note:
The setBatching() method does not affect an existing statement batch.
Neither enabling nor disabling update batching causes an existing batch to
be executed or canceled.
11-11
Chapter 11
Performance Enhancement Features
Note:
It is important to be aware of what happens when an exception occurs in the
middle of a batch execution.
Use the executeBatch() method of the execution context instance to explicitly execute
an update batch. This method returns an int array of update counts.
Note:
If you invoke executeBatch() when the execution context instance has no
pending batch, then the method returns null.
11-12
Chapter 11
Performance Enhancement Features
...
/* Statements in the following loop will be placed in a batch */
double[] sals = ...;
String[] empnos = ...;
for (int i = 0; i < empnos.length; i++)
{
#sql [ec] { UPDATE employees SET salary = :(sals[i]) WHERE employee_id = :
(empnos[i]) };
}
To obtain the update count array for a batch executed implicitly, invoke the
getBatchUpdateCounts() method of the execution context instance. This returns the
update counts for the last batch to be executed successfully in this execution context
instance. The following code statement could be inserted after the SELECT and after the
last UPDATE:
int[] updateCounts = ec.getBatchUpdateCounts();
Note:
If no update batch has been executed successfully for the execution context
instance, then getBatchUpdateCounts() returns null.
Canceling a Batch
To cancel the batch that is pending in an execution context, use the cancel() method
of the execution context instance. You can, for example, cancel a batch that has been
executed, but not yet committed, in the event that an exception occurred during batch
execution. Following is an example:
...
ExecutionContext ec = new ExecutionContext();
ec.setBatching(true);
...
double[] sals = ...;
String[] empnos = ...;
for (int i = 0; i < empnos.length; i++)
{
#sql [ec] { UPDATE employees SET salary = :(sals[i]) WHERE employee_id = :
11-13
Chapter 11
Performance Enhancement Features
(empnos[i]) };
if (!check(sals[i], empnos[i])) //assume "check" is a user-supplied function
{
ec.cancel();
throw new SQLException("Process canceled.");
}
}
try
{
int[] updateCounts = ec.executeBatch();
} catch ( SQLException exception) { ec.cancel(); }
...
When you cancel a batch, the next batchable statement will start a new batch.
Note:
After a batch has been executed, either explicitly or implicitly, the array of values
returned by executeBatch() or getBatchUpdateCounts() indicates only whether the
statements executed successfully. There is an array element for each batched
statement. In accordance with the JDBC 2.0 specification, a value of -2 for an array
11-14
Chapter 11
Performance Enhancement Features
element indicates that the corresponding statement completed successfully, but that
the number of rows it affected is unknown.
Checking all the array values after execution of a batch would not be meaningful. As
currently implemented, the only useful test of this array would be to verify the number
of statements that were in the batch prior to execution, by checking the number of
elements in the array after a successful execution (essentially, after a batch execution
that does not produce an exception).
Note that the update counts array is not modified as statements are batched, only as
the batch is executed.
This loop is executed 20 times, with the statements being batched and the batch being
executed during the 11th time through the loop, before the 11th statement would be
added to the batch. Note that the batch would not be executed a second time in the
loop, however. When your application exits the loop, the last ten statements would still
be in the batch and would not be executed until another statement is encountered or
you execute the batch explicitly.
You can use two special static int constants of the ExecutionContext class as input
to the setBatchLimit() method:
• AUTO_BATCH: Enables the SQLJ run time to determine the batch limit.
• UNLIMITED_BATCH (default): Specifies that there is no batch limit.
For example:
...
ExecutionContext ec = new ExecutionContext();
ec.setBatching(true);
ec.setBatchLimit(ExecutionContext.AUTO_BATCH);
...
or:
ec.setBatchLimit(ExecutionContext.UNLIMITED_BATCH);
...
To check the current batch limit, use the getBatchLimit() method of the execution
context instance.
11-15
Chapter 11
Performance Enhancement Features
Note:
This example assumes that the two UPDATE statements are completely
independent of each other. Do not batch interdependent statements in
different execution contexts because you cannot completely assure the order
in which they will be executed.
An alternative is to use a single execution context and separate loops so that all the
EMP1 updates are batched and executed prior to the EMP2 updates:
...
ExecutionContext ec = new ExecutionContext();
ec.setBatching(true);
...
double[] sals = ...;
String[] empnos = ...;
for (int i = 0; i < empnos.length; i++)
{
#sql [ec] { UPDATE emp1 SET sal = :(sals[i]) WHERE empno = :(empnos[i]) };
}
for (int i = 0; i < empnos.length; i++)
{
#sql [ec] { UPDATE emp2 SET sal = :(sals[i]) WHERE empno = :(empnos[i]) };
}
ec.executeBatch();
...
This example executes the first batch implicitly and the second batch explicitly.
11-16
Chapter 11
Performance Enhancement Features
instance has an implicit execution context instance. For example, you can access the
implicit execution context instance of the default connection as follows:
DefaultContext.getDefaultContext().getExecutionContext().setBatching(true);
...
double[] sals = ...;
String[] empnos = ...;
for (int i = 0; i < empnos.length; i++)
{
#sql { UPDATE employees SET salary = :(sals[i]) WHERE employee_id = :
(empnos[i]) };
}
// implicitly execute the batch and commit
#sql { COMMIT };
or:
#sql { ROLLBACK };
This is another reason that you should always commit or roll back changes using
#sql syntax, which cleans up both SQLJ resources and JDBC resources.
• When a batch is implicitly executed as a result of an unbatchable or incompatible
statement being encountered, the batch is executed before the unbatchable
or incompatible statement is executed, but after the input parameters of that
statement have been evaluated and passed to the statement.
• If you no longer intend to use a particular batch-enabled execution context
instance, then explicitly execute or cancel its pending batch to free resources.
11-17
Chapter 11
Performance Enhancement Features
• If the batch where the exception occurred was executed implicitly as the result
of another (unbatchable or incompatible) statement being encountered, that
statement is not executed.
Note:
Presumably you have disabled auto-commit mode when using update
batching. This gives you commit/rollback control in case of an error during
batch execution.
When an exception occurs during batch execution under JDBC 2.0 or later, it
is typically an instance of the standard java.sql.BatchUpdateException class, a
subclass of the java.sql.SQLException class. The BatchUpdateException class has
a getUpdateCounts() method that, for batched statements successfully executed
before the exception occurred, returns an array of update counts equivalent to what
would be returned by the executeBatch() or getBatchUpdateCounts() method of the
ExecutionContext class.
11-18
Chapter 11
Performance Enhancement Features
11-19
Chapter 11
Performance Enhancement Features
specified. If there is no source code hint or appropriate default size, then maximum
resources are allocated according to the JDBC implementation.
When your application executes, the parameter sizes are registered through calls to
the defineParameterType() and registerOutParameter() methods available in the
Oracle JDBC statement classes.
Note:
If you do not enable the parameter definition flag, then parameter size
defaults and source code hints will be ignored and maximum or default
resources will be allocated according to the JDBC implementation.
The size is in bytes. Hints are ignored if the optparams flag is disabled.
You can override the default parameter size, without specifying a new size (leaving
size allocation to the JDBC implementation), as follows:
/*()*/
Here is an example:
byte[] hash;
String name=Tyrone;
String street=2020 Meryl Street;
String city=Wichita;
String state=Kansas;
String zipcode=77777;
#sql hash = { /* (5) */ VALUES (ADDR_HASH(:name /* (20) */, :street /* () */,
:city, :state, :INOUT zipcode /* (10) */ )) };
A hint for a result expression, such as the result expression hash in the example, must
be the first item appearing inside the brackets of the SQLJ statement, as shown. Hints
for input and output host variables must immediately follow the variables, as shown.
11-20
Chapter 11
SQLJ Debugging Features
Note:
If any parameter size is altered such that its actual size exceeds its
registered size at run time, then a SQL exception will be thrown.
Note:
If you are translating in the server, then class schema objects created during
server-side translation automatically reference line numbers that map to the
SQLJ source code. This is equivalent to enabling the -linemap option when
you translate on a client.
11-21
Chapter 11
SQLJ Support for Oracle Performance Monitoring
See Also:
"AuditorInstaller Customizer for Debugging"
11-22
Chapter 11
SQLJ Support for Oracle Performance Monitoring
11-23
Chapter 11
SQLJ Support for Oracle Performance Monitoring
See Also:
"SQLJ Run-Time Commands and Properties File Settings for DMS"
For a client-side SQLJ program, you can use both DMS statistics and server-side
tracing. For example, from DMS you can get the total time required for a #sql
statement that consists of a query, then from server-side tracing you can find out how
much of that time was actually spent executing the SQL query in the server.
Note:
Note:
A setting of -instrument is equivalent to -instrument=true. A setting of
-instrument=false (the default) disables instrumentation.
11-24
Chapter 11
SQLJ Support for Oracle Performance Monitoring
11-25
Chapter 11
SQLJ Support for Oracle Performance Monitoring
Note:
A setting of sqlmonitor.dms=false is not currently supported.
Note:
For sysurl, sysuser, and syspassword, default values are according to
the user, password, and url values supplied to SQLJ, either through the
SQLJ command line or through the SQLJ properties file.
11-26
Chapter 11
SQLJ Support for Oracle Performance Monitoring
oracle.sqlj.runtime.sqlmonitor.SQLMonitor.close();
}
catch( Throwable e ) { ... }
Metrics:
– value: A string indicating the connection context type
• Sensor name: SQLString
/SQLJ/application_name/module/class/linenum/SQLString
Metrics:
– value: A string consisting of the SQL statement
This is the exact string that is passed to JDBC, including any transformations
made from the original #sql statement.
• Sensor name: Execute
/SQLJ/application_name/module/class/linenum/Execute
Metrics:
– time: The total time, in milliseconds, of all the executions of the JDBC
execute() method for this statement
If the statement executes five times, for example, then time would be the total
time spent in the execute() method for the five executions.
– completed: The number of executions completed (such as 5)
– minTime: The shortest time of any single execution
– maxTime: The longest time of any single execution
– avg: The average execution time, which is time divided by completed
– active: The number of threads executing the statement at the end of program
execution, typically 0.
– maxActive: The maximum number of threads that executed the statement
during program execution
11-27
Chapter 11
SQLJ Support for Oracle Performance Monitoring
Metrics:
– value: The total execution time in the server, in milliseconds, for all executions
of this SQL statement
– count: The number of executions completed
– minValue: The shortest time of any single execution
– maxValue: The longest time of any single execution
• Sensor name: ServerFetch
/SQLJ/application_name/module/class/linenum/ServerFetch
Metrics:
– value: The total fetch time in the server, in milliseconds, for all executions of
this SQL statement
– count: The number of executions completed
– minValue: The shortest time of any single execution
– maxValue: The longest time of any single execution
• Sensor name: ServerParse
/SQLJ/application_name/module/class/linenum/ServerParse
Metrics:
– value: The total time spent parsing the SQL statement in the server, in
milliseconds, for all executions of this SQL statement
– count: The number of executions completed
– minValue: The shortest time of any single execution
– maxValue: The longest time of any single execution
• Sensor name: Next
/SQLJ/application_name/module/class/linenum/Next
Metrics:
– time: The total time, in milliseconds, spent in the next() method of the result
set iterator for all executions of this SQL statement
– completed: The number of executions completed (such as 5)
– minTime: The shortest time of any single execution
– maxTime: The longest time of any single execution
– avg: The average execution time, which is time divided by count.
11-28
Chapter 11
SQLJ Support for Oracle Performance Monitoring
– active: The number of threads executing the statement at the end of program
execution, typically 0.
– maxActive: The maximum number of threads that executed the statement
during program execution
Note:
Ensure that dms.jar is in your classpath.
Note:
If you run the SQLJ translator again, then app.properties is overwritten and
you will lose any changes you made.
Sample Statistics
The sqlmonitor.dms=true setting specifies that monitoring statistics are to be
delivered to DMS. Given the sqlmonitor.dumpfile value, the DMS tool writes the
statistics to the ./a/b/c/app.mtr file when you compile and run the program.
11-29
Chapter 11
SQLJ Support for Oracle Performance Monitoring
#sql
{
DECLARE
n NUMBER;
s NUMBER;
BEGIN
n := 0;
s := 0;
WHILE n < 100 LOOP
n := n + 1;
s := s + :IN (indx++);
END LOOP;
:OUT total := s;
END;
};
And here is a segment of statistics from app.mtr, relating to the preceding code
example and showing the execution time and server execution times:
SQLString.value: DECLARE n NUMBER; s NUMBER;
BEGIN n := 0; s := 0; WHILE n < 100 LOOP
n := n + 1;
s := s + :1 ;
END LOOP; :2 := s; END; statement SQL string
ServerExecute.maxValue: 20.0 server_execute_time
ServerExecute.minValue: 20.0 server_execute_time
ServerExecute.count: 0 ops
ServerExecute.value: 20.0 server execute time
ServerFetch.maxValue: 0.0 server_fetch_time
ServerFetch.minValue: 0.0 server_fetch_time
ServerFetch.count: 0 ops
ServerFetch.value: 0.0 server fetch time
ServerParse.maxValue: 0.0 server_parse_time
ServerParse.minValue: 0.0 server_parse_time
ServerParse.count: 0 ops
ServerParse.value: 0.0 server parse time
193.5
ContextType.value: class sqlj.runtime.ref.DefaultContext
statement connection context
Execute.maxActive: 1 threads
Execute.active: 0 threads
Execute.avg: 37.0 msecs
Execute.maxTime: 37 msecs
Execute.minTime: 37 msecs
Execute.completed: 1 ops
Execute.time: 37 msecs
These statistics indicate that the total execution time at the JDBC client was 37
milliseconds (in one execution), while the execution time in the server was 20
milliseconds.
....
Iter iter;
#sql iter = { select first_name from employees};
11-30
Chapter 11
SQLJ Support for Oracle Performance Monitoring
while (iter.next())
{
System.out.println(iter.ename());
}
For iterators, DMS collects the execution time for the next() operation. Here is a
sample DMS result for the iterator type Iter:
Iter
Next.time: 5 msecs
This shows that the total time spent on the next() operation while iterating through the
Iter instance was 5 milliseconds.
This shows that the context has a statement cache size of five statements. Altogether,
seven SQL statements are executed.
11-31
A
Customization and Specialized
Customizers
Profiles and profile customization are introduced in "SQLJ Profiles". 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
Note:
If you use the default Oracle-specific code generation (-codegen=oracle),
the discussion in this appendix does not pertain to your application.
A-1
Appendix A
More About Profiles
For profiles to have binary portability, SQLJ industry-standard requirements have been
met in the Oracle SQLJ implementation.
Note:
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.
As discussed in "Code Generation", profile file names for application Foo are of the
form:
Foo_SJProfilen.ser
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".
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.
A-2
Appendix A
More About Profile Customization
Note that in the profile entry, the host variable is replaced by JDBC syntax (the
question mark).
Note:
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".
A-3
Appendix A
More About Profile Customization
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.
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.
A-4
Appendix A
More About Profile Customization
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.
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:
A-5
Appendix A
More About Profile Customization
such as creating new entries that are equivalent to the original entries but are modified
to use features of your particular database.
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.
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.
A-6
Appendix A
Customization Options and Choosing a Customizer
A-7
Appendix A
Customization Options and Choosing a Customizer
or:
-P-option=true
Boolean options are disabled by default, but you can explicitly disable them with:
-P-option=false
A-8
Appendix A
Customization Options and Choosing a Customizer
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<=true|false>
A-9
Appendix A
Customization Options and Choosing a Customizer
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
A-10
Appendix A
Customization Options and Choosing a Customizer
Note:
Visit the Sun site more information about JAR manifest file.
For information about JAR files and the JAR utility, see one of the following Web sites:
http://www.javasoft.com/products/jdk/1.2/docs/guide/jar/index.html
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.
A-11
Appendix A
Customization Options and Choosing a Customizer
-P-help <-P-customizer=customizer_class>
A-12
Appendix A
Customization Options and Choosing a 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.
Note:
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.
A-13
Appendix A
Customization Options and Choosing a Customizer
The password can also be set with the user option, as described in "Customization
User Option (user)".
Note:
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.
The URL can also be set with the user option, as described in "Customization User
Option (user)".
Note:
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.
A-14
Appendix A
Customization Options and Choosing a Customizer
-P-url=jdbc:oracle:oci:@
A-15
Appendix A
Customization Options and Choosing a Customizer
Note:
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.
You also cannot use more than one of print, debug, or verify
simultaneously.
A-16
Appendix A
Customization Options and Choosing a Customizer
Use the following command, if you want to see all the customizer options:
% sqlj -P-print *.ser
#sql { commit }
setFixedchar is disabled
Ncharconv is disabled
………
A-17
Appendix A
Customization Options and Choosing a Customizer
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".
Note:
For online semantics-checking of the profile, you must also use the
customizer harness user, password, and url options.
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=HR -P-url=jdbc:oracle:oci:@ Foo_SJProfile0.ser
Bar_SJProfile0.ser
Password: password
(You must also specify profiles, and typically customizer harness connection options,
in the SQLJ command line.)
Properties file example is:
profile.verify
A-18
Appendix A
Customization Options and Choosing a Customizer
-P-C
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
A-19
Appendix A
Customization Options and Choosing a Customizer
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 <...SQLJ options...> -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
Note:
If customization does not take place because a valid previous customization
is detected, the compat option reports compatibility regardless.
A-20
Appendix A
Customization Options and Choosing a Customizer
false
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<=true|false>
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".
A-21
Appendix A
Customization Options and Choosing a Customizer
Note:
You can use the SQLJ translator -optcols option instead. This sets the
customizer option automatically. For Oracle-specific code generation, which
uses no profiles, you must use the translator option instead.
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
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=HR@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=HR@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=HR@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".
A-22
Appendix A
Customization Options and Choosing a Customizer
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:
% sqlj -P-Csummary MyApp_SJProfile*.ser
For general information about the summary flag, see that section under "Overview of
Customizer-Specific Options".
Command-line syntax is:
-P-Coptcols<=true|false>
Note:
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.)
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
A-23
Appendix A
Customization Options and Choosing a Customizer
This flag is disabled by default, but you can also disable it explicitly. Disable it on the
command line as follows:
-P-Coptparams=false
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.
For an overview of parameter size definitions and a discussion of source code hints,
see "Parameter Size Definitions".
A-24
Appendix A
Customization Options and Choosing a Customizer
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.)
That section also has important additional conceptual and syntax
information. Functionality of the two options is equivalent.
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),...
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
Note:
If at run time, the actual size exceeds the registered size of any parameter,
run-time errors will occur.
A-25
Appendix A
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.)
• 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)" for an example.
In this example, the MyApp profiles will be created and customized and their SQL
transformations displayed in a single running of SQLJ.
A-26
Appendix A
Customization Options and Choosing a Customizer
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: <<<NEW SQL>>> #sql {BEGIN ? := VALUES(tkjsSET_f1); END};
Note:
If customization does not take place because a valid previous customization
is detected, the showSQL option shows SQL transformations regardless.
A-27
Appendix A
Customization Options and Choosing a Customizer
Note:
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.
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 <...SQLJ options...> -P-Cstmtcache=15 MyApp.sqlj
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
A-28
Appendix A
Customization Options and Choosing a Customizer
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 <...SQLJ options...> -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.
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: Info: Oracle features used:
MyApp_SJProfile0.ser: Info: * oracle.sql.NUMBER: 2
MyApp_SJProfile0.ser: Info: * oracle.sql.DATE: 2
MyApp_SJProfile0.ser: Info: * oracle.sql.CHAR: 2
MyApp_SJProfile0.ser: Info: * 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
Note:
If customization does not take place because a valid previous customization
is detected, the summary option produces a summary regardless.
A-29
Appendix A
JAR Files for Profiles
A-30
Appendix A
JAR Files for Profiles
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.
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:
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
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
A-31
Appendix A
SQLCheckerCustomizer for Profile Semantics-Checking
profile. It accomplishes this by matching the names in the manifest with the names you
specify in your text file.
Note:
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:
For online semantics-checking of the profile, you must also specify
connection parameters using the customizer harness connection options.
A-32
Appendix A
SQLCheckerCustomizer for Profile Semantics-Checking
The verify option results in the customizer harness instantiating and invoking the
following class:
sqlj.runtime.profile.util.SQLCheckerCustomizer
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.
A-33
Appendix A
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
A-34
Appendix A
AuditorInstaller Customizer for Debugging
A-35
Appendix A
AuditorInstaller Customizer for Debugging
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".)
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)" for information about how to specify the
layer at which to install an auditor.
The debug option results in the customizer harness instantiating and invoking the
following class:
% sqlj.runtime.profile.util.AuditorInstaller
A-36
Appendix A
AuditorInstaller Customizer for Debugging
A-37
Appendix A
AuditorInstaller Customizer for Debugging
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 )
oracle.sqlj.runtime.OraRTStatement@3 . setMaxRows returned
oracle.sqlj.runtime.OraRTStatement@3 . setMaxFieldSize ( 3000 )
oracle.sqlj.runtime.OraRTStatement@3 . setMaxFieldSize returned
oracle.sqlj.runtime.OraRTStatement@3 . setQueryTimeout ( 1000 )
oracle.sqlj.runtime.OraRTStatement@3 . setQueryTimeout returned
oracle.sqlj.runtime.OraRTStatement@3 . setBigDecimal ( 1 , 5 )
oracle.sqlj.runtime.OraRTStatement@3 . setBigDecimal returned
oracle.sqlj.runtime.OraRTStatement@3 . setBoolean ( 2 , false )
oracle.sqlj.runtime.OraRTStatement@3 . setBoolean returned
oracle.sqlj.runtime.OraRTStatement@3 . executeRTQuery ( )
oracle.sqlj.runtime.OraRTStatement@3 . executeRTQuery returned
oracle.sqlj.runtime.OraRTResultSet@6
oracle.sqlj.runtime.OraRTStatement@3 . getWarnings ( )
oracle.sqlj.runtime.OraRTStatement@3 . getWarnings returned null
oracle.sqlj.runtime.OraRTStatement@3 . executeComplete ( )
oracle.sqlj.runtime.OraRTStatement@3 . executeComplete returned
oracle.sqlj.runtime.OraRTResultSet@6 . next ( )
oracle.sqlj.runtime.OraRTResultSet@6 . next returned true
oracle.sqlj.runtime.OraRTResultSet@6 . getBigDecimal ( 1 )
oracle.sqlj.runtime.OraRTResultSet@6 . getBigDecimal returned 5
oracle.sqlj.runtime.OraRTResultSet@6 . getDate ( 7 )
oracle.sqlj.runtime.OraRTResultSet@6 . 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.
Note:
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.
• 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.
A-38
Appendix A
AuditorInstaller Customizer for Debugging
• 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-39
Appendix A
AuditorInstaller Customizer for Debugging
-P-Clog=log_file
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"
A-40
Appendix A
AuditorInstaller Customizer for Debugging
oracle.sqlj.runtime.OraRTResultSet@6 . getDate ( 7 )
oracle.sqlj.runtime.OraRTResultSet@6 . getDate returned 1998-03-28
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<=true|false>
A-41
Appendix A
AuditorInstaller Customizer for Debugging
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-42
Index
A BigDecimal
support, 6-35
access mode settings (transactions), 8-46 binary portability of profiles, 4-37
alternative environments, support, 9-66 bind-by-identifier option (sqlj -bind-by-identifier),
applets, using SQLJ, 3-14 9-54
arrays BLOB support, 6-24
as iterator columns, 6-7 BOOLEAN type (PL/SQL), 6-8
VARRAYs, 7-4
assignment statements (SET), 5-44
assumptions, environment, 2-1
C
AuditorInstaller C prefix (sqlj -C-x), 9-51
command-line examples, A-42 cache option (sqlj -cache), 9-59
customizer for debugging, A-35 caching online checker results, 9-59
invoking, A-36 caching statements, 11-3
options, A-38 CALL syntax for stored procedures, 5-45
runtime output, A-37 calling stored functions, 5-46
auditors in profiles for debugging, A-36 calling stored procedures, 5-45
auto-commit calls to runtime, generated, 10-3
modifying in existing connection, 4-23 case-sensitive SQL UDT names, 7-9
specifying in new connection, 4-22 cause/action output for errors, 9-35
CHAR comparisons, blank padding, 9-43, A-26
B character encoding
command line example, 10-18
backup option (customizer harness), A-9 for messages, 10-18
backward compatibility for source, 10-18
Oracle SQLJ, general, 2-3 overview, 10-15
to Oracle8i, 6-9 setting at runtime, 10-24
batch updates using native2ascii, 10-24
batch limit, 11-10 check source name against. public class, 9-66
batchable and compatible statements, 11-10 check sources, expand resolution search, 9-54
batching incompatible statements, 11-10 checker option (SQLCheckerCustomizer), A-34
canceling a batch, 11-10 checkfilename option (sqlj -checkfilename), 9-66
cautions, 11-10 checksource option (sqlj -checksource), 9-54
enabling and disabling, 11-10 classpath and path, 2-4
error conditions during execution, 11-10 classpath option (sqlj -classpath), 9-18
explicit and implicit batch execution, 11-10 clauses, SQLJ executable statements, 5-9
overview, 11-10 CLOB support, 6-24
update counts, 11-10 CLOSE_CONNECTION, 8-51
using implicit execution contexts, 11-10 close() method (DefaultContext), 4-12
with respect to recursive call-ins, 11-10 close() method (ExecutionContext), 8-32
BetterDate (custom Java class), 7-12 close() method (Oracle class), 4-11, 4-12
BFILEs code generation
as stored function results, 6-24 general information, 10-3
BFILE support, 6-24 Oracle-specific vs. ISO standard, 4-34
translator -codegen option, 9-43
Index-1
Index
Index-2
Index
Index-3
Index
Index-4
Index
I J
IDE SQLJ integration, 3-17 J prefix (sqlj -J-x), 9-51
IMPLEMENTS clause jar file digests option, customization, A-10
in connection context declarations, 8-8 jar files for profiles, A-30
in iterator declarations, 8-37 Java bind expressions (dynamic SQL), 8-55
syntax, 5-4 Java properties, getProperty(), 10-24
importing required classes, 4-26 Java VM
informational messages, translator, 10-9 classpath option, 9-18
input to translator, 3-8 options through SQLJ, 9-51
installation and configuration verification, 2-4 specifying name, 9-66
instrument option (sqlj -instrument), 9-40 JavaBeans for SQLJ connections, 8-15
instrumenting class file (linemap), 9-39 javac compatibility, 9-2
interoperability with JDBC JDBC 2.0
connection contexts and connections, 8-48 support for LOB types, 6-22
iterators and result sets, 8-52 support for weakly typed Struct, Ref, Array,
isolation level settings (transactions), 8-46 7-37
iterators types supported, 6-6
accessing named iterators, 5-33 JDBC connection methods (transactions), 8-47
accessing positional iterators, 5-36 JDBC driver registration option (sqlj -driver), 9-26
array columns, 6-7 JDBC drivers
as host variables, 5-39 Oracle drivers, 4-1
as iterator columns (nested), 5-42 select for translation, 4-4
as stored function returns, 5-47 select/register for customization, A-15
commit/rollback effect, 4-24 select/register for runtime, 4-4
concepts, 5-29 verify, 2-8
converting from result sets, 8-52 JDBC interoperability
converting to result sets, 8-52 connection contexts and connections, 8-48
declarations, 5-3 iterators and result sets, 8-52
declaring named iterators, 5-33 JDBC vs. SQLJ, sample application, 3-11
declaring positional iterators, 5-36 jdblinemap option (sqlj -jdblinemap), 9-35
declaring with IMPLEMENTS clause, 8-37 JDeveloper
extending, 8-38 debugging with, 11-22
general steps in using, 5-31 SQLJ integration, 3-17
instantiating/populating named iterators, 5-33 JDK
instantiating/populating positional iterators, supported versions, 2-2
5-36 JNDI
iterator class functionality, 8-36 name of default data source, 8-10
named vs. positional, 5-32 use for data sources, connections, 8-10
Index-5
Index
Index-6
Index
Index-7
Index
Index-8
Index
Index-9
Index
Index-10
Index
vm option (sqlj -vm), 9-66 weakly typed custom Java classes, 7-2
weakly typed iterators, 8-38
WHERE CURRENT OF, 6-29
W WHERE CURRENT OF clause, 6-31
warn option (SQLCheckerCustomizer), A-35 Windows, SQLJ development in, 3-17
warn option (sqlj -warn), 9-35 WITH clause syntax, 5-5
warning messages, translator, 10-9 wrapper classes for null-handling, 4-16
warnings, translator, enabling/disabling, 9-35
weak object/collection types
restrictions, 7-38
support, 7-37
Index-11