Page 474
You should use these return codes for proper error checking and error handling.
Using the RECEIVE_MESSAGE Function
The RECEIVE_MESSAGE function moves a message from the pipe to the message buffer. Then
the datatype can be identified with NEXT_ITEM_TYPE, or you could use
UNPACK_MESSAGE to read the message buffer and use in your process.
The Syntax for the RECEIVE_MESSAGE Function
The format for RECEIVE_MESSAGE is
FUNCTION RECEIVE_MESSAGE(name_of_pipe IN VARCHAR2, timeout IN INTEGER DEFAULT maxwait); RETURN INTEGER;
name_of_pipe is the name of the pipe already in existence. timeout is how long it will attempt to read the next line from the pipe if there are no current messages in the pipe. The possible return codes are listed in Table 19.9.
Table 19.9. Return values from RECEIVE_MESSAGE.
Return Code | Meaning |
0 | The message was received successfully. |
1 | The maximum wait time has been exceeded while waiting for a message to be sent to the pipe. |
2 | The message in the pipe is too big for the message buffer. This should never occur because both SEND_MESSAGE and RECEIVE_MESSAGE buffers are limited to the same length of |
4096 bytes. | 3 |
The message being received was interrupted. |
The UNPACK_MESSAGE Procedure
After you have received a message in the buffer, you need to move the message from the
buffer into a variable. This is done through the use of the
UNPACK_MESSAGE procedure. As with the PACK_MESSAGE procedure, the
UNPACK_MESSAGE procedure is overloaded, and can accept
such datatypes as VARCHAR2, DATE, and NUMBER.
The Syntax for the UNPACK_MESSAGE Procedure
The syntax of the procedure is
PROCEDURE UNPACK_MESSAGE(data OUT VARCHAR2); PROCEDURE UNPACK_MESSAGE(data OUT DATE); PROCEDURE UNPACK_MESSAGE(data OUT NUMBER);
Page 475
data is the data that you are receiving from the message buffer. You can receive two possible errors when trying to unpack the message, which are
ORA-06556 the pipe is empty, cannot fulfill the UNPACK_MESSAGE request ORA-06559 wrong datatype requested, datatype, actual datatype is datatype
Both can be handled through error message handlers. The first error occurs when you try to read the message buffer, which is empty. The second error message says that the datatype that you are requesting is a different datatype than the one stored in the pipe. You would most likely not have this problem if the datatype in the pipe is always the same, but if it can vary, you would use the NEXT_ITEM_TYPE function to determine the datatype of the next item in the buffer before you retrieve it.
The format for NEXT_ITEM_TYPE function is
FUNCTION NEXT_ITEM_TYPE RETURN INTEGER;
There are no parameters required to send to the function. It returns a value of the datatype, which is listed in Table 19.10.
Table 19.10. Return datatype definitions from NEXT_ITEM_TYPE.
Return Code | Description |
0 | No more items |
6 | NUMBER |
9 | VARCHAR2 |
11 | ROWID |
12 | DATE |
13 | RAW |
You can use the NEXT_ITEM_TYPE function for exception handling for no data in the pipe, as well as for determining the type of data being passed to you from the message buffer. This can easily be implemented with a series of IF...ELSIF statements.
The REMOVE_PIPE Function
After you no longer need a pipe, you can either wait for the system to eventually delete
the pipe, or you can use the REMOVE_PIPE function.
The Syntax for the REMOVE_PIPE Function The syntax for the function is
FUNCTION REMOVE_PIPE(name_of_pipe IN VARCHAR2); RETURN INTEGER; -- Status on pipe deletion
Page 476
The return value is 0 whether the pipe exists or not. The only exception you will receive is ORA-23322, which means that you don't have access to remove the pipe. When a pipe is removed, all messages stored in the pipe are also deleted.
This section demonstrates the use of pipes by creating both a public and a private pipe and then extracting the data from both pipes and displaying it to the screen.
Creating Public and Private Pipes
To create the public and private pipes, enter and execute the code in Listing 19.21.
Before you execute the code, make sure that you type
SET SERVEROUTPUT ON to see output from the DBMS_OUTPUT package.
INPUTListing 19.21. Creating pipes.
1: DECLARE 2: v_statpipe1 integer; -- Status for private pipe 3: v_statpipe2 integer; -- Status for public pipe created on-the-fly 4: v_pubchar VARCHAR2(100) := `This is a text string'; 5: v_pubdate DATE := SYSDATE; 6: v_pubnum NUMBER := 109; 7: BEGIN 8: -- Creates Private Pipe 9: v_statpipe1 := DBMS_PIPE.CREATE_PIPE(`myprivatepipe'); 10: -- If the pipe was successfully created 11: IF (v_statpipe1 = 0) THEN 12: DBMS_PIPE.PACK_MESSAGE(`privateline1'); 13: DBMS_PIPE.PACK_MESSAGE(`privateline2'); 14: -- Send Message Buffer to Private Pipe 15: v_statpipe1 := DBMS_PIPE.SEND_MESSAGE(`myprivatepipe'); 16: END IF; 17: 18: DBMS_PIPE.PACK_MESSAGE(v_pubchar); -- sends datatype VARCHAR2 19: DBMS_PIPE.PACK_MESSAGE(v_pubdate); -- sends datatype DATE 20: DBMS_PIPE.PACK_MESSAGE(v_pubnum); -- sends datatype NUMBER 21: --Creates public pipe and sends message buffer to the pipe 22: v_statpipe2 := DBMS_PIPE.SEND_MESSAGE(`mypublicpipe'); 23: --Check status of both pipes to make sure they're 0 (created properly) 24: DBMS_OUTPUT.PUT_LINE(`The Status of your Private Pipe is: ` || 25: v_statpipe1 ); 26: DBMS_OUTPUT.PUT_LINE(`The Status of your Public Pipe is: ` || 27: v_statpipe2 ); 28: 29: END;
After the code has executed, if you have all permissions to the DBMS_PIPE package, then you should see the following output:
Page 477
OUTPUTThe Status of your Private Pipe is: 0 The Status of your Public Pipe is: 0
ANALYSIS In this example, the program first creates a private pipe called myprivatepipe in line 9. It then sends two messages of type VARCHAR2 to the message buffer and then uses SEND_MESSAGE in line 15 to output the buffer to the pipe. The only error checking done here is to make sure that the private pipe is created properly in line 11. Ideally, you should check for overflows of the message buffer and whether the data was sent to the pipe (pipe not full, and so on).
The program then sends more data to the message buffer of type VARCHAR2, DATE, and NUMBER in lines 18 through 20, and upon execution of SEND_MESSAGE in line 22, it creates the public pipe mypublicpipe. The DBMS_OUTPUT package will then display the status of the newly created pipes in lines 24 through 27.
Reading Data from the Pipes You can now prepare to read data from both pipes. Enter and execute the code in Listing 19.22. Again, make sure that you have typed SET SERVEROUTPUT ON for proof that the pipes worked.
INPUTListing 19.22. Reading data from the private and public pipe.
1: DECLARE 2: v_statpipe1 integer; -- status of private pipe 3: v_statpipe2 integer; -- status of public pipe 4: v_holdtype INTEGER; -- holds status of next item type 5: v_holdchar VARCHAR2(100); 6: v_holddate DATE; 7: v_holdnum NUMBER; 8: BEGIN 9: -- start procedure of getting message from private pipe 10: v_statpipe1 := DBMS_PIPE.RECEIVE_MESSAGE(`myprivatepipe',15); 11: DBMS_PIPE.UNPACK_MESSAGE(v_holdchar); 12: DBMS_OUTPUT.PUT_LINE(v_holdchar);--display 1st datatype from msg 13: DBMS_PIPE.UNPACK_MESSAGE(v_holdchar); 14: DBMS_OUTPUT.PUT_LINE(v_holdchar);--display 2nd datatype from msg 15: 16: -- start procedure of getting message from public pipe 17: v_statpipe2 := DBMS_PIPE.RECEIVE_MESSAGE(`mypublicpipe',10); 18: LOOP 19: v_holdtype := DBMS_PIPE.NEXT_ITEM_TYPE; 20: IF v_holdtype = 0 THEN EXIT; 21: ELSIF v_holdtype = 6 THEN 22: DBMS_PIPE.UNPACK_MESSAGE(v_holdnum); 23: ELSIF v_holdtype = 9 THEN 24: DBMS_PIPE.UNPACK_MESSAGE(v_holdchar); 25: ELSIF v_holdtype = 12 THEN 26: DBMS_PIPE.UNPACK_MESSAGE(v_holddate); 27: END IF;
continues