I have a query like:
SELECT dmr.message_guid, dmr.document_id, dmr.part_name, dmr.document_type, dmr.dlv_partition_date, xdc.document_type, xdc.document, GET_XML_DOCUMENT(xdc.document,to_clob(' ')) doc_PAYLOAD, xdc.document_binary_format, dmg.conv_id , dmg.conv_type, dmg.properties msg_properties FROM document_dlv_msg_ref dmr join xml_document xdc on xdc.document_id = dmr.document_id join dlv_message dmg on dmg.message_guid = dmr.message_guid where dmg.cikey in (select cikey from cube_instance where flow_id = 4537505 or flow_id = 4537504);
To get all the messages that are related to two flows that run parallel based on the same message exchange.
The thing is that of course you want to see the contents of the message in the xml_document. This attribute is a BLOB that contains the parsed document from oracle xml classes. You need the oracle classes to serialize it to a String representation of the document. I found this nice solution from Michael Heyn.
In 12c this did not work right a way. First I had to rename the class to SOAXMLDocument, because I got a Java compilation error complaining that XMLDocument already was in use. I think it conflicts with the imported oracle.xml.parser.v2.XMLDocument class. Renaming it was the simple solution.
Another thing is that in SOA Suite 12c, the documents are apparent
set define off; CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "SOAXMLDocument" as // Title: Oracle Java Class to Decode XML_DOCUMENT.DOCUMENT Content // Author: Michael Heyn, Martien van den Akker // Created: 2015 05 08 // Twitter: @TheHeynComplex // History: // 2020-02-25: Added GZIP Unzip and renamed class to SOAXMLDocument // Import all required classes import oracle.xml.parser.v2.XMLDOMImplementation; import java.io.ByteArrayOutputStream; import java.io.IOException; import oracle.xml.binxml.BinXMLStream; import oracle.xml.binxml.BinXMLDecoder; import oracle.xml.binxml.BinXMLException; import oracle.xml.binxml.BinXMLProcessor; import oracle.xml.scalable.InfosetReader; import oracle.xml.parser.v2.XMLDocument; import oracle.xml.binxml.BinXMLProcessorFactory; import java.util.zip.GZIPInputStream; // Import required sql classes import java.sql.Blob; import java.sql.Clob; import java.sql.SQLException; public class SOAXMLDocument{ public static Clob GetDocument(Blob docBlob, Clob tempClob){ XMLDOMImplementation xmlDom = new XMLDOMImplementation(); BinXMLProcessor xmlProc = BinXMLProcessorFactory.createProcessor(); ByteArrayOutputStream byteStream; String xml; try { // Create a GZIP InputStream from the Blob Object GZIPInputStream gzipInputStream = new GZIPInputStream(docBlob.getBinaryStream()); // Create the Binary XML Stream from the GZIP InputStream BinXMLStream xmlStream = xmlProc.createBinXMLStream(gzipInputStream); // Decode the Binary XML Stream BinXMLDecoder xmlDecode = xmlStream.getDecoder(); InfosetReader xmlReader = xmlDecode.getReader(); XMLDocument xmlDoc = (XMLDocument) xmlDom.createDocument(xmlReader); // Instantiate a Byte Stream Object byteStream = new ByteArrayOutputStream(); // Load the Byte Stream Object xmlDoc.print(byteStream); // Get the string value of the Byte Stream Object as UTF8 xml = byteStream.toString("UTF8"); // Empty the temporary SQL Clob Object tempClob.truncate(0); // Load the temporary SQL Clob Object with the xml String tempClob.setString(1,xml); return tempClob; } catch (BinXMLException ex) { return null; } catch (IOException e) { return null; } catch (SQLException se) { return null; } catch (Exception e){ return null; } } } /
Also, I needed to execute set define off before it. Another thing is that in SOA Suite 12c the documents are apparently stored as GZIP object. Therefor I had to put the binaryStream from the docBlob parameter into a GZIPInputStream, and feed that to the xmlProc.createBinXMLStream().
Then create the following Function wrapper:
CREATE OR REPLACE FUNCTION GET_XML_DOCUMENT(p_blob BLOB ,p_clob CLOB) RETURN CLOB AS LANGUAGE JAVA NAME 'SOAXMLDocument.GetDocument(java.sql.Blob, java.sql.Clob) return java.sql.Clob';
You can use it in a query as:
select * from ( select xdc2.*, GET_XML_DOCUMENT(xdc2.document,to_clob(' ')) doc_PAYLOAD from (select * from xml_document xdc where xdc.doc_partition_date > to_date('25-02-20 09:10:00', 'DD-MM-YY HH24:MI:SS') and xdc.doc_partition_date < to_date('25-02-20 09:20:00', 'DD-MM-YY HH24:MI:SS') ) xdc2 ) xdc3 where xdc3.doc_payload like '%16720284%' or xdc3.doc_payload like '%9F630D36DD24214EE053082D260AB792%'
In this example I do a scan over documents between a certain period where I filter over contents from the blob. Notice that database need to unparse the blob of every row to be able to filter on it. You should not do this over the complete table.
No comments:
Post a Comment