Oracle8i SQLJ Developer's Guide and Reference Release 3 (8.1.7) Part Number A83723-01 |
Library | Service | Contents | Index

## Internal Translator Operations

The following topics summarize the operations executed by the SQLJ translator during a translation:

- Code-Parsing and Syntax-Checking

- Semantics-Checking

- Code Generation

- Java Compilation

- Profile Customization

### Code-Parsing and Syntax-Checking

In this first phase of SQLJ translation, a SQLJ parser and a Java parser are used to process all 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, then 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".

Note: Semantics-checking can also be performed on a profile that was produced during a previous execution of the SQLJ translator. See "SQLCheckerCustomizer for Profile Semantics-Checking".

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 entered on the command-line, and any imported Java classes whose `.class` files or `.java` files 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 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 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 };

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 SQL 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 process 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.

Notes: 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.

Note: 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 your generic Java code, your 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 source file `Foo.java` will be generated by the translator.

The location of the generated `.java` file depends on whether and 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` 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. (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 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. (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 might or might not employ JDBC statement classes directly. SQLJ statement classes add functionality particular to SQLJ. For example:

- 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 an Oracle database.

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

- `Foo.class`

- `Foo_SJProfileKeys.class`

- a `.class` file for each additional class you defined in `Foo.sqlj`

- a `.class` file for each iterator and connection context class you declared in `Foo.sqlj` (whether public or private)

To ensure 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 JVM `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:

- "Output Directory for Generated .ser and .class Files (-d)"

- "Encoding for Input and Output Source Files (-encoding)"

- "Options to Pass to the Java Compiler (-C)"

- "Compilation Flag (-compile)"

- "Compiler Encoding Support (-compiler-encoding-flag)"

- "Name of the Java Compiler (-compiler-executable)"

- "Compiler Output File (-compiler-output-file)"

- "Compiler Message Output Pipe (-compiler-pipe-output-flag)"

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

- to allow 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, 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 must customize with the Oracle customizer to utilize any of the `oracle.sql` type extensions.

Note: The Oracle SQLJ runtime and an Oracle JDBC driver will be required by your application whenever you use the Oracle customizer during translation, even if you do not use Oracle extensions in your code. The generic SQLJ runtime 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 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:

- "Default Profile Customizer (-default-customizer)"

- "Options to Pass to the Profile Customizer (-P)"

- "Profile Customization Flag (-profile)"

- "Customization Options and Choosing a Customizer"

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index