|Oracle8i SQLJ Developer's Guide and Reference
The following subsections summarize the operations executed by the SQLJ translator during a translation.
In this first phase of SQLJ translation, a SQLJ parser and a Java parser are used to process all of the source code and check syntax.
As the SQLJ translator parses the
.sqlj file, it invokes a Java parser to check the syntax of Java statements and a SQLJ parser to check the syntax of SQLJ constructs (anything preceded by
#sql). The SQLJ parser also invokes the Java parser to check the syntax of Java host variables and expressions within SQLJ executable statements.
The SQLJ parser checks the grammar of SQLJ constructs according to the SQLJ language specification. It does not check the grammar of the embedded SQL operations, however. SQL syntax is not checked until the semantics-checking step.
This syntax-check will discover errors such as missing semi-colons, mismatched curly braces, and obvious type mismatches (such as multiplying a number by a string).
If the parsers discover any syntax errors or type mismatches during this phase, the translation is aborted and the errors are reported to the user.
Once the SQLJ application source code is verified as syntactically correct, the translator enters into the semantics-checking phase and invokes a semantics-checker according to user option settings. The semantics-checker verifies the validity of Java types in SQL operations (result expressions or host expressions) and optionally connects to a database to check compatibility between Java types and SQL types.
-user option specifies online checking, and the
-url options finish specifying the database connection if the password and URL were not specified in the
-user option. The
-online option specifies which checker to use. The default is a checker front end called
OracleChecker, which chooses the most appropriate checker according to whether you have enabled online checking and which JDBC driver you are using. For more information, see "Connection Options" and "Semantics-Checking Options".
The following two tasks are always performed during semantics-checking, whether offline or online:
This includes examining the SQLJ source files being translated, any
.java files that were also entered on the command-line, and any imported Java classes that can be found through the
CLASSPATH. SQLJ examines whether and how stream types are used in
CAST statements, what Java types are used in iterator columns or INTO-lists, what Java types are used as input host variables, and what Java types are used as output host variables.
SQLJ also processes
SET statements syntactically.
Any Java expression in a SQLJ executable statement must have a Java type that is valid for the given situation and usage. For example, in the following statement:
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.
And in the following example:
newSal is a variable (as opposed to a field), then an error is generated if
newSal was not previously declared. In any case, an error is generated if it cannot be assigned to a valid Java type or its Java type cannot be used in a SQL statement (a
java.util.Vector, for example).
Remember that 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.
INSERTso that SQLJ knows what kind of operation it is. For example, the following statement will generate an error:
The following two tasks are performed only if online checking is enabled:
In the process of doing this, SQLJ verifies that the schema objects 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 handle null data. (Nullability is not checked for stored procedure and function output parameters and return values, however.)
If the semantics-checker discovers any syntax or semantics errors during this phase, then the translation is aborted and the errors are reported.
Oracle supplies Oracle-specific offline checkers, a generic offline checker, Oracle-specific online checkers, and a generic online checker. For more information about checkers, see "Offline Semantics-Checker (-offline)" and "Online Semantics-Checker (-online)".
The generic checkers assume you are using only standard SQL92 and standard JDBC features. Oracle recommends that you use the Oracle-specific checkers when using an Oracle database.
The following is not checked against the database during online semantics-checking:
.sqlj application source file, the SQLJ translator generates a
.java file and at least one profile (either in
.class files). A
.java file is created for your translated application source code, class definitions for private iterators and connection contexts you declared, and a profile-keys class definition generated and used internally by SQLJ.
Profiles and a profile-keys class are not generated if you do not use any SQLJ executable statements in your code.
Once your application source code has passed the preceding syntax and semantics checks, it is translated and output to a
.java file. SQLJ executable statements are replaced by calls to the SQLJ runtime, which in turn contains calls to the JDBC driver to access the database.
.java file contains all of your generic Java code, your private iterator class and connection context class definitions, and calls to the SQLJ runtime.
For convenience, generated
.java files also include a comment for each of your
#sql statements, repeating the statement in its entirety for reference.
.java file will have the same base name as the input
.sqlj file, which would be the name of the public class defined in the
.sqlj file (or the first class defined if there are no public classes). For example,
Foo.sqlj defines class
Foo, and the generated file will be
The location of the generated
.java file depends on how the SQLJ
-dir option is set. By default, the
.java file will be placed in the directory of the
.sqlj input file. (See "Output Directory for Generated .java Files (-dir)" for more information.)
During translation, SQLJ generates a profile-keys class that it uses internally during runtime to load and access the serialized profile. This class contains mapping information between the SQLJ runtime calls in your translated application and the SQL operations placed in the serialized profile. It also contains methods to access the serialized profile.
This 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:
For example, translating
Foo.sqlj defines the following profile-keys class in the generated
If your application is in a package, this is reflected appropriately. For example, translating
Foo.sqlj that is in the package
a.b defines the following class:
SQLJ generates profiles that it uses to store information about the SQL operations found in the input file. A profile is generated for each connection context class that you use in your application. It describes the operations to be performed using instances of the associated connection context class, such as SQL operations to execute, tables to access, stored procedures and functions to call.
Profiles are generated in
.ser serialized resource files. If, however, you enable the SQLJ
-ser2class option, they are automatically converted to
.class files as part of the translation.
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:
n is a unique number, starting with 0, for each profile generated for a particular
.sqlj input file.
Again using the example of the input file
Foo.sqlj, if two profiles are generated, then they will have the following base names (presuming no package):
Foo.sqlj is in the package
a.b, then the profile base names will be:
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:
(Or they will be named
Foo_SJProfile1.class if you enable the
-ser2class option. If you choose this option, the conversion to
.class takes place after the customization step below.)
The location of these files depends on how the SQLJ
-d option is set, which determines where all generated
.class files are placed. The default for this option is to use the same directory as the
-dir option, which determines where generated
.java files are placed. (See "Output Directory for Generated .ser and .class Files (-d)" for more information.)
In a later step in the SQLJ process, your profiles are customized for use with your particular database. See "Profile Customization".
#sql statements are replaced by calls to the SQLJ runtime, these calls implement the following steps:
setXXX()methods of the statement object).
executeQuery()method of the statement object).
getXXX()methods of the statement object).
A SQLJ runtime uses SQLJ statement objects that are similar to JDBC statement objects, although a particular implementation of SQLJ may or may not employ JDBC statement classes directly. SQLJ statement classes add functionality that is particular to SQLJ. For example:
float, which cannot take null values.
After code generation, SQLJ invokes the Java compiler to compile the generated
.java file. This produces a
.class file for each class you defined in your application, including iterator and connection context declarations, as well as a
.class file for the generated profile-keys class (presuming your application uses SQLJ executable statements). Any
.java files you specified directly on the SQLJ command line (for type-resolution, for example) are compiled at this time as well.
In the example used in "Code Generation", the following
.class files would be produced in the appropriate directory (given package information in the source code):
.classfile for each additional class you defined in
.classfile for each iterator and connection context class you declared in
Foo.sqlj(whether public or private)
.class files generated by the compiler and profiles generated by SQLJ (whether
.class) will be located in the same directory, SQLJ passes its
-d option to the Java compiler. If the
-d option is not set, then
.class files and profiles are placed in the same directory as the generated
.java file (which is placed according to the
-dir option setting).
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, SQLJ and the compiler will use the setting in the Java VM
By default, SQLJ invokes the standard
javac compiler of the Sun Microsystems JDK, but other compilers can be used instead. You can request that an alternative Java compiler be used by setting the SQLJ
If you are using the SQLJ
For information about compiler-related SQLJ options, see the following:
After Java compilation, the generated profiles (which contain information about your embedded SQL instructions) are customized so that your application can work efficiently with your database and use vendor-specific extensions.
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 by SQLJ option settings.
During customization, profiles are updated in two ways:
Without customization, you can access and use only standard JDBC types.
For example, the Oracle customizer can update a profile to support an Oracle8i
Person type that you had defined. You could then use
Person as you would any other supported datatype.
You also have to use the Oracle customizer to utilize any of the
oracle.sql type extensions.
You can also customize previously created profiles by specifying
For more information about how
For more information about profile customization, see Chapter 10, "Profiles and Customization".
Also see the following for information about SQLJ options related to profile customization: