create or replace package body uuid_pkg is
--
function internal_get_uuid
(bar in foo.bar%type, qux in foo.qux%type)
return foo.uuid%type is
uuid foo.uuid%type;
begin
select foo.uuid into uuid
from foo
where foo.bar = internal_get_uuid.bar
and foo.qux = internal_get_uuid.qux;
return uuid;
exception
when no_data_found then
return null;
end internal_get_uuid;
--
function new_uuid
(bar in foo.bar%type, qux in foo.qux%type)
return foo.uuid%type is
pragma autonomous_transaction;
uuid foo.uuid%type;
retry_attempts number := 20; -- number of retry attempts before giving up
successful boolean := false;
begin
-- generate the uuid however you need
uuid := SYS_GUID();
loop
begin
insert into foo (bar, qux, uuid) values (bar, qux, uuid);
successful := true;
exception
when dup_val_on_index then
-- has the other session committed the value?
uuid := get_uuid(bar,qux);
if uuid is not null then
successful := true;
elsif retry_attempts < 1 then
raise_application_error(-20000, 'unable to store uuid');
else
retry_attempts := retry_attempts - 1;
end if;
end;
exit when successful;
end loop;
commit;
return uuid;
end new_uuid;
--
function get_uuid
(bar in foo.bar%type, qux in foo.qux%type)
return foo.uuid%type is
begin
return coalesce
(internal_get_uuid(bar,qux)
,new_uuid(bar,qux));
end get_uuid;
--
end uuid_pkg;