Oracle8i SQLJ Developer's Guide and Reference Release 8.1.5 A64684-01 |
|
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.
The -user
option specifies online checking, and the -password
and -url
options finish specifying the database connection if the password and URL were not specified in the -user
option. The -offline
or -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 SELECT
or 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 FETCH
, CAST
, CALL
, SET TRANSACTION
, VALUES
, and 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:
#sql [myCtx] { UPDATE ... };
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.
And in the following example:
#sql { UPDATE emp SET sal = :newSal };
If 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).
SELECT
or INSERT
so that SQLJ knows what kind of operation it is. For example, the following statement will generate an error:
#sql { foo };
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.
Note: The following is not checked against the database during online semantics-checking:
|
For your .sqlj
application source file, the SQLJ translator generates a .java
file and at least one profile (either in .ser
or .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.
Notes: 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.
The generated .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.
The generated .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 Foo.java
.
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:
Basename_SJProfileKeys
For example, translating Foo.sqlj
defines the following profile-keys class in the generated .java
file:
Foo_SJProfileKeys
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:
a.b.Foo_SJProfileKeys
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:
_SJProfile
n
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 input file Foo.sqlj
, 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 package a.b
, 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:
Foo_SJProfile0.ser
Foo_SJProfile1.ser
(Or they will be named Foo_SJProfile0.class
and 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 .ser
and .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".
When your #sql
statements are replaced by calls to the SQLJ runtime, these calls implement the following steps:
setXXX()
methods of the statement object).
executeUpdate()
or 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:
int
or 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):
Foo.class
Foo_SJProfileKeys.class
.class
file for each additional class you defined in Foo.sqlj
.class
file for each iterator and connection context class you declared in Foo.sqlj
(whether public or private)
So that .class
files generated by the compiler and profiles generated by SQLJ (whether .ser
or .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 file.encoding
property.
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 -compiler-executable
option.
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.
Note:
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: