ARRAYs as *real* objects?
Date: 22 Jan 2001 19:50:18 +0100
Message-ID: <yfn1cjv2tx.fsf_at_sartorius.curie.fr>
Hello,
I'm trying to get a "generic" way to handle ARRAYs (nested tables in fact) from a table. Considering this code : create type attribute as object ( name varchar2(256), attr varchar2(256) );
/
create type attribute_list as table of attribute;
/
create type node as object (
name varchar2(256), attributes attribute_list, attributes_private attribute_list, childlist ref node, parent ref node, previous ref node, next ref node, childnum number, content clob );
/
create table arbo of node
nested table attributes store as attr_table nested table attributes_private store as attrpriv_table;
/
This example works fine, but the problem arises when I want to do some dml on nested tables "attributes" and "attributes_private". I must declare particular methods for *each* nested tables, and I haven't found a way to manage both nested table the same way, with the same code (neither with jdbc nor with pl/sql). I thought that the "table_collection_expression" as specified in the SQL reference can take an ARRAY as argument, but if I don't set this *explicitly*, I'll get syntax error in pl/sql or invalid table name with jdbc. Please see the following code.
PL/SQL Code :
CREATE OR REPLACE PROCEDURE insertAttr(attrlist ATTRIBUTE_LIST, key CHAR, value CHAR) is
BEGIN
INSERT INTO TABLE(attrlist) VALUES (key, value);
END;
/
Error Code :
Erreurs pour PROCEDURE INSERTATTR :
LINE/COL ERROR
- ----------------------------------------------------------------- 3/2 PLS-00801: erreur interne [22016] 3/2 PL/SQL: SQL Statement ignored
I could do something as :
CREATE OR REPLACE PROCEDURE insertAttr(attrlist ATTRIBUTE_LIST, key CHAR, value CHAR) is BEGIN
attrlist.EXTEND; attrlist(attrlist.LAST) := attribute(key, value);END;
/
but it is illegal too, because argument are passed by value et I haven't found a way to "REFerencing" a nested table, REF ATTRIBUTE_LISTE is simply refused by pl/sql engine.
*This* works :
CREATE OR REPLACE PROCEDURE insertAttr(anode REF NODE, key CHAR, value CHAR) is
BEGIN
INSERT INTO TABLE(SELECT attributes FROM arbo a WHERE REF(a) = anode) VALUES (key, value);
END;
/
Same problem with JDBC Code :
OracleConnection conn; StructDescriptor structdesc; ArrayDescriptor arraydesc; OracleCallableStatement createNodeStatement; OracleCallableStatement insertNodeStatement; OracleCallableStatement createAttributeListStatement; OraclePreparedStatement pstmt; Statement stmt; STRUCT anode; REF refnode = null; ARRAY anarray; Class.forName("oracle.jdbc.driver.OracleDriver"); conn = (OracleConnection) DriverManager.getConnection("jdbc:oracle:oci8:_at_",<snipped>,<snipped>); structdesc = StructDescriptor.createDescriptor("NODE", conn); arraydesc = ArrayDescriptor.createDescriptor("ATTRIBUTE_LIST", conn); createNodeStatement = (OracleCallableStatement) conn.prepareCall("begin ? := node(NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL); end;"); createNodeStatement.registerOutParameter(1, Types.STRUCT, "LIVRET.NODE"); insertNodeStatement = (OracleCallableStatement) conn.prepareCall("begin ? := insertNode(?); end;"); insertNodeStatement.registerOutParameter(1, Types.REF, "LIVRET.NODE"); createAttributeListStatement = (OracleCallableStatement) conn.prepareCall("begin ? := attribute_list(); end;"); createAttributeListStatement.registerOutParameter(1, Types.ARRAY, "LIVRET.ATTRIBUTE_LIST"); stmt = conn.createStatement(); stmt.execute("DELETE FROM arbo"); createNodeStatement.execute(); anode = createNodeStatement.getSTRUCT(1); stmt.execute("CREATE OR REPLACE FUNCTION insertNode(anode NODE) "+ " RETURN REF node AS "+ " node_ref REF node; "+ "BEGIN "+ " INSERT INTO arbo a VALUES (anode) RETURNING REF(a) INTO node_ref; "+ " RETURN node_ref; "+ "END;"); insertNodeStatement.setSTRUCT(2, anode); insertNodeStatement.execute(); refnode = insertNodeStatement.getREF(1); pstmt = (OraclePreparedStatement) conn.prepareStatement("UPDATE arbo a SET attributes = attribute_list() WHERE REF(a) = ?"); pstmt.setREF(1, refnode); pstmt.execute(); pstmt.close(); pstmt = (OraclePreparedStatement) conn.prepareStatement("SELECT attributes FROM arbo a WHERE REF(a) = ?"); pstmt.setREF(1, refnode); rs = pstmt.executeQuery(); rs.next(); anarray = ((OracleResultSet) rs).getARRAY(1); rs.close(); pstmt.close();
/* This works */
pstmt = (OraclePreparedStatement) conn.prepareStatement("INSERT INTO TABLE(SELECT attributes FROM arbo a WHERE REF(a) = ?) VALUES (?, ?)"); pstmt.setREF(1, anode); pstmt.setString(2, "bouh"); pstmt.setString(3, "haha"); pstmt.execute(); pstmt.close();
/* This doesn't work and throws SQLException ORA-00903: Invalid table name */
pstmt = (OraclePreparedStatement) conn.prepareStatement("INSERT INTO TABLE(?) VALUES (?, ?)"); pstmt.setARRAY(1, anarray); pstmt.setString(2, "blah"); pstmt.setString(3, "blih"); pstmt.execute(); pstmt.close(); createNodeStatement.close(); createAttributeListStatement.close(); stmt.close(); conn.close(); }
}
In conclusion, ARRAYs *aren't* real objects, or I've missed something.
[Quoted] Many thanks for any help or references you can provide on that topic.
--
François-David Collin
Institut Curie/Section Recherche
remove the "nospam" in adress for email.
Received on Mon Jan 22 2001 - 19:50:18 CET