Listen to Advanced Oracle Queue (AQ) - go

I'm checking Go ability to migrate an existing C++ application.
One of the main task is to listen actively (no polling) an Advanced Oracle Queue.
In Java and C++ there are existing libraries supporting it since a long time.
I could not find anything similar in Go (libraries & examples).
Could you help me with that?

I have an implementation whereby I'm using the "gopkg.in/goracle.v2" package to connect to Oracle, along with the generic Go library "database/sql".
The way I did it, I have the code to read from the AQ in a PL/SQL procedure which I'm calling from my Go code. Although this is not the best approach - and I'm actually going to change it so that it doesn't rely on a stored oracle procedure - it works. The code looks something like the following:
Oracle PL/SQL proc:
PROCEDURE GetAQMessage ( out_content OUT VARCHAR2, in_acknowledge IN VARCHAR2 DEFAULT 'N' )
IS
dyn_sql VARCHAR2(32000);
l_content VARCHAR2(4000);
BEGIN
dyn_sql := '
DECLARE
l_payload MESSAGE_TYPE := MESSAGE_TYPE (NULL);
l_msg_id RAW(16);
l_dequeue_options DBMS_AQ.DEQUEUE_OPTIONS_T;
l_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;
BEGIN
DBMS_AQ.DEQUEUE(
queue_name => '''|| v_queue_name ||''',
dequeue_options => l_dequeue_options,
message_properties => l_message_properties,
payload => l_payload,
msgid => l_msg_id
);
:b_output := l_payload.message;
END;';
EXECUTE IMMEDIATE dyn_sql USING OUT l_content;
-- Return the content to the OUT parameter
out_content := l_content;
-- Permanently removes the message from the Queue
IF in_acknowledge = 'Y' THEN
COMMIT;
END IF;
END GetAQMessage;
Go code:
func GetAQMessage(transaction *sql.Tx) (string, error) {
var outResult string
var resErr error
var debug int
configuration = conf.Read()
//Run the command
_, resErr = transaction.Exec(`BEGIN CONSENT.GETAQMESSAGE(:1,:2) ; END;`, sql.Out{Dest: &outResult}, "N")
return outResult, resErr
}

Related

Access Oracle Apex Application Settings from PL/SQL

I've created an apex application setting FOO with value bar following these instructions.
When I try to access the setting from the SQL Workshop > SQL Commands page I see
Requested Application Setting #FOO# is not defined. Here is the SQL command I am running to retrieve the value:
declare
l_value varchar2(4000);
begin
l_value := APEX_APP_SETTING.GET_VALUE( p_name => 'FOO');
dbms_output.put_line(l_value);
end;
Any idea why this won't work?
Since you are not executing the code from within an APEX session, you need create an APEX session or attach yourself to to an existing APEX session otherwise there is no way to know what workspace/application to get the setting from. If the code was running from within a page, then your existing code would work.
Try executing the code below, but modify your APP ID and PAGE ID to an actual app/page within your APEX application. The username does not matter.
DECLARE
l_value VARCHAR2 (4000);
BEGIN
apex_session.create_session (p_app_id => 100, p_page_id => 2, p_username => 'any_username');
l_value := APEX_APP_SETTING.GET_VALUE (p_name => 'FOO');
DBMS_OUTPUT.put_line (l_value);
apex_session.delete_session;
END;
If you want to try building a function to return the setting value, I would recommend building a function like this
CREATE OR REPLACE FUNCTION FN_APP_CONFIG (
p_setting_name APEX_190200.WWV_FLOW_APP_SETTINGS.NAME%TYPE,
p_app_id APEX_190200.WWV_FLOW_APP_SETTINGS.FLOW_ID%TYPE DEFAULT APEX_APPLICATION.g_flow_id)
RETURN APEX_190200.WWV_FLOW_APP_SETTINGS.VALUE%TYPE
IS
l_value APEX_190200.WWV_FLOW_APP_SETTINGS.VALUE%TYPE;
BEGIN
SELECT VALUE
INTO l_value
FROM APEX_190200.WWV_FLOW_APP_SETTINGS
WHERE flow_id = p_app_id AND name = p_setting_name;
RETURN l_value;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
RETURN NULL;
WHEN TOO_MANY_ROWS
THEN
RETURN NULL;
END;
/

