Oracle8i SQLJ Developer's Guide and Reference
Release 8.1.5

A64684-01

Library

Product

Contents

Index

Prev  Chap Top Next

Internal Translator Operations

The following subsections summarize the operations executed by the SQLJ translator during a translation.

Code-Parsing and Syntax-Checking

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.

Semantics-Checking

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:

  1. SQLJ analyzes the types of Java expressions in your SQLJ executable statements.

    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).


Note:

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.  


  1. 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 };
    
    

The following two tasks are performed only if online checking is enabled:

  1. SQLJ analyzes your embedded SQL operations and checks their syntax against the database.

  2. SQLJ checks the types of Java expressions in SQLJ executable statements against: 1) SQL types of corresponding columns in the database; 2) SQL types of corresponding arguments and return variables of stored procedures and functions.

    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:

  • DDL statements (such as CREATE, ALTER, and DROP) and transaction-control statements (such as COMMIT and ROLLBACK)

  • compatibility of data corresponding to weakly typed host expressions (those using the oracle.sql package STRUCT, REF, and ARRAY classes, which are discussed in "Weakly Typed Objects, References, and Collections")

  • mode compatibility (IN, OUT, or IN OUT) of expressions in PL/SQL anonymous blocks

 

Code Generation

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.  


Generated Application Code in .java File

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.)

Generated Profile-Keys Class in .java File

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

Generated Profiles in .ser or .class Files

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:

_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 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".

More About Generated Calls to SQLJ Runtime

When your #sql statements are replaced by calls to the SQLJ runtime, these calls implement the following steps:

  1. Get a SQLJ statement object (using information stored in the associated profile entry).

  2. Bind inputs into the statement (using setXXX() methods of the statement object).

  3. Execute the statement (using the executeUpdate() or executeQuery() method of the statement object).

  4. Create iterator instances, if applicable.

  5. Retrieve outputs from the statement (using getXXX() methods of the statement object).

  6. Close the statement.

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:

Java Compilation

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):

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.


Note:

If you are using the SQLJ -encoding option but using a compiler that does not have an -encoding option, turn off the SQLJ -compiler-encoding-flag (otherwise SQLJ will attempt to pass the -encoding option to the compiler).  


For information about compiler-related SQLJ options, see the following:

Profile Customization

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 .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 and compiled, but not both.

For more information about how .jar files are used, see "Use of .jar Files for Profiles".  


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:




Prev

Top

Next
Oracle
Copyright © 1999 Oracle Corporation.

All Rights Reserved.

Library

Product

Contents

Index