Wednesday, September 23, 2009

The strange case of DBMS_AQ.DEQUEUE_ARRAY returning zero messages

Always check out the original article at http://www.oraclequirks.com for latest comments, fixes and updates.

After a fortnight spent working with DBMS_AQ and DBMS_AQADM packages, i'd be ready to feed oraclequirks with interesting situations for days, if not weeks if only i had enough time to do so.
Unfortunately i am rather busy sorting out some important stuff before leaving or OOW 2009, so i decided to pick one of my favorite AQ (Advanced Queuing) quirks concerning bulk dequeuing of messages, via DBMS_AQ.DEQUEUE_ARRAY in Oracle 10gR2 (XE on Xubuntu linux), as this situation may easily drive you mad.

create or replace
procedure MESSAGE_READER as
dequeue_options dbms_aq.dequeue_options_t;
msg_prop_in_array dbms_aq.message_properties_array_t;
msgid_in_array dbms_aq.msgid_array_t;
type payload_array is varray(30) of payload_type;
msg_in_array payload_array;
l_msgs_in pls_integer;
begin
msg_prop_in_array := dbms_aq.message_properties_array_t();
msg_in_array := payload_array();
msgid_in_array := dbms_aq.msgid_array_t();

dequeue_options.navigation := DBMS_AQ.FIRST_MESSAGE;
dequeue_options.consumer_name := 'MESSAGE_READER';
dequeue_options.wait := DBMS_AQ.NO_WAIT;

l_msgs_in := dbms_aq.dequeue_array(
queue_name => 'INBOX',
dequeue_options => dequeue_options,
array_size => 30,
message_properties_array => msg_prop_in_array,
payload_array => msg_in_array,
msgid_array => msgid_in_array);

...
end;
The most interesting property of this procedure is that it runs without raising any errors, but simply doesn't dequeue any messages from the queue.
So, you see you queue full of messages in READY state, but the procedure doesn't pull out any data.
The value returned by DBMS_AQ.DEQUEUE_ARRAY function and stored into variable l_msgs_in remains zero and the collection remains empty, however no exceptions are raised.

While i felt that something weird must be going on behind the scenes, i did not figure out the solution until i read this thread on OTN.
As soon as i declared the type as a stand-alone SQL type, in contrast with the PL/SQL declaration above (in red color), the procedure started working properly.

create type type payload_array as varray(30) of payload_type;

create or replace
procedure MESSAGE_READER as
dequeue_options dbms_aq.dequeue_options_t;
msg_prop_in_array dbms_aq.message_properties_array_t;
msgid_in_array dbms_aq.msgid_array_t;
msg_in_array payload_array;
l_msgs_in pls_integer;
begin
msg_prop_in_array := dbms_aq.message_properties_array_t();
msg_in_array := payload_array();
msgid_in_array := dbms_aq.msgid_array_t();

dequeue_options.navigation := DBMS_AQ.FIRST_MESSAGE;
dequeue_options.consumer_name := 'MESSAGE_READER';
dequeue_options.wait := DBMS_AQ.NO_WAIT;

l_msgs_in := dbms_aq.dequeue_array(
queue_name => 'INBOX',
dequeue_options => dequeue_options,
array_size => 30,
message_properties_array => msg_prop_in_array,
payload_array => msg_in_array,
msgid_array => msgid_in_array);

...
end;
Don't ask me why.
I ignore if this problem or bug, whatever we wanna call it, has been fixed in subsequent releases and/or it affects all platforms.

3 comments:

Fahd Mirza said...

Interesting....

Byte64 said...

i was lucky enough to quickly find the answer on OTN, it's the kind of problem that makes you spend hours asking yourself what the hell is wrong with the code that is identical to the sample taken from the documentation.

Anonymous said...

This has helped me a lot after cracking my head for almost 2 days. Thanks alot for this post. Funny this issue has still not been fixed(if it's actually a bug)

yes you can!

Two great ways to help us out with a minimal effort. Click on the Google Plus +1 button above or...
We appreciate your support!

latest articles