Generate the URL of a Remote File using PL/SQL

I created a Concurrent Program that creates an Excel File from a long, parametrized query using PL/SQL.
Once the Program successfully completes, the file is placed in the remote server's directory and is usually around 4 MB in Size.
I'm thinking of an approach to notify the requestor and enable him/her to save the file to their local directory.
However, I cannot use UTL_MAIL to attach and send the file via email due to the 32 Kilobyte Limitation. (Does UTL_MAIL have an attachment limit of 32k).
In the same post, Tom Kyte preferred approach would be to:
store the attachment to the database.
email a very small email with a link. the link points to my database - using a URL.
With that, i was thinking taking the same approach and use the block below to notify the requestor and enable him/her to download the said Excel file:
declare
l_url_link varchar2(100); -- how can i get the URL of the File?
BEGIN
UTL_MAIL.SEND(sender => 'xxx#oracle.com'
, recipients => 'Migs.Isip.23#Gmail.com'
, subject => 'Testmail'
, message => 'Your File is Ready to be downloaded, click the link here: '||l_url_link);
END;
My Questions would be:
How can i generate the "URL" of the Remote file using PL/SQL?
Do the users need to be granted access to the remote server to download the file?
Thank you!
Oracle Database Version:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
"CORE 11.2.0.4.0 Production"
TNS for Solaris: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
Here is a pl/sql function I wrote to retrieve the URL of either the concurrent log file or output file. If you write your Excel file to the concurrent output, this should work fine. Let me know how you get on. I have not checked to see if this will give the correct mime-type or extension - not sure how EBS handles this but the function itself will definitely compile as is for 12.1.3.
Spec
FUNCTION get_concurrent_url (p_file_type IN VARCHAR2
,p_request_id IN NUMBER
,p_expiry IN NUMBER)
RETURN VARCHAR2;
Body
/* Get a URL to view the log/output
File Type is LOG or OUT
Request ID is the concurrent request ID
Expiry is in minutes */
FUNCTION get_concurrent_url (p_file_type IN VARCHAR2
,p_request_id IN NUMBER
,p_expiry IN NUMBER)
RETURN VARCHAR2
IS
CURSOR c_gwyuid
IS
SELECT profile_option_value
FROM fnd_profile_options FPO
,fnd_profile_option_values FPOV
WHERE FPO.profile_option_name = 'GWYUID'
AND FPO.application_id = FPOV.application_id
AND FPO.profile_option_id = FPOV.profile_option_id;
CURSOR c_two_task
IS
SELECT profile_option_value
FROM fnd_profile_options FPO
,fnd_profile_option_values FPOV
WHERE FPO.profile_option_name = 'TWO_TASK'
AND FPO.application_id = FPOV.application_id
AND FPO.profile_option_id = FPOV.profile_option_id;
l_request_id NUMBER;
l_file_type VARCHAR2 (3 BYTE);
l_expiry NUMBER;
l_two_task VARCHAR2 (100 BYTE);
l_gwyuid VARCHAR2 (100 BYTE);
l_url VARCHAR2 (1024 BYTE);
BEGIN
l_request_id := p_request_id;
l_file_type := p_file_type;
l_expiry := p_expiry;
FOR i IN c_gwyuid LOOP
l_gwyuid := i.profile_option_value;
END LOOP;
FOR i IN c_two_task LOOP
l_two_task := i.profile_option_value;
END LOOP;
IF l_file_type = 'LOG' THEN
l_url := fnd_webfile.get_url
(file_type => fnd_webfile.request_log
,id => l_request_id
,gwyuid => l_gwyuid
,two_task => l_two_task
,expire_time => l_expiry);
ELSE
l_url := fnd_webfile.get_url
(file_type => fnd_webfile.request_out
,id => l_request_id
,gwyuid => l_gwyuid
,two_task => l_two_task
,expire_time => l_expiry);
END IF;
RETURN l_url;
END get_concurrent_url;
I was able to find a solution for this using a (slightly different) method using the FND_GFM File Uploader Package in Oracle EBS.
FND_GFM is a package usually used in Oracle EBS when uploading files from the front-end application pages.
First, generate the Excel file (xlsx) using the code from the previous post: Create an Excel File (.xlsx) using PL/SQL,
Then the file is inserted into FND_LOBS and removed the from the OS (for good housekeeping), and finally sent as an email using UTL_FILE:
procedure generate_and_send_excel
is
l_content varchar2(250);
l_file_url varchar2(4000);
l_directory varchar2(250);
l_filename varchar2(250);
l_message clob;
l_instance varchar2(100);
l_ebs_url varchar2(100);
begin
/* your excel generation code here */
l_content := 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
l_directory := 'EXT_TAB_DATA';
l_filename := 'report.xlsx';
select instance_name
into l_instance
from v$instance;
select home_url
into l_ebs_url
from icx_parameters;
IMPORT_TO_LOB (p_file_name => l_filename -- this is the actual filename of the saved OS File
, p_directory => l_directory -- should be a defined directory in the Database
, p_content_type => l_content -- standard for Excel Files
, p_program_name => 'your prog here'
, p_program_tag => 'your prog here'
, p_file_url => l_file_url); -- this will be the generated URL of your File
utl_file.fremove(l_directory, l_filename);
l_message := l_message||'<h2 style="color: #5e9ca0;">'||l_title||'</h2>';
l_message := l_message||'<h3 style="color: #2e6c80;">Report is Ready for Download: '||l_filename||'</h3>';
l_message := l_message||'<p>File was generated on '|| sysdate ||' from '||l_instance||'</p>';
l_message := l_message||'<strong>Regards,</strong><br/><strong>Sample Team</strong>';
l_message := l_message||'<br/>Sample#sample.com';
UTL_MAIL.SEND(sender => 'SAMPLE#SAMPLE.com'
, recipients => 'Migs.Isip.23#gmail.com'
, subject => 'Hello message'
, message => l_message
, mime_type => 'text/html; charset=us-ascii');
end generate_and_send_excel;
Procedure below to insert into FND_LOBS (there's no available seeded API):
Procedure IMPORT_TO_LOB (p_file_name IN FND_LOBS.FILE_NAME%TYPE
, p_directory IN dba_directories.directory_name%type
, p_content_type IN FND_LOBS.file_content_type%type
, p_program_name IN FND_LOBS.program_name%type
, p_program_tag IN FND_LOBS.program_tag%type
, p_language IN FND_LOBS.language%type default 'US'
, p_file_format IN FND_LOBS.file_format%type default 'binary'
, p_file_url OUT varchar2)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
lBlob BLOB;
lFile BFILE := BFILENAME(p_directory, p_file_name);
L_ORA_CHARSET VARCHAR2(100);
P_COUNT NUMBER;
BEGIN
SELECT value
into l_ora_charset
FROM nls_database_parameters
where parameter = 'NLS_CHARACTERSET';
insert into FND_LOBS
(
file_id
, file_name
, file_content_type
, file_data
, upload_date
, expiration_date
, program_name
, program_tag
, LANGUAGE
, oracle_charset
, file_format
)
values
(
fnd_lobs_s.NEXTVAL -- FILE_ID
, p_file_name -- FILE_NAME
, p_content_type -- FILE_CONTENT_TYPE
, EMPTY_BLOB() -- FILE_DATA
, sysdate -- UPLOAD_DATE
, NULL -- EXPIRATION_DATE
, p_program_name -- PROGRAM_NAME
, p_program_tag -- PROGRAM_TAG
, p_language -- LANGUAGE
, l_ora_charset -- ORACLE_CHARSET
, p_file_format -- FILE_FORMAT
)
RETURNING file_data INTO lBlob;
DBMS_LOB.OPEN(lFile, DBMS_LOB.LOB_READONLY);
DBMS_LOB.OPEN(lBlob, DBMS_LOB.LOB_READWRITE);
DBMS_LOB.LOADFROMFILE(DEST_LOB => lBlob,
SRC_LOB => lFile,
AMOUNT => DBMS_LOB.GETLENGTH(lFile));
DBMS_LOB.CLOSE(lFile);
DBMS_LOB.CLOSE(lBlob);
commit;
p_file_url := fnd_gfm.construct_download_url (fnd_web_config.gfm_agent, fnd_lobs_s.currval);
END IMPORT_TO_LOB;
Note that this is an AUTONOMOUS_TRANSACTION so it needs to be committed before returning to the calling package/block.
Hope that Helps!

PLSQL function if not available do else

In my oracle 11 environment I have declared following function (successfully, no errors).
create or replace function s2_encrypt(paramToEncrypt in VARCHAR2, encrypt8BYTEKey in RAW)
return RAW is encryptedReturnValue RAW (2000);
encryptionMode number := DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
begin
encryptedReturnValue := dbms_crypto.encrypt(UTL_I18N.STRING_TO_RAW(paramToEncrypt, 'AL32UTF8'), encryptionMode, encrypt8BYTEKey);
return encryptedReturnValue;
end;
/
found here: http://anujktyagi.blogspot.ch/2012/12/oracle-using-dbmscrypto-package-for.html
I am deploying this on several servers, some of which only run Oracle version 8 / 9 -> in which case I want to just copy the value (instead of decrypting it).
How would I extend the above function so that it can be deployed both in Oracle 10+ and lower (in later case just copy paste the value and not encrypt)?
Something like
create or replace function s2_encrypt(paramToEncrypt in VARCHAR2, encrypt8BYTEKey in RAW)
return RAW is encryptedReturnValue RAW (2000);
encryptionMode number := DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
begin
...
if !dbms_crypto.encrypt exit ???
...
encryptedReturnValue := dbms_crypto.encrypt(UTL_I18N.STRING_TO_RAW(paramToEncrypt, 'AL32UTF8'), encryptionMode, encrypt8BYTEKey);
return encryptedReturnValue;
end;
/
You can use conditional compilation
using package DBMS_DB_VERSION or some of your constants
$IF DBMS_DB_VERSION.ver_le_9_1 $THEN
return paramToEncrypt ;
$ELSE
encryptedReturnValue := dbms_crypto.encrypt(UTL_I18N.STRING_TO_RAW(paramToEncrypt, 'AL32UTF8'), encryptionMode, encrypt8BYTEKey);
return encryptedReturnValue;
$END
The most sensible approach would be to use two separate versions of the function - one for version 8/9 and one for 10.
That being said, the following approach should work (untested, I don't have access to any instances running Oracle 10 or lower):
check the database version (either by checking the existence of DBMS_DB_VERSION or by parsing the output of PRODUCT_COMPONENT_VERSION or V$VERSION which - to the best of my knowledge - already existed in version 8).
use dynamic SQL to either call dbms_crypto or return the string unchanged (since your package won't compile on 8/9 if you reference dbms_crypto directly)
Example (untested):
create or replace function s2_encrypt(paramToEncrypt in VARCHAR2,
encrypt8BYTEKey in RAW) return RAW is
encryptedReturnValue RAW(2000);
objectCount pls_integer;
begin
select count(*)
into objectCount
from all_objects
where object_name = 'DBMS_CRYPTO';
-- Oracle 8/9: return string unchanged
if objectCount = 0 then
encryptedReturnValue := paramToEncrypt;
else
execute immediate '
declare
encryptionMode number := DBMS_CRYPTO.ENCRYPT_AES128 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5;
begin
:encryptedReturnValue := dbms_crypto.encrypt(UTL_I18N.STRING_TO_RAW(:paramToEncrypt, ''AL32UTF8''), encryptionMode, :encrypt8BYTEKey);
end;'
using out encryptedReturnValue, in paramToEncrypt, in encrypt8BYTEKey;
end if;
return encryptedReturnValue;
end;
Usage (11g - 8i apparently did not have UTL_I18N, see comments)
select s2_encrypt(
'hello world',
UTL_I18N.STRING_TO_RAW ('8232E3F8BDE7703C', 'AL32UTF8'))
from dual;
You can use Conditional Compilation available from Oracle 10g Release 1.
See https://oracle-base.com/articles/10g/conditional-compilation-10gr2
In older versions you can just use a normal IF-ELSE statement
DECLARE
v1 VARCHAR2 (10);
v2 VARCHAR2 (10);
BEGIN
DBMS_UTILITY.db_version (v1, v2);
IF SUBSTR (v1, 1, INSTR (v1, '.', 1)-1) < 10 THEN
returnvalue paramToEncrypt;
ELSE
returnValue := dbms_crypto.encrypt(UTL_I18N.STRING_TO_RAW(paramToEncrypt, 'AL32UTF8'), encryptionMode, encrypt8BYTEKey);
END;
return returnValue;
END;

Is there a fast way to clear Exception queue from Oracle AQ?

AQ$_MESSAGES_EXCEPTIONFirst of all I know there's this question: How to clear a queue in Oracle AQ but it doesn't have an answer.
I have a lot of messages(500k) in the exception queue in the Oracle AQ(I didn't know expired messages are moved to another queue so I didn't create a consumer for those). What I need now is to be able to delete those messages fast. I've read that it's not a good idea to clear the queue table via delete, because it could lead to inconsistent state. So I've put together following procedure, but it only clears about 50 messages/second
EXECUTE dbms_aqadm.start_queue(queue_name => 'AQ$_MESSAGES_EXCEPTION',
enqueue => FALSE, dequeue => TRUE);
DECLARE
dequeue_options DBMS_AQ.dequeue_options_t;
message_properties DBMS_AQ.message_properties_t;
message_handle RAW(16);
message SYS.AQ$_JMS_MESSAGE;
no_messages EXCEPTION;
pragma exception_init (no_messages, -25228);
BEGIN
dequeue_options.wait := DBMS_AQ.NO_WAIT;
dequeue_options.navigation := DBMS_AQ.FIRST_MESSAGE;
LOOP
DBMS_AQ.DEQUEUE(
queue_name => 'AQ$_MESSAGES_EXCEPTION',
dequeue_options => dequeue_options,
message_properties => message_properties,
payload => message,
msgid => message_handle);
DBMS_OUTPUT.put_line ('Message: ' || message_handle || ' dequeued');
END LOOP;
EXCEPTION
WHEN no_messages THEN
DBMS_OUTPUT.put_line (' ---- NO MORE MESSAGES ---- ');
WHEN others then
DBMS_OUTPUT.put_line ('Exception queue not started for dequeue.');
END;
/
It seems really slow considering it's running on the database machine. This procedure takes about three hours with 500k messages. Can I do it in some more effective manner?
EDIT:
I tried the dequeue_array from the link here: http://www.oracle-developer.net/display.php?id=319
But I can't create the tables, so I'm trying to create an array to "store" the results.
Here's what I've got:
DECLARE
type messages_type is varray(500) of SYS.AQ$_JMS_MESSAGE;
messages messages_type;
dequeue_options DBMS_AQ.dequeue_options_t;
msg_properties DBMS_AQ.message_properties_array_t;
msg_ids DBMS_AQ.MSGID_ARRAY_T;
x_timeout EXCEPTION;
no_messages EXCEPTION;
dequeue_batch PLS_INTEGER := 500;
pragma exception_init (no_messages, -25228);
BEGIN
messages := messages_type();
msg_properties := DBMS_AQ.MESSAGE_PROPERTIES_ARRAY_T();
msg_properties.EXTEND(dequeue_batch);
msg_ids := DBMS_AQ.MSGID_ARRAY_T();
dequeue_options.wait := 5;
LOOP
DBMS_AQ.DEQUEUE_ARRAY(
queue_name => 'AQ$_MESSAGES_EXCEPTION',
dequeue_options => dequeue_options,
array_size => dequeue_batch,
message_properties_array => msg_properties,
payload_array => messages,
msgid_array => msg_ids);
...
I'm getting this error:
wrong number or types of arguments in call to 'DEQUEUE_ARRAY'
I think the problem is in the messages array, but I don't know what to do to make it work. Also, according to oracle doc(http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_aq.htm#i1000850), there should be another parameter:
error_array OUT error_array_t
But the explanation for this parameter is "Currently not implemented". What does it mean? Can it be left out? Should it be set to null? This is really confusing and google doesn't help here :(
If you really want to dequeue, you could probably use the dequeue_array(n) function. That should be much faster.
but the link you provide does have the solution :
-- purge queue
DECLARE
po_t dbms_aqadm.aq$_purge_options_t;
BEGIN
dbms_aqadm.purge_queue_table('MY_QUEUE_TABLE', NULL, po_t);
END;
Otherwise, since this exception queue is created automatically,
I guess you could just drop it, but I am not sure if that is safe
BEGIN
DBMS_AQADM.STOP_QUEUE(
queue_name => 'demo_queue'
);
DBMS_AQADM.DROP_QUEUE(
queue_name => 'demo_queue'
);
DBMS_AQADM.DROP_QUEUE_TABLE(
queue_table => 'demo_queue_table'
);
END;
You can use procedure "purge_queue_table" (as #Stephane said) from dbms_aqadm package but with "purge_condition" parameter specified , with this parameter you can select which messages you delete :
Example :
declare
purge_options dbms_aqadm.aq$_purge_options_t;
begin
purge_options.block := false;
purge_options.delivery_mode := dbms_aqadm.persistent;
dbms_aqadm.purge_queue_table
(queue_table => 'vista.svig_std_tab',
purge_condition => 'qtview.queue = ''AQ$_SVIG_STD_TAB_E'' and qtview.enq_time < to_date(''01.06.2014 00:00:00'',''dd.mm.yyyy hh24:mi:ss'') ',
purge_options => purge_options
);
end;
/
This example deletes messages that are from the specified exception queue and are older than the specified date. It also does this in a much quicker fashion than using "dbms_aq.dequeue" procedure.

How to determine payload type for DBMS_AQ.DEQUEUE_ARRAY

I am attempting to use the function DBMS_AQ.DEQUEUE_ARRAY in Oracle 10.2.0.4.0. to browse the contents of a queue. Is there a way to determine the type to use for the message array? Is there some "generic" type I could be using? What I'm attempting is as follows:
CREATE or REPLACE TYPE I_NEED_THIS_TYPE AS ????
/
CREATE or REPLACE myFunction
return pls_integer
IS
dequeue_options DBMS_AQ.dequeue_options_t;
message_properties DBMS_AQ.message_properties_t;
msgPropArray DBMS_AQ.message_properties_array_t;
msgIdArray DBMS_AQ.msgid_array_t;
msgArray I_NEED_THIS_TYPE;
cMsgs pls_integer;
BEGIN
msgPropArray := DBMS_AQ.message_properties_array_t();
msgIdArray := dbms_aq.msgid_array_t();
msgArray := I_NEED_THIS_TYPE();
--where SOME_NAME and SOME_QUEUE_TABLE I get from
--select owner,name from user_queues;
dequeue_options.CONSUMER_NAME := 'SOME_NAME.SOME_QUEUE_TABLE';
dequeue_options.DEQUEUE_MODE := DBMS_AQ.BROWSE;
dequeue_options.NAVIGATION := DBMS_AQ.FIRST_MESSAGE;
dequeue_options.VISIBILITY := DBMS_AQ.IMMEDIATE;
dequeue_options.WAIT := DBMS_AQ.NO_WAIT;
dequeue_options.MSGID := null;
cMsgs := DBMS_AQ.DEQUEUE_ARRAY(
queue_name => 'MY_QUEUE_NAME',
dequeue_options => dequeue_options,
array_size => 30,
message_properties => msgPropArray,
payload_array => msgArray,
msgid_array => msgIdArray);
return cMsgs;
END;
/
I have tried numerous combinations of
CREATE or REPLACE TYPE I_NEED_THIS_TYPE AS VARRAY(100) of CLOB;
CREATE or REPLACE TYPE I_NEED_THIS_TYPE AS VARRAY(100) of SYS.xmltype;
CREATE or REPLACE TYPE I_NEED_THIS_TYPE AS VARRAY(100) of xmltype;
CREATE or REPLACE TYPE I_NEED_THIS_TYPE AS OBJECT(
id NUMBER,
xmlData CLOB
)
DECLARE
TYPE assoc_array is TABLE OF CLOB index by pls_integer;
myData assoc_array;
I AM able to use the DBMS_AQ.DEQUEUE function as expected, the message parameter for that is SYS.xmltype.
I am unable to use the administrator account, but do have privilieges to create types and functions. If there is no way to determine this information, what type of query should I ask the administrator to run so that I can determine this information?
Thanks!
It's probable your queue was created with a payload type when CREATE_QUEUE_TABLE was run. You can therefore find out the type for the queue by performing this query:
select OBJECT_TYPE
from DBA_QUEUE_TABLES
where OWNER = 'SOME_NAME' and QUEUE_TABLE = 'SOME_QUEUE_TABLE';
Then your function can use this:
type I_NEED_THIS_TYPE is varray(100) of <OBJECT_TYPE>;

Resources