Реализация ODCITableDescribe в хранимой процедуре Java
Текущий вопрос является второй частью этого вопроса, связанного с ODCI.
Я реализовал тип коллекции в Oracle SQL, который практически определяется как тип и таблица этого типа.
CREATE TYPE row_type AS OBJECT
(
C1 VARCHAR2(50),
C2 VARCHAR2(50),
C3 VARCHAR2(50)
);
/
CREATE TYPE row_type_set AS TABLE OF row_type;
Кроме того, я определил тип ODCI с его реализацией как хранимую процедуру Java в базе данных:
SQL:
CREATE OR REPLACE TYPE ODCIImpl AS OBJECT (
key INTEGER,
STATIC FUNCTION ODCITableStart(sctx OUT ODCIImpl, cur SYS_REFCURSOR)
RETURN NUMBER
AS LANGUAGE JAVA
NAME 'ODCIImpl.ODCITableStart(oracle.sql.STRUCT[], java.sql.ResultSet) return java.math.BigDecimal',
MEMBER FUNCTION ODCITableFetch(self IN OUT ODCIImpl, nrows IN NUMBER,
outSet OUT row_type_set) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'ODCIImpl.ODCITableFetch(java.math.BigDecimal, oracle.sql.ARRAY[]) return java.math.BigDecimal',
MEMBER FUNCTION ODCITableClose(self IN ODCIImpl) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'ODCIImpl.ODCITableClose() return java.math.BigDecimal'
);
/
Хранимая процедура Java:
import java.io.*;
import java.util.*;
import oracle.sql.*;
import java.sql.*;
import java.math.BigDecimal;
import oracle.CartridgeServices.*;
// stored context type
public class StoredCtx
{
ResultSet rset;
public StoredCtx(ResultSet rs) { rset=rs; }
}
// implementation type
public class ODCIImpl implements SQLData
{
private BigDecimal key;
final static BigDecimal SUCCESS = new BigDecimal(0);
final static BigDecimal ERROR = new BigDecimal(1);
final static int MAX_COLUMNS = 3;
// Implement SQLData interface.
String sql_type;
public String getSQLTypeName() throws SQLException
{
return sql_type;
}
public void readSQL(SQLInput stream, String typeName) throws SQLException
{
sql_type = typeName;
key = stream.readBigDecimal();
}
public void writeSQL(SQLOutput stream) throws SQLException
{
stream.writeBigDecimal(key);
}
// type methods implementing ODCITable interface
static public BigDecimal ODCITableStart(STRUCT[] sctx,ResultSet rset)
throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
// create a stored context and store the result set in it
StoredCtx ctx=new StoredCtx(rset);
// register stored context with cartridge services
int key;
try {
key = ContextManager.setContext(ctx);
} catch (CountException ce) {
return ERROR;
}
// create a ODCIImpl instance and store the key in it
Object[] impAttr = new Object[1];
impAttr[0] = new BigDecimal(key);
StructDescriptor sd = new StructDescriptor("ODCIIMPL",conn);
sctx[0] = new STRUCT(sd,conn,impAttr);
return SUCCESS;
}
public BigDecimal ODCITableFetch(BigDecimal nrows, ARRAY[] outSet)
throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
// retrieve stored context using the key
StoredCtx ctx;
try {
ctx=(StoredCtx)ContextManager.getContext(key.intValue());
} catch (InvalidKeyException ik ) {
return ERROR;
}
// get the nrows parameter, but return up to 10 rows
int nrowsval = nrows.intValue();
// create a vector for the fetched rows
Vector v = new Vector(nrowsval);
int i=0;
StructDescriptor outDesc =
StructDescriptor.createDescriptor("ROW_TYPE", conn);
Object[] out_attr = new Object[MAX_COLUMNS];
ResultSetMetaData rsmd = ctx.rset.getMetaData();
int columnsNumber = rsmd.getColumnCount();
while(nrowsval>0 && ctx.rset.next()){
for(int j = 0; j < columnsNumber; j++) {
if(j == MAX_COLUMNS)
break;
out_attr[j] = (Object)ctx.rset.getString(j+1);
}
v.add((Object)new STRUCT(outDesc, conn, out_attr));
i+=1;
nrowsval-=1;
}
// return if no rows found
if(i==0) return SUCCESS;
// create the output ARRAY using the vector
Object out_arr[] = v.toArray();
ArrayDescriptor ad = new ArrayDescriptor("ROW_TYPE_SET",conn);
outSet[0] = new ARRAY(ad,conn,out_arr);
return SUCCESS;
}
public BigDecimal ODCITableClose() throws SQLException {
// retrieve stored context using the key, and remove from ContextManager
StoredCtx ctx;
try {
ctx=(StoredCtx)ContextManager.clearContext(key.intValue());
} catch (InvalidKeyException ik ) {
return ERROR;
}
// close the result set
Statement stmt = ctx.rset.getStatement();
ctx.rset.close();
if(stmt!=null) stmt.close();
return SUCCESS;
}
}
После всего этого я реализовал конвейерную функцию, которую можно вызывать с помощью курсора.
CREATE OR REPLACE FUNCTION Exec_Remote_SQL_JSP(p SYS_REFCURSOR) RETURN row_type_set
PIPELINED USING ODCIImpl;
/
Мой вопрос теперь заключается в том, как мы можем реализовать метод ODCITableDescribe в хранимой процедуре Java для вывода любого типа данных в эмулируемую таблицу? Прежде всего, возможно ли это вообще? Похоже, я не нашел нужной информации об этом в документации Oracle здесь и здесь.
Если это возможно, это само собой понятно, что нам больше не нужны типы коллекций, упомянутые в начале. Эмулируемая таблица должна иметь тот же размер и типы данных, что и таблица, из которой мы намерены выбирать информацию.