Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Difference between revisions of "EclipseLink/Development/DBWS/OracleUseCases"
(20 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
+ | <css> | ||
+ | .source-sql {padding:4px;border:1px solid black;} | ||
+ | </css> | ||
+ | __NOTOC__ | ||
== Supported Use-Cases for Oracle Platforms == | == Supported Use-Cases for Oracle Platforms == | ||
<i>All of the use-cases support for non-Oracle Platforms are supported on Oracle</i> | <i>All of the use-cases support for non-Oracle Platforms are supported on Oracle</i> | ||
− | The design-time utility <code>DBWSBuilder</code> uses custom Data Dictionary queries for the Oracle Platform | + | The design-time utility <code>DBWSBuilder</code> uses custom Data Dictionary queries for the Oracle Platform since the <code>java.sql.DatabaseMetaData</code> API suffers from well-documented problems of accuracy and scope<sup>1</sup>. By doing so, additional use-cases can be supported: |
− | By doing so, additional use-cases can be supported: | + | === Advanced JDBC types as arguments to Stored Procedure calls === |
− | + | * Object Types - <code>java.sql.Struct</code>'s are realized in Oracle using proprietary types (<code>oracle.sql.STRUCT</code>) and APIs that are encapsulated in <code>org.eclipse.persistence.platform.database.oracle.Oracle8Platform</code> *or higher) | |
− | + | * Array Types - <code>java.sql.Array</code>'s are realized in Oracle using proprietary types (<code>oracle.sql.VARRAY</code>) and APIs that are encapsulated in <code>org.eclipse.persistence.platform.database.oracle.Oracle8Platform</code> (or higher). | |
− | + | ||
− | + | ||
− | + | ||
An extreme (!) use-case: an object type wrapped in an array type, wrapped in another object type which is again wrapped in an array type and (finally!) wrapped in a third object type. | An extreme (!) use-case: an object type wrapped in an array type, wrapped in another object type which is again wrapped in an array type and (finally!) wrapped in a third object type. | ||
− | + | ||
− | + | === Scalar PL/SQL datatypes === | |
− | + | Some PL/SQL datatypes have no JDBC equivalent and must be converted. The strategy is to use an anonymous PL/SQL block and handle the type conversion before the invocation of the Stored Procedure: e.g. BOOLEAN (pass in argument as JDBC integer 0 or 1 | |
+ | <source lang=sql> | ||
declare | declare | ||
x_target boolean := SYS.SQLJUTL.INT2BOOL(:1); | x_target boolean := SYS.SQLJUTL.INT2BOOL(:1); | ||
Line 19: | Line 22: | ||
end; | end; | ||
</source> | </source> | ||
− | + | * numeric types: PLS_INTEGER, SMALLINT, NUMERIC, BINARY_INTEGER, PLS_INTEGER, NATURAL, NATURALN, POSITIVE, POSITIVEN, SIGNTYPE, DEC, DECIMAL, LONG, LONG_RAW, RAW <br />Using the JDBC type with the widest precision <code>java.sql.Types.NUMERIC</code>, a simple assignment will do: | |
− | + | <source lang=sql> | |
− | + | ||
− | + | ||
declare | declare | ||
y_target PLS_INTEGER := :1; | y_target PLS_INTEGER := :1; | ||
Line 29: | Line 30: | ||
end; | end; | ||
</source> | </source> | ||
− | * Advanced PL/SQL types as arguments to Stored Procedure calls | + | * OUT arguments |
− | + | <source lang=sql> | |
− | ::this | + | declare |
− | + | x_target VARCHAR(20) := :1; | |
− | :: | + | y_target BOOLEAN; |
+ | begin | ||
+ | some_pkg2.nint_test3(x=>x_target, y=>y_target); | ||
+ | :2 := SYS.SQLJUTL.BOOL2INT(y_target); | ||
+ | end; | ||
+ | </source> | ||
+ | * INOUT arguments: PL/SQL anonymous blocks do not support INOUT arguments; thus an additional <i>computed</i> bind variable is needed: | ||
+ | <source lang=sql> | ||
+ | declare | ||
+ | x_target VARCHAR(20) := :1; | ||
+ | y_target BOOLEAN := SYS.SQLJUTL.INT2BOOL(:2); | ||
+ | begin | ||
+ | test_pkg.test2(x=>x_target, y=>y_target); | ||
+ | :3 := SYS.SQLJUTL.BOOL2INT(y_target); | ||
+ | end; | ||
+ | </source> | ||
+ | === Advanced PL/SQL types as arguments to Stored Procedure calls === | ||
+ | * Record types - a PL/SQL record is created either explicitly in a <tt>package</tt> declaration: | ||
+ | <source lang=sql> | ||
+ | CREATE OR REPLACE PACKAGE SOMEPACKAGE AS | ||
+ | TYPE TBL1 IS TABLE OF VARCHAR2(111) INDEX BY BINARY_INTEGER; | ||
+ | TYPE TBL2 IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; | ||
+ | TYPE ARECORD IS RECORD ( | ||
+ | T1 TBL1, | ||
+ | T2 TBL2, | ||
+ | T3 BOOLEAN | ||
+ | ); | ||
+ | ... | ||
+ | END SOMEPACKAGE; | ||
+ | </source> | ||
+ | or implicitly using the <tt>%ROWTYPE</tt> macro: | ||
+ | <source lang=sql>procedure rec_test(z in emp%ROWTYPE)</source> | ||
+ | In either case, the trick to passing along the required information is to 'stage' it a compatible JDBC Object type whose fields and types are the same as the record's: | ||
+ | <source lang=sql> | ||
+ | CREATE TYPE EMP_TYPE AS OBJECT ( | ||
+ | EMPNO NUMBER(4,0), | ||
+ | ENAME VARCHAR2(10), | ||
+ | JOB VARCHAR2(9), | ||
+ | MGR NUMBER(4,0), | ||
+ | HIREDATE DATE, | ||
+ | SAL NUMBER(7,2), | ||
+ | COMM NUMBER(7,2), | ||
+ | DEPTNO NUMBER(2,0) | ||
+ | ); | ||
+ | </source> | ||
+ | The generated anonymous PL/SQL block can take advantage of this compatibility: | ||
+ | <source lang=sql> | ||
+ | DECLARE | ||
+ | Z_TARGET emp%ROWTYPE; | ||
+ | Z_COMPAT EMP_TYPE := :1; | ||
+ | BEGIN | ||
+ | Z_TARGET.EMPNO := Z_COMPAT.EMPNO; | ||
+ | Z_TARGET.ENAME := Z_COMPAT.ENAME; | ||
+ | Z_TARGET.JOB := Z_COMPAT.JOB; | ||
+ | Z_TARGET.MGR := Z_COMPAT.MGR; | ||
+ | Z_TARGET.HIREDATE := Z_COMPAT.HIREDATE; | ||
+ | Z_TARGET.SAL := Z_COMPAT.SAL; | ||
+ | Z_TARGET.COMM := Z_COMPAT.COMM; | ||
+ | Z_TARGET.DEPTNO := Z_COMPAT.DEPTNO; | ||
+ | REC_TEST(Z=>Z_TARGET); | ||
+ | END; | ||
+ | </source> | ||
+ | For more complicated nested structures, the anonymous PL/SQL block will contain nested functions that do the compatibility conversion and can be called multiple times at different levels of the nested structure. | ||
+ | * Collection types: in the same way that compatible JDBC Object types are used, compatible JDBC Array types are used to pass along the information into the Stored Procedure's argument that is a PL/SQL collection type. | ||
+ | |||
+ | === LOB datatypes === | ||
+ | * <tt>CLOB</tt>: supported; realized in-memory and when marshalled to SOAP messages as inlined strings | ||
+ | * <tt>BLOB</tt>: supported; realized in-memory as <code>byte[]</code> array's; can be marshalled to SOAP messages inlined as <tt>base64binary</tt> or can be handled as binary attachments. | ||
+ | * <tt>NCLOB</tt>: not supported | ||
+ | |||
+ | <b>It is important to note</b> that <tt>CLOB</tt>'s and <tt>BLOB</tt>'s cannot exceed the JVM's memory handling capabilities; i.e. there is no support for <b><i>streamed</i></b> attachments. | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
<sup>1</sup> | <sup>1</sup> | ||
− | Compliance to the meta-data APIs available through the <code>java.sql.DatabaseMetaData</code> is weak - no vendor implements the APIs fully, nor in a standard fashion. For example, the simple act of getting the <b><i>names</i></b> of available databases is different across platforms: on Oracle the <code>getSchemas</code> method is used while for DB2/Sybase/MS SQLServer the <code>getCatalogs</code> method is used. Another example of cross-platform meta-data issues is the <code>getColumns</code> method: for PostgreSQL, the name of the table <b>must</b> be lower-case; for Oracle, it <b>must</b> be upper-case; others support mixed-case. [http://www.sun.com/bigadmin/content/submitted/jdbc_drivers.html | + | Compliance to the meta-data APIs available through the <code>java.sql.DatabaseMetaData</code> is weak - no vendor implements the APIs fully, nor in a standard fashion. For example, the simple act of getting the <b><i>names</i></b> of available databases is different across platforms: on Oracle the <code>getSchemas</code> method is used while for DB2/Sybase/MS SQLServer the <code>getCatalogs</code> method is used. Another example of cross-platform meta-data issues is the <code>getColumns</code> method: for PostgreSQL, the name of the table <b>must</b> be lower-case; for Oracle, it <b>must</b> be upper-case; others support mixed-case. [http://www.sun.com/bigadmin/content/submitted/jdbc_drivers.html This link is a case-study of some of the issues]. |
Latest revision as of 14:16, 21 December 2009
Supported Use-Cases for Oracle Platforms
All of the use-cases support for non-Oracle Platforms are supported on Oracle
The design-time utility DBWSBuilder
uses custom Data Dictionary queries for the Oracle Platform since the java.sql.DatabaseMetaData
API suffers from well-documented problems of accuracy and scope1. By doing so, additional use-cases can be supported:
Advanced JDBC types as arguments to Stored Procedure calls
- Object Types -
java.sql.Struct
's are realized in Oracle using proprietary types (oracle.sql.STRUCT
) and APIs that are encapsulated inorg.eclipse.persistence.platform.database.oracle.Oracle8Platform
*or higher) - Array Types -
java.sql.Array
's are realized in Oracle using proprietary types (oracle.sql.VARRAY
) and APIs that are encapsulated inorg.eclipse.persistence.platform.database.oracle.Oracle8Platform
(or higher).
An extreme (!) use-case: an object type wrapped in an array type, wrapped in another object type which is again wrapped in an array type and (finally!) wrapped in a third object type.
Scalar PL/SQL datatypes
Some PL/SQL datatypes have no JDBC equivalent and must be converted. The strategy is to use an anonymous PL/SQL block and handle the type conversion before the invocation of the Stored Procedure: e.g. BOOLEAN (pass in argument as JDBC integer 0 or 1
DECLARE x_target BOOLEAN := SYS.SQLJUTL.INT2BOOL(:1); BEGIN bool_test(x=>x_target); END;
- numeric types: PLS_INTEGER, SMALLINT, NUMERIC, BINARY_INTEGER, PLS_INTEGER, NATURAL, NATURALN, POSITIVE, POSITIVEN, SIGNTYPE, DEC, DECIMAL, LONG, LONG_RAW, RAW
Using the JDBC type with the widest precisionjava.sql.Types.NUMERIC
, a simple assignment will do:
DECLARE y_target PLS_INTEGER := :1; BEGIN int_test(y=>y_target); END;
- OUT arguments
DECLARE x_target VARCHAR(20) := :1; y_target BOOLEAN; BEGIN some_pkg2.nint_test3(x=>x_target, y=>y_target); :2 := SYS.SQLJUTL.BOOL2INT(y_target); END;
- INOUT arguments: PL/SQL anonymous blocks do not support INOUT arguments; thus an additional computed bind variable is needed:
DECLARE x_target VARCHAR(20) := :1; y_target BOOLEAN := SYS.SQLJUTL.INT2BOOL(:2); BEGIN test_pkg.test2(x=>x_target, y=>y_target); :3 := SYS.SQLJUTL.BOOL2INT(y_target); END;
Advanced PL/SQL types as arguments to Stored Procedure calls
- Record types - a PL/SQL record is created either explicitly in a package declaration:
CREATE OR REPLACE PACKAGE SOMEPACKAGE AS TYPE TBL1 IS TABLE OF VARCHAR2(111) INDEX BY BINARY_INTEGER; TYPE TBL2 IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; TYPE ARECORD IS RECORD ( T1 TBL1, T2 TBL2, T3 BOOLEAN ); ... END SOMEPACKAGE;
or implicitly using the %ROWTYPE macro:
PROCEDURE rec_test(z IN emp%ROWTYPE)
In either case, the trick to passing along the required information is to 'stage' it a compatible JDBC Object type whose fields and types are the same as the record's:
CREATE TYPE EMP_TYPE AS OBJECT ( EMPNO NUMBER(4,0), ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4,0), HIREDATE DATE, SAL NUMBER(7,2), COMM NUMBER(7,2), DEPTNO NUMBER(2,0) );
The generated anonymous PL/SQL block can take advantage of this compatibility:
DECLARE Z_TARGET emp%ROWTYPE; Z_COMPAT EMP_TYPE := :1; BEGIN Z_TARGET.EMPNO := Z_COMPAT.EMPNO; Z_TARGET.ENAME := Z_COMPAT.ENAME; Z_TARGET.JOB := Z_COMPAT.JOB; Z_TARGET.MGR := Z_COMPAT.MGR; Z_TARGET.HIREDATE := Z_COMPAT.HIREDATE; Z_TARGET.SAL := Z_COMPAT.SAL; Z_TARGET.COMM := Z_COMPAT.COMM; Z_TARGET.DEPTNO := Z_COMPAT.DEPTNO; REC_TEST(Z=>Z_TARGET); END;
For more complicated nested structures, the anonymous PL/SQL block will contain nested functions that do the compatibility conversion and can be called multiple times at different levels of the nested structure.
- Collection types: in the same way that compatible JDBC Object types are used, compatible JDBC Array types are used to pass along the information into the Stored Procedure's argument that is a PL/SQL collection type.
LOB datatypes
- CLOB: supported; realized in-memory and when marshalled to SOAP messages as inlined strings
- BLOB: supported; realized in-memory as
byte[]
array's; can be marshalled to SOAP messages inlined as base64binary or can be handled as binary attachments. - NCLOB: not supported
It is important to note that CLOB's and BLOB's cannot exceed the JVM's memory handling capabilities; i.e. there is no support for streamed attachments.
1
Compliance to the meta-data APIs available through the java.sql.DatabaseMetaData
is weak - no vendor implements the APIs fully, nor in a standard fashion. For example, the simple act of getting the names of available databases is different across platforms: on Oracle the getSchemas
method is used while for DB2/Sybase/MS SQLServer the getCatalogs
method is used. Another example of cross-platform meta-data issues is the getColumns
method: for PostgreSQL, the name of the table must be lower-case; for Oracle, it must be upper-case; others support mixed-case. This link is a case-study of some of the issues.