Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 353417

Summary: DBWS should support non-associative PLSQL collections
Product: z_Archived Reporter: Mike Norman <michael.norman>
Component: EclipselinkAssignee: Nobody - feel free to take it <nobody>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: david.mccann, eclipselink.dbws-inbox
Version: unspecified   
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard:
Attachments:
Description Flags
Proposed fix.
none
Supporting test cases.
none
Proposed fix v2 (post review) none

Description Mike Norman CLA 2011-07-29 10:10:40 EDT
From the issue raised in the OTN TopLink forum:
   http://forums.oracle.com/forums/thread.jspa?threadID=2257216

A simple PLSQL collection type is used in a Stored Procedure call query:

CREATE OR REPLACE PACKAGE MY_PACKAGE AS 
    TYPE MY_ARRAY IS TABLE OF VARCHAR2(20); 
    PROCEDURE TEST(NAMES IN MY_ARRAY, CNT OUT NUMERIC);  
END MY_PACKAGE;

CREATE OR REPLACE PACKAGE BODY MY_PACKAGE AS
  PROCEDURE TEST(NAMES IN MY_ARRAY, CNT OUT NUMERIC) AS
  BEGIN
    CNT := NAMES.COUNT;
  END TEST;
END MY_PACKAGE;

        PLSQLCollection myArrayType = new PLSQLCollection();
        myArrayType.setTypeName("MY_PACKAGE.MY_ARRAY");
        myArrayType.setCompatibleType("MY_PACKAGE_MY_ARRAY");
        myArrayType.setJavaType(ArrayList.class);
        myArrayType.setNestedType(JDBCTypes.VARCHAR_TYPE);

        PLSQLStoredProcedureCall testCall = new PLSQLStoredProcedureCall();
        testCall.setProcedureName("MY_PACKAGE.TEST");
        testCall.addNamedArgument("NAMES", myArrayType);
        testCall.addNamedOutputArgument("CNT", JDBCTypes.INTEGER_TYPE);
        ValueReadQuery query = new ValueReadQuery();
        query.addArgument("NAMES", ArrayList.class);
        query.setCall(testCall);

        ArrayList<String> items = new ArrayList<String>();
        items.add("first string");
        items.add("second string");
        items.add("third string");
        items.add("fourth string");
        items.add("fifth string");
        items.add("sixth string");
        items.add("seventh string");
        items.add("eighth string");
        items.add("nineth string");
        items.add("tenth string");
        Object value = null;
        try {
            List<Object> args = new ArrayList<Object>();
            args.add(items);
            value = session.executeQuery(query, args);
        }
        catch (Exception e) {
            e.printStackTrace();
        }

The following anonymous PLSQL block is generated:
DECLARE
  NAMES_TARGET MY_PACKAGE.MY_ARRAY;
  NAMES_COMPAT MY_PACKAGE_MY_ARRAY := :1;
  CNT_TARGET INTEGER;
  FUNCTION EL_SQL2PL_1(aSqlItem MY_PACKAGE_MY_ARRAY) RETURN MY_PACKAGE.MY_ARRAY IS
      aPlsqlItem MY_PACKAGE.MY_ARRAY;
  BEGIN
      IF aSqlItem.COUNT > 0 THEN
          FOR I IN 1..aSqlItem.COUNT LOOP
              aPlsqlItem(I) := aSqlItem(I);
          END LOOP;
      END IF;
      RETURN aPlsqlItem;
  END EL_SQL2PL_1;
BEGIN
  NAMES_TARGET := EL_SQL2PL_1(NAMES_COMPAT);
  MY_PACKAGE.TEST(NAMES=>NAMES_TARGET, CNT=>CNT_TARGET);
  :2 := CNT_TARGET;
END;

An exception is thrown:
...
ORA-06531: Reference to uninitialized collection
ORA-06512: at line 11
...
Comment 1 Mike Norman CLA 2011-07-29 10:17:57 EDT
The behaviour of PLSQL collection contructors changed when associative
array were added to the language (9i). Non-associative collections require
the constructor to be called:
...
      aPlsqlItem MY_PACKAGE.MY_ARRAY;
  BEGIN
      IF aSqlItem.COUNT > 0 THEN
          aPlsqlItem := MY_PACKAGE.MY_ARRAY();
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          FOR I IN 1..aSqlItem.COUNT LOOP
              aPlsqlItem(I) := aSqlItem(I);
          END LOOP;

The unfortunate thing is that the above code throws a 'weird' error
when the collection IS associative

PLS-00222: no function with name 'MY_ARRAY' exists in this scope

We need a way to get metadata information discovered at design-time
(is the collection associative?) passed to EclipseLink runtime so that
the generated nested function code in the anonymous PLSQL block can take
the incompatible behaviour into account and generate (or not) the appropriate
constructor call.
Comment 2 David McCann CLA 2012-01-05 15:28:25 EST
Created attachment 209102 [details]
Proposed fix.
Comment 3 David McCann CLA 2012-01-05 15:28:40 EST
Created attachment 209103 [details]
Supporting test cases.
Comment 4 David McCann CLA 2012-01-06 10:47:53 EST
Created attachment 209134 [details]
Proposed fix v2 (post review)

Changed xpath of isNonAssociative mapping on the PLSQLargument descriptor from a text node to an attribute - '@non-associative'.
Comment 5 David McCann CLA 2012-01-06 10:51:43 EST
Reviewed by:  michael.norman@oracle.com 
Tests:  all DBWS unit tests pass as expected; core LRG passes; added NonAssociativePLSQLCollectionTestSuite
Revision: 10652
Comment 6 David McCann CLA 2012-01-06 10:52:01 EST
Fixed.
Comment 7 Eclipse Webmaster CLA 2022-06-09 10:27:11 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink