I have a table declared like so:
CREATE TABLE my_table (
...
guid uuid UNIQUE DEFAULT create_guid('my_table')
....
);
I have a function to compute unique GUIDs.
CREATE FUNCTION create_guid(in_table text)
RETURNS uuid AS $$
DECLARE
v_guid uuid;
v_rows int;
BEGIN
v_guid := md5(current_timestamp::text||random()::text);
EXECUTE 'SELECT 1 FROM ' || quote_ident(in_table) ||' WHERE guid=' || quote_literal(v_guid);
GET DIAGNOSTICS v_rows = ROW_COUNT;
WHILE v_rows > 0 LOOP -- can't use FOUND with EXECUTE
v_guid := md5(current_timestamp::text||random()::text||v_guid::text);
EXECUTE 'SELECT 1 FROM ' || quote_ident(in_table) ||' WHERE guid=' || quote_literal(v_guid);
GET DIAGNOSTICS v_rows = ROW_COUNT;
END LOOP;
RETURN v_guid;
END;
$$ LANGUAGE PLPGSQL VOLATILE;
I have never experienced an INSERT failure in my production environment, but in my test environment I can fairly reliably obtain an error similar to the following:
ERROR: duplicate key value violates unique constraint 'my_table_guid_key'
DETAIL: Key (guid)=(fed050ad-61c4-d548-3008-2de01301c2fc) already exists.
I realize current_timestamp
could be an identical value and I suppose random()
could as well, but it should be rather unlikely and its not. Even if they they were the same, wouldn't the while loop prevent duplication?
I am, of course, using the default value when inserting. How can this happen? What would fix it?