@ -79,6 +79,42 @@ pguuid_complain(uuid_rc_t rc)
errmsg ( " OSSP uuid library failure: error code %d " , rc ) ) ) ;
errmsg ( " OSSP uuid library failure: error code %d " , rc ) ) ) ;
}
}
/*
* We create a uuid_t object just once per session and re - use it for all
* operations in this module . OSSP UUID caches the system MAC address and
* other state in this object . Reusing the object has a number of benefits :
* saving the cycles needed to fetch the system MAC address over and over ,
* reducing the amount of entropy we draw from / dev / urandom , and providing a
* positive guarantee that successive generated V1 - style UUIDs don ' t collide .
* ( On a machine fast enough to generate multiple UUIDs per microsecond ,
* or whatever the system ' s wall - clock resolution is , we ' d otherwise risk
* collisions whenever random initialization of the uuid_t ' s clock sequence
* value chanced to produce duplicates . )
*
* However : when we ' re doing V3 or V5 UUID creation , uuid_make needs two
* uuid_t objects , one holding the namespace UUID and one for the result .
* It ' s unspecified whether it ' s safe to use the same uuid_t for both cases ,
* so let ' s cache a second uuid_t for use as the namespace holder object .
*/
static uuid_t *
get_cached_uuid_t ( int which )
{
static uuid_t * cached_uuid [ 2 ] = { NULL , NULL } ;
if ( cached_uuid [ which ] = = NULL )
{
uuid_rc_t rc ;
rc = uuid_create ( & cached_uuid [ which ] ) ;
if ( rc ! = UUID_RC_OK )
{
cached_uuid [ which ] = NULL ;
pguuid_complain ( rc ) ;
}
}
return cached_uuid [ which ] ;
}
static char *
static char *
uuid_to_string ( const uuid_t * uuid )
uuid_to_string ( const uuid_t * uuid )
{
{
@ -109,20 +145,14 @@ string_to_uuid(const char *str, uuid_t *uuid)
static Datum
static Datum
special_uuid_value ( const char * name )
special_uuid_value ( const char * name )
{
{
uuid_t * uuid ;
uuid_t * uuid = get_cached_uuid_t ( 0 ) ;
char * str ;
char * str ;
uuid_rc_t rc ;
uuid_rc_t rc ;
rc = uuid_create ( & uuid ) ;
if ( rc ! = UUID_RC_OK )
pguuid_complain ( rc ) ;
rc = uuid_load ( uuid , name ) ;
rc = uuid_load ( uuid , name ) ;
if ( rc ! = UUID_RC_OK )
if ( rc ! = UUID_RC_OK )
pguuid_complain ( rc ) ;
pguuid_complain ( rc ) ;
str = uuid_to_string ( uuid ) ;
str = uuid_to_string ( uuid ) ;
rc = uuid_destroy ( uuid ) ;
if ( rc ! = UUID_RC_OK )
pguuid_complain ( rc ) ;
return DirectFunctionCall1 ( uuid_in , CStringGetDatum ( str ) ) ;
return DirectFunctionCall1 ( uuid_in , CStringGetDatum ( str ) ) ;
}
}
@ -166,20 +196,14 @@ uuid_ns_x500(PG_FUNCTION_ARGS)
static Datum
static Datum
uuid_generate_internal ( int mode , const uuid_t * ns , const char * name )
uuid_generate_internal ( int mode , const uuid_t * ns , const char * name )
{
{
uuid_t * uuid ;
uuid_t * uuid = get_cached_uuid_t ( 0 ) ;
char * str ;
char * str ;
uuid_rc_t rc ;
uuid_rc_t rc ;
rc = uuid_create ( & uuid ) ;
if ( rc ! = UUID_RC_OK )
pguuid_complain ( rc ) ;
rc = uuid_make ( uuid , mode , ns , name ) ;
rc = uuid_make ( uuid , mode , ns , name ) ;
if ( rc ! = UUID_RC_OK )
if ( rc ! = UUID_RC_OK )
pguuid_complain ( rc ) ;
pguuid_complain ( rc ) ;
str = uuid_to_string ( uuid ) ;
str = uuid_to_string ( uuid ) ;
rc = uuid_destroy ( uuid ) ;
if ( rc ! = UUID_RC_OK )
pguuid_complain ( rc ) ;
return DirectFunctionCall1 ( uuid_in , CStringGetDatum ( str ) ) ;
return DirectFunctionCall1 ( uuid_in , CStringGetDatum ( str ) ) ;
}
}
@ -202,25 +226,15 @@ uuid_generate_v1mc(PG_FUNCTION_ARGS)
static Datum
static Datum
uuid_generate_v35_internal ( int mode , pg_uuid_t * ns , text * name )
uuid_generate_v35_internal ( int mode , pg_uuid_t * ns , text * name )
{
{
uuid_t * ns_uuid ;
uuid_t * ns_uuid = get_cached_uuid_t ( 1 ) ;
Datum result ;
uuid_rc_t rc ;
rc = uuid_create ( & ns_uuid ) ;
string_to_uuid ( DatumGetCString ( DirectFunctionCall1 ( uuid_out ,
if ( rc ! = UUID_RC_OK )
UUIDPGetDatum ( ns ) ) ) ,
pguuid_complain ( rc ) ;
string_to_uuid ( DatumGetCString ( DirectFunctionCall1 ( uuid_out , UUIDPGetDatum ( ns ) ) ) ,
ns_uuid ) ;
ns_uuid ) ;
result = uuid_generate_internal ( mode ,
return uuid_generate_internal ( mode ,
ns_uuid ,
ns_uuid ,
text_to_cstring ( name ) ) ;
text_to_cstring ( name ) ) ;
rc = uuid_destroy ( ns_uuid ) ;
if ( rc ! = UUID_RC_OK )
pguuid_complain ( rc ) ;
return result ;
}
}