diff --git a/contrib/uuid-ossp/expected/uuid_ossp.out b/contrib/uuid-ossp/expected/uuid_ossp.out index fe3e325992..409c885c33 100644 --- a/contrib/uuid-ossp/expected/uuid_ossp.out +++ b/contrib/uuid-ossp/expected/uuid_ossp.out @@ -42,26 +42,35 @@ LANGUAGE SQL STRICT IMMUTABLE; CREATE FUNCTION uuid_reserved_bits(uuid) RETURNS varbit AS $$ SELECT ('x' || substr($1::text, 20, 2))::bit(8) & '11000000' $$ LANGUAGE SQL STRICT IMMUTABLE; -CREATE FUNCTION uuid_multicast_bits(uuid) RETURNS varbit AS -$$ SELECT ('x' || substr($1::text, 25, 2))::bit(8) & '00000011' $$ +CREATE FUNCTION uuid_multicast_bit(uuid) RETURNS bool AS +$$ SELECT (('x' || substr($1::text, 25, 2))::bit(8) & '00000001') != '00000000' $$ +LANGUAGE SQL STRICT IMMUTABLE; +CREATE FUNCTION uuid_local_admin_bit(uuid) RETURNS bool AS +$$ SELECT (('x' || substr($1::text, 25, 2))::bit(8) & '00000010') != '00000000' $$ LANGUAGE SQL STRICT IMMUTABLE; CREATE FUNCTION uuid_node(uuid) RETURNS text AS $$ SELECT substr($1::text, 25) $$ LANGUAGE SQL STRICT IMMUTABLE; +-- Ideally, the multicast bit would never be set in V1 output, but the +-- UUID library may fall back to MC if it can't get the system MAC address. +-- Also, the local-admin bit might be set (if so, we're probably inside a VM). +-- So we can't test either bit here. SELECT uuid_version_bits(uuid_generate_v1()), - uuid_reserved_bits(uuid_generate_v1()), - uuid_multicast_bits(uuid_generate_v1()); - uuid_version_bits | uuid_reserved_bits | uuid_multicast_bits --------------------+--------------------+--------------------- - 00010000 | 10000000 | 00000000 + uuid_reserved_bits(uuid_generate_v1()); + uuid_version_bits | uuid_reserved_bits +-------------------+-------------------- + 00010000 | 10000000 (1 row) +-- Although RFC 4122 only requires the multicast bit to be set in V1MC style +-- UUIDs, our implementation always sets the local-admin bit as well. SELECT uuid_version_bits(uuid_generate_v1mc()), uuid_reserved_bits(uuid_generate_v1mc()), - uuid_multicast_bits(uuid_generate_v1mc()); - uuid_version_bits | uuid_reserved_bits | uuid_multicast_bits --------------------+--------------------+--------------------- - 00010000 | 10000000 | 00000011 + uuid_multicast_bit(uuid_generate_v1mc()), + uuid_local_admin_bit(uuid_generate_v1mc()); + uuid_version_bits | uuid_reserved_bits | uuid_multicast_bit | uuid_local_admin_bit +-------------------+--------------------+--------------------+---------------------- + 00010000 | 10000000 | t | t (1 row) -- timestamp+clock sequence should be monotonic increasing in v1 @@ -77,13 +86,20 @@ SELECT uuid_timestamp_bits(uuid_generate_v1mc()) < uuid_timestamp_bits(uuid_gene t (1 row) --- node should be stable in v1, but not v1mc -SELECT uuid_node(uuid_generate_v1()) = uuid_node(uuid_generate_v1()); - ?column? ----------- +-- Ideally, the node value is stable in V1 addresses, but OSSP UUID +-- falls back to V1MC behavior if it can't get the system MAC address. +SELECT CASE WHEN uuid_multicast_bit(uuid_generate_v1()) AND + uuid_local_admin_bit(uuid_generate_v1()) THEN + true -- punt, no test + ELSE + uuid_node(uuid_generate_v1()) = uuid_node(uuid_generate_v1()) + END; + case +------ t (1 row) +-- In any case, V1MC node addresses should be random. SELECT uuid_node(uuid_generate_v1()) <> uuid_node(uuid_generate_v1mc()); ?column? ---------- diff --git a/contrib/uuid-ossp/sql/uuid_ossp.sql b/contrib/uuid-ossp/sql/uuid_ossp.sql index 3b1fa24bc6..b4237df884 100644 --- a/contrib/uuid-ossp/sql/uuid_ossp.sql +++ b/contrib/uuid-ossp/sql/uuid_ossp.sql @@ -23,28 +23,46 @@ CREATE FUNCTION uuid_reserved_bits(uuid) RETURNS varbit AS $$ SELECT ('x' || substr($1::text, 20, 2))::bit(8) & '11000000' $$ LANGUAGE SQL STRICT IMMUTABLE; -CREATE FUNCTION uuid_multicast_bits(uuid) RETURNS varbit AS -$$ SELECT ('x' || substr($1::text, 25, 2))::bit(8) & '00000011' $$ +CREATE FUNCTION uuid_multicast_bit(uuid) RETURNS bool AS +$$ SELECT (('x' || substr($1::text, 25, 2))::bit(8) & '00000001') != '00000000' $$ +LANGUAGE SQL STRICT IMMUTABLE; + +CREATE FUNCTION uuid_local_admin_bit(uuid) RETURNS bool AS +$$ SELECT (('x' || substr($1::text, 25, 2))::bit(8) & '00000010') != '00000000' $$ LANGUAGE SQL STRICT IMMUTABLE; CREATE FUNCTION uuid_node(uuid) RETURNS text AS $$ SELECT substr($1::text, 25) $$ LANGUAGE SQL STRICT IMMUTABLE; +-- Ideally, the multicast bit would never be set in V1 output, but the +-- UUID library may fall back to MC if it can't get the system MAC address. +-- Also, the local-admin bit might be set (if so, we're probably inside a VM). +-- So we can't test either bit here. SELECT uuid_version_bits(uuid_generate_v1()), - uuid_reserved_bits(uuid_generate_v1()), - uuid_multicast_bits(uuid_generate_v1()); + uuid_reserved_bits(uuid_generate_v1()); +-- Although RFC 4122 only requires the multicast bit to be set in V1MC style +-- UUIDs, our implementation always sets the local-admin bit as well. SELECT uuid_version_bits(uuid_generate_v1mc()), uuid_reserved_bits(uuid_generate_v1mc()), - uuid_multicast_bits(uuid_generate_v1mc()); + uuid_multicast_bit(uuid_generate_v1mc()), + uuid_local_admin_bit(uuid_generate_v1mc()); -- timestamp+clock sequence should be monotonic increasing in v1 SELECT uuid_timestamp_bits(uuid_generate_v1()) < uuid_timestamp_bits(uuid_generate_v1()); SELECT uuid_timestamp_bits(uuid_generate_v1mc()) < uuid_timestamp_bits(uuid_generate_v1mc()); --- node should be stable in v1, but not v1mc -SELECT uuid_node(uuid_generate_v1()) = uuid_node(uuid_generate_v1()); +-- Ideally, the node value is stable in V1 addresses, but OSSP UUID +-- falls back to V1MC behavior if it can't get the system MAC address. +SELECT CASE WHEN uuid_multicast_bit(uuid_generate_v1()) AND + uuid_local_admin_bit(uuid_generate_v1()) THEN + true -- punt, no test + ELSE + uuid_node(uuid_generate_v1()) = uuid_node(uuid_generate_v1()) + END; + +-- In any case, V1MC node addresses should be random. SELECT uuid_node(uuid_generate_v1()) <> uuid_node(uuid_generate_v1mc()); SELECT uuid_node(uuid_generate_v1mc()) <> uuid_node(uuid_generate_v1mc());