2

I want to implement a stack data structure in 10gR2.

However, when I try to do:

CREATE or replace TYPE ContainerArray AS VARRAY(25) OF XDB.DBMS_XMLDOM.DOMNODE ;

I get

"schema-level type has illegal reference to XDB.DBMS_XMLDOM."

So I've figured out that's because Oracle will not let you create a schema-level type which references a package-level type.

I can fix that problem by creating the type inside of the package:

TYPE ContainerArray AS VARRAY(25) OF XDB.DBMS_XMLDOM.DOMNODE;

However, then when I try to create my object, I can't reference the package-level type:

CREATE TYPE DOMNode_Stack AS OBJECT ( 
   max_size INTEGER, 
   top      INTEGER,
   position ContainerArray,
   MEMBER PROCEDURE initialize,
   MEMBER FUNCTION full RETURN BOOLEAN,
   MEMBER FUNCTION empty RETURN BOOLEAN,
   MEMBER PROCEDURE push (n IN INTEGER),
   MEMBER PROCEDURE pop (n OUT INTEGER)
);

and I can't create the object type inside of the package because I get

"Object not supported in this context."

Any thoughts on how I can solve this issue?

1 Answer 1

1

sql level objects like an OBJECT can only reference SQL types in their attributes.

if you see the package spec:

TYPE DOMNode IS RECORD (id RAW(13));

so you could create an sql array of

SQL> CREATE or replace TYPE ContainerArray AS VARRAY(25) OF raw(13);
  2  /

Type created.

then in your object put

position ContainerArray

which will work. when you reference it, just assign a local variable v_dom xml_dom.domnode; begin v_dom.id := your array index value that you're dealing with at the time;

be advised that on any Oracle upgrade you need to verify that the structure of DOMNODE hasn't changed.

edit: here's a sample:

SQL> set serverout on
SQL> create or replace type containerarray as varray(25) of raw(13);
  2  /

Type created.

SQL> create type domnode_stack as object (
  2     position containerarray,
  3     member procedure initialize,
  4     member procedure print_node_names
  5  );
  6  /

Type created.

SQL> CREATE TYPE body DOMNode_Stack
  2  as
  3    member procedure initialize
  4    is
  5      v_dom dbms_xmldom.DOMNode;
  6      v_doc dbms_xmldom.domdocument;
  7      v_nl  dbms_xmldom.DOMNodeList;
  8    begin
  9      position := containerarray();
 10      v_doc := dbms_xmldom.newDOMDocument(xmltype('<root><foo>test</foo><foo2>test2</foo2></root>')); -- just some summy data.
 11      v_nl  := dbms_xmldom.getElementsByTagName(v_doc, '*');
 12      for idx in 0..dbms_xmldom.getLength(v_nl)-1 loop
 13        v_dom := DBMS_XMLDOM.item(v_nl, idx);
 14        position.extend;
 15        position(position.last) := v_dom.id;
 16      end loop;
 17    end;
 18
 19    member procedure print_node_names
 20    is
 21      v_dom dbms_xmldom.DOMNode;
 22    begin
 23      for idx in 1..position.count
 24      loop
 25        v_dom.id := position(idx);
 26        dbms_output.put_line(dbms_xmldom.getnodename(v_dom)||'='||dbms_xmldom.getnodevalue(dbms_xmldom.getfirstchild(v_dom)));
 27      end loop;
 28    end;
 29  end;
 30  /

Type body created.

SQL> show errors type body DOMNode_Stack
No errors.
SQL> declare
  2    o_domnode DOMNode_Stack := DOMNode_Stack(null);
  3  begin
  4    o_domnode.initialize();
  5    o_domnode.print_node_names();
  6  end;
  7  /
root=
foo=test
foo2=test2

PL/SQL procedure successfully completed.

the important bit being:

to assign from DBMS_XMLDOM to the sql type we take v_dom.id.

13 v_dom := DBMS_XMLDOM.item(v_nl, idx); 14 position.extend; 15 position(position.last) := v_dom.id;

and when reversing:

23 for idx in 1..position.count 24 loop 25 v_dom.id := position(idx);

ie assign the ID part (not the record itself..that would error out) back.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the response. I was able to get the object created. The one issue I'm having now is converting between the types. For example, I get wrong number or types of arguments when calling my_stack.push(my_node)` because push is defined to take a RAW and my_node is a DOMNODE. But a DOMNODE is actually a RAW(13). How can I get Oracle to allow use of the types interchangeably? CAST() does not appear like it will work.
create a local variable like: v_dom DBMS_XMLDOM.DOMNode then assign like v_dom.id := t_array(idx) (where t_array is your sql array and idx is the array element you're dealing with at the time).
Doesn't work unfortunately. Expression is of wrong type I'm wondering if I'm going to have to use SQL to insert and remove elements from this VARRAY.
can you paste the failing code snippet in your question as an edit at all?
see my amended answer..ive put a sample in there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.