1 package dbms_pipe is
2
3 -- DE-HEAD <- tell SED where to cut when generating fixed package
4
5 ------------
6 -- OVERVIEW
7 --
8 -- This package provides a DBMS "pipe" service which allows messages
9 -- to be sent between sessions.
10 --
11 -- The metaphor is similar to UNIX pipes: you can do
12 -- dbms_pipe.send_message(<pipename>)
13 -- dbms_pipe.receive_message(<pipename>)
14 -- which will cause a message to be sent or received. You do
15 -- dbms_pipe.pack_message(<varchar2>|<number>|<date>)
16 -- to pack an item into a static buffer (which will then be sent with
17 -- the "send_message" call), and
18 -- dbms_pipe.unpack_message(<varchar2>|<number>|<date>)
19 -- to get an item out of the static buffer (which is filled by the
20 -- "receive_message" call).
21 -- Pipes can be private to a user-id - which only allows session connected
22 -- under the same user-id or stored procedure owned by the user-id to read
23 -- write to the pipe. Pipes could be public - and all database users with
24 -- execute privilege on dbms_pipe and knowledge of the pipe can read or
25 -- write to the pipe.
26 --
27 -- Pipes operate independently of transactions. They also operate
28 -- asynchronously. There can be multiple readers and writers of the
29 -- same pipe.
30 --
31 -- Pipes only operate between sessions in the same instance.
32 --
33 -- Pipes can be explicitly created using
34 -- dbms_pipe.create_pipe(<pipename>)
35 -- and removed using
36 -- dbms_pipe.remove_pipe(<pipename>)
37 -- A pipe created using the explicit create command should be removed
38 -- using the remove function. A pipe can also be created implicitly.
39 -- Pipes automatically come into existence the first time they are
40 -- referenced. They effectively disappear when they contain no more
41 -- data (some overhead remains in the SGA until it gets aged out).
42 -- Pipes take up space in the SGA (see "maxpipesize" parameter to
43 -- "send_message").
44
45
46 --------
47 -- USES
48 --
49 -- The pipe functionality has several potential applications:
50 --
51 -- o External service interface. You can provide the ability to
52 -- communicate with (user-written) services that are external to the
53 -- RDBMS. This can be done in a (effectively) multi-threaded manner
54 -- so that several instances of the service can be executing
55 -- simultaneously. Additionally, the services are available
56 -- asynchronously - the requestor of the service need not block
57 -- awaiting a reply. The requestor can check (with or without
58 -- timeout) at a later time. The service can be written in any
59 -- of the 3GL languages that ORACLE supports, not just C. See
60 -- example below.
61 -- o Independent transactions. The pipe can be used to communicate
62 -- to a separate session which can perform an operation in an
63 -- independent transaction (such as logging an attempted security
64 -- violation detected by a trigger).
65 -- o Alerters (non-transactional). You can post another process
66 -- without requiring the waiting process to poll. If an "after-row"
67 -- or "after-statement" trigger were to alert an application, then
68 -- the application would treat this alert as an indication that
69 -- the data probably changed. The application would then go read
70 -- the data to get the current value. Since this is an "after"
71 -- trigger, the application would want to do a "select for update"
72 -- to make sure it read the correct data.
73 -- o Debugging. Triggers and/or stored procedures can send debugging
74 -- information to a pipe. Another session can keep reading out
75 -- of the pipe and displaying it on the screen or writing it
76 -- out to a file.
77 -- o Concentrator. Useful for multiplexing large numbers of users
78 -- over a fewer number of network connections, or improving
79 -- performance by concentrating several user-transactions into
80 -- one dbms-transaction.
81
82
83 ------------
84 -- SECURITY
85 --
86 -- Security can be achieved by use of 'grant execute' on the dbms_pipe
87 -- package, by creating a pipe using the 'private' parameter in the create
88 -- function and by writing cover packages that only expose particular
89 -- features or pipenames to particular users or roles.
90
91
92 ------------
93 -- EXAMPLES
94 --
95 -- External service interface
96 ------------------------------
97 --
98 -- Put the user-written 3GL code into an OCI or Precompiler program.
99 -- The program connects to the database and executes PL/SQL code to read
100 -- its request from the pipe, computes the result, and then executes
101 -- PL/SQL code to send the result on a pipe back to the requestor.
102 -- Below is an example of a stock service request.
103 --
104 -- The recommended sequence for the arguments to pass on the pipe
105 -- for all service requests is
106 --
107 -- protocol_version varchar2 - '1', 10 bytes or less
108 -- returnpipe varchar2 - 30 bytes or less
109 -- service varchar2 - 30 bytes or less
110 -- arg1 varchar2/number/date
111 -- ...
112 -- argn varchar2/number/date
113 --
114 -- The recommended format for returning the result is
115 --
116 -- success varchar2 - 'SUCCESS' if OK,
117 -- otherwise error message
118 -- arg1 varchar2/number/date
119 -- ...
120 -- argn varchar2/number/date
121 --
122 --
123 -- The "stock price request server" would do, using OCI or PRO* (in
124 -- pseudo-code):
125 --
126 -- <loop forever>
127 -- begin dbms_stock_server.get_request(:stocksymbol); end;
128 -- <figure out price based on stocksymbol (probably from some radio
129 -- signal), set error if can't find such a stock>
130 -- begin dbms_stock_server.return_price(:error, :price); end;
131 --
132 -- A client would do:
133 --
134 -- begin :price := stock_request('YOURCOMPANY'); end;
135 --
136 -- The stored procedure, dbms_stock_server, which is called by the
137 -- "stock price request server" above is:
138 --
139 -- create or replace package dbms_stock_server is
140 -- procedure get_request(symbol out varchar2);
141 -- procedure return_price(errormsg in varchar2, price in varchar2);
142 -- end;
143 --
144 -- create or replace package body dbms_stock_server is
145 -- returnpipe varchar2(30);
146 --
147 -- procedure returnerror(reason varchar2) is
148 -- s integer;
149 -- begin
150 -- dbms_pipe.pack_message(reason);
151 -- s := dbms_pipe.send_message(returnpipe);
152 -- if s <> 0 then
153 -- raise_application_error(-20000, 'Error:' || to_char(s) ||
154 -- ' sending on pipe');
155 -- end if;
156 -- end;
157 --
158 -- procedure get_request(symbol out varchar2) is
159 -- protocol_version varchar2(10);
160 -- s integer;
161 -- service varchar2(30);
162 -- begin
163 -- s := dbms_pipe.receive_message('stock_service');
164 -- if s <> 0 then
165 -- raise_application_error(-20000, 'Error:' || to_char(s) ||
166 -- 'reading pipe');
167 -- end if;
168 -- dbms_pipe.unpack_message(protocol_version);
169 -- if protocol_version <> '1' then
170 -- raise_application_error(-20000, 'Bad protocol: ' ||
171 -- protocol_version);
172 -- end if;
173 -- dbms_pipe.unpack_message(returnpipe);
174 -- dbms_pipe.unpack_message(service);
175 -- if service != 'getprice' then
176 -- returnerror('Service ' || service || ' not supported');
177 -- end if;
178 -- dbms_pipe.unpack_message(symbol);
179 -- end;
180 --
181 -- procedure return_price(errormsg in varchar2, price in varchar2) is
182 -- s integer;
183 -- begin
184 -- if errormsg is null then
185 -- dbms_pipe.pack_message('SUCCESS');
186 -- dbms_pipe.pack_message(price);
187 -- else
188 -- dbms_pipe.pack_message(errormsg);
189 -- end if;
190 -- s := dbms_pipe.send_message(returnpipe);
191 -- if s <> 0 then
192 -- raise_application_error(-20000, 'Error:'||to_char(s)||
193 -- ' sending on pipe');
194 -- end if;
195 -- end;
196 -- end;
197 --
198 --
199 -- The procedure called by the client is:
200 --
201 -- create or replace function stock_request (symbol varchar2)
202 -- return varchar2 is
203 -- s integer;
204 -- price varchar2(20);
205 -- errormsg varchar2(512);
206 -- begin
207 -- dbms_pipe.pack_message('1'); -- protocol version
208 -- dbms_pipe.pack_message(dbms_pipe.unique_session_name); -- return pipe
209 -- dbms_pipe.pack_message('getprice');
210 -- dbms_pipe.pack_message(symbol);
211 -- s := dbms_pipe.send_message('stock_service');
212 -- if s <> 0 then
213 -- raise_application_error(-20000, 'Error:'||to_char(s)||
214 -- ' sending on pipe');
215 -- end if;
216 -- s := dbms_pipe.receive_message(dbms_pipe.unique_session_name);
217 -- if s <> 0 then
218 -- raise_application_error(-20000, 'Error:'||to_char(s)||
219 -- ' receiving on pipe');
220 -- end if;
221 -- dbms_pipe.unpack_message(errormsg);
222 -- if errormsg <> 'SUCCESS' then
223 -- raise_application_error(-20000, errormsg);
224 -- end if;
225 -- dbms_pipe.unpack_message(price);
226 -- return price;
227 -- end;
228 --
229 -- You would typically only grant execute on 'dbms_stock_service' to
230 -- the stock service application server, and would only grant execute
231 -- on 'stock_request' to those users allowed to use the service.
232
233
234 ---------------------
235 -- SPECIAL CONSTANTS
236 --
237 maxwait constant integer := 86400000; /* 1000 days */
238 -- The maximum time to wait attempting to send or receive a message
239
240
241 ----------------------------
242 -- PROCEDURES AND FUNCTIONS
243 --
244 procedure pack_message(item in varchar2 character set any_cs);
245 pragma restrict_references(pack_message,WNDS,RNDS);
246 procedure pack_message(item in number);
247 pragma restrict_references(pack_message,WNDS,RNDS);
248 procedure pack_message(item in date);
249 pragma restrict_references(pack_message,WNDS,RNDS);
250 procedure pack_message_raw(item in raw);
251 pragma restrict_references(pack_message_raw,WNDS,RNDS);
252 procedure pack_message_rowid(item in rowid);
253 pragma restrict_references(pack_message_rowid,WNDS,RNDS);
254 -- Pack an item into the message buffer
255 -- Input parameters:
256 -- item
257 -- Item to pack into the local message buffer.
258 -- Exceptions:
259 -- ORA-06558 generated if message buffer overflows (currently 4096
260 -- bytes). Each item in the buffer takes one byte for the type,
261 -- two bytes for the length, plus the actual data. There is also one
262 -- byte needed to terminate the message.
263 --
264 procedure unpack_message(item out varchar2 character set any_cs);
265 pragma restrict_references(unpack_message,WNDS,RNDS);
266 procedure unpack_message(item out number);
267 pragma restrict_references(unpack_message,WNDS,RNDS);
268 procedure unpack_message(item out date);
269 pragma restrict_references(unpack_message,WNDS,RNDS);
270 procedure unpack_message_raw(item out raw);
271 pragma restrict_references(unpack_message_raw,WNDS,RNDS);
272 procedure unpack_message_rowid(item out rowid);
273 pragma restrict_references(unpack_message_rowid,WNDS,RNDS);
274 -- Unpack an item from the local message buffer
275 -- Output parameters:
276 -- item
277 -- The argument to receive the next unpacked item from the local
278 -- message buffer.
279 -- Exceptions:
280 -- ORA-06556 or 06559 are generated if the buffer contains
281 -- no more items, or if the item is not of the same type as that
282 -- requested (see 'next_item_type' below).
283 --
284 function next_item_type return integer;
285 pragma restrict_references(next_item_type,WNDS,RNDS);
286 -- Get the type of the next item in the local message buffer
287 -- Return value:
288 -- Type of next item in buffer:
289 -- 0 no more items
290 -- 9 varchar2
291 -- 6 number
292 -- 11 rowid
293 -- 12 date
294 -- 23 raw
295 --
296 function create_pipe(pipename in varchar2,
297 maxpipesize in integer default 8192,
298 private in boolean default TRUE)
299 return integer;
300 pragma restrict_references(create_pipe,WNDS,RNDS);
301 -- Create an empty pipe with the given name.
302 -- Input parameters:
303 -- pipename
304 -- Name of pipe to be created. WARNING: Do not use pipe names
305 -- beginning with 'ORA$'. These are reserved for use by procedures
306 -- provided by Oracle Corporation. Pipename should not be longer than
307 -- 128 bytes, and is case_insensitive. At this time, the name cannot
308 -- contain NLS characters.
309 -- maxpipesize
310 -- Maximum allowed size for the pipe. The total size of all the
311 -- messages on the pipe cannot exceed this amount. The maxpipesize
312 -- for a pipe becomes part of the pipe and persists for the lifetime
313 -- of the pipe. Callers of send_message with larger values will
314 -- cause the maxpipesize to be increased. Callers with a smaller
315 -- value will just use the larger value. The specification of
316 -- maxpipesize here allows us to avoid its use in future send_message
317 -- calls.
318 -- private
319 -- Boolean indicating whether the pipe will be private - and for the
320 -- use of the creating user-id, or public. A private pipe can be used
321 -- directly through calls to this package by sessions connected to the
322 -- database as the same user as the one that created the pipe. It can
323 -- also be used via stored procedures owned by the user that created
324 -- the pipe. The procedure may be executed by anyone with execute
325 -- privilege on it. A public pipe can be accessed by anyone who has
326 -- knowledge of it and execute privilege on dbms_pipe.
327 -- Return values:
328 -- 0 - Success. This is returned even if the pipe had been created in
329 -- mode that permits its use by the user executing the create call.
330 -- If a pipe already existed, it is not emptied.
331 -- Exceptions:
332 -- Null pipe name.
333 -- Permission error. Pipe with the same name already exists and
334 -- you are not allowed to use it.
338 pragma restrict_references(remove_pipe,WNDS,RNDS);
335 --
336 function remove_pipe(pipename in varchar2)
337 return integer;
339 -- Remove the named pipe.
340 -- Input Parameters:
341 -- pipename
342 -- Name of pipe to remove.
343 -- Return value:
344 -- 0 - Success. Calling remove on a pipe that does not exist returns 0.
345 -- Exceptions:
346 -- Null pipe name.
347 -- Permission error. Insufficient privilege to remove pipe. The
348 -- pipe was created and is owned by someone else.
349 --
350 function send_message(pipename in varchar2,
351 timeout in integer default maxwait,
352 maxpipesize in integer default 8192)
353 return integer;
354 pragma restrict_references(send_message,WNDS,RNDS);
355 -- Send a message on the named pipe. The message is contained in the
356 -- local message buffer which was filled with calls to 'pack_message'.
357 -- A pipe could have been created explicitly using 'create_pipe', or
358 -- it will be created implicitly.
359 -- Input parameters:
360 -- pipename
361 -- Name of pipe to place the message on. The message is copied
362 -- from the local buffer which can be filled by the "pack_message"
363 -- routine. WARNING: Do not use pipe names beginning with 'ORA$'.
364 -- These names are reserved for use by procedures provided by
365 -- Oracle Corporation. Pipename should not be longer than 128 bytes,
366 -- and is case_insensitive. At this time, the name cannot
367 -- contain NLS characters.
368 -- timeout
369 -- Time to wait while attempting to place a message on a pipe, in
370 -- seconds (see return codes below).
371 -- maxpipesize
372 -- Maximum allowed size for the pipe. The total size of all the
373 -- messages on the pipe cannot exceed this amount. If this message
374 -- would exceed this amount the call will block. The maxpipesize
375 -- for a pipe becomes part of the pipe and persists for the lifetime
376 -- of the pipe. Callers of send_message with larger values will
377 -- cause the maxpipesize to be increased. Callers with a smaller
378 -- value will just use the larger value. The specification of
379 -- maxpipesize here allows us to avoid the use of a "open_pipe" call.
380 -- Return value:
381 -- 0 - Success
382 -- 1 - Timed out (either because can't get lock on pipe or pipe stays
383 -- too full)
384 -- 3 - Interrupted
385 -- Exceptions:
386 -- Null pipe name.
387 -- Permission error. Insufficient privilege to write to the pipe.
388 -- The pipe is private and owned by someone else.
389 function receive_message(pipename in varchar2,
390 timeout in integer default maxwait)
391 return integer;
392 pragma restrict_references(receive_message,WNDS,RNDS);
393 -- Receive a message from the named pipe. Copy the message into the
394 -- local message buffer. Use 'unpack_message' to access the
395 -- individual items in the message. The pipe can be created explicitly
396 -- using the 'create_pipe' function or it will be created implicitly.
397 -- Input parameters:
398 -- pipename
399 -- Name of pipe from which to retrieve a message. The message is
400 -- copied into a local buffer which can be accessed by the
401 -- "unpack_message" routine. WARNING: Do not use pipe names
402 -- beginning with 'ORA$'. These names are reserved for use by
403 -- procedures provided by Oracle Corporation. Pipename should not be
404 -- longer than 128 bytes, and is case-insensitive. At this time,
405 -- the name cannot contain NLS characters.
406 -- timeout
407 -- Time to wait for a message. A timeout of 0 allows you to read
408 -- without blocking.
409 -- Return value:
410 -- 0 - Success
411 -- 1 - Timed out
412 -- 2 - Record in pipe too big for buffer (should not happen).
413 -- 3 - Interrupted
414 -- Exceptions:
415 -- Null pipe name.
416 -- Permission error. Insufficient privilege to remove the record
417 -- from the pipe. The pipe is owned by someone else.
418 procedure reset_buffer;
419 pragma restrict_references(reset_buffer,WNDS,RNDS);
420 -- Reset pack and unpack positioning indicators to 0. Generally this
421 -- routine is not needed.
422 --
423 procedure purge(pipename in varchar2);
424 pragma restrict_references(purge,WNDS,RNDS);
425 -- Empty out the named pipe. An empty pipe is a candidate for LRU
426 -- removal from the SGA, therefore 'purge' can be used to free all
427 -- memory associated with a pipe.
428 -- Input Parameters:
429 -- pipename
430 -- Name of pipe from which to remove all messages. The local
431 -- buffer may be overwritten with messages as they are discarded.
432 -- Pipename should not be longer than 128 bytes, and is
433 -- case-insensitive.
434 -- Exceptions:
435 -- Permission error if pipe belongs to another user.
436 --
437 function unique_session_name return varchar2;
438 pragma restrict_references(unique_session_name,WNDS,RNDS,WNPS);
439 -- Get a name that is unique among all sessions currently connected
440 -- to this database. Multiple calls to this routine from the same
441 -- session will always return the same value.
442 -- Return value:
443 -- A unique name. The returned name can be up to 30 bytes.
444 --
445
446 pragma TIMESTAMP('2000-06-09:14:30:00');
447
448 end;
449
450 -- CUT_HERE <- tell sed where to chop off the rest