mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 10:30:33 +03:00 
			
		
		
		
	Similar to commit 7e735035f2.
Author: Richard Guo <guofenglinux@gmail.com>
Reviewed-by: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CAMbWs4-WhpCFMbXCjtJ%2BFzmjfPrp7Hw1pk4p%2BZpU95Kh3ofZ1A%40mail.gmail.com
		
	
		
			
				
	
	
		
			553 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			553 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*-------------------------------------------------------------------------
 | |
|  *
 | |
|  * UUID generation functions using the BSD, E2FS or OSSP UUID library
 | |
|  *
 | |
|  * Copyright (c) 2007-2024, PostgreSQL Global Development Group
 | |
|  *
 | |
|  * Portions Copyright (c) 2009 Andrew Gierth
 | |
|  *
 | |
|  * contrib/uuid-ossp/uuid-ossp.c
 | |
|  *
 | |
|  *-------------------------------------------------------------------------
 | |
|  */
 | |
| 
 | |
| #include "postgres.h"
 | |
| 
 | |
| #include "common/cryptohash.h"
 | |
| #include "common/sha1.h"
 | |
| #include "fmgr.h"
 | |
| #include "port/pg_bswap.h"
 | |
| #include "utils/builtins.h"
 | |
| #include "utils/uuid.h"
 | |
| #include "varatt.h"
 | |
| 
 | |
| /*
 | |
|  * It's possible that there's more than one uuid.h header file present.
 | |
|  * We expect configure to set the HAVE_ symbol for only the one we want.
 | |
|  *
 | |
|  * BSD includes a uuid_hash() function that conflicts with the one in
 | |
|  * builtins.h; we #define it out of the way.
 | |
|  */
 | |
| #define uuid_hash bsd_uuid_hash
 | |
| 
 | |
| #if defined(HAVE_UUID_H)
 | |
| #include <uuid.h>
 | |
| #elif defined(HAVE_OSSP_UUID_H)
 | |
| #include <ossp/uuid.h>
 | |
| #elif defined(HAVE_UUID_UUID_H)
 | |
| #include <uuid/uuid.h>
 | |
| #else
 | |
| #error "please use configure's --with-uuid switch to select a UUID library"
 | |
| #endif
 | |
| 
 | |
| #undef uuid_hash
 | |
| 
 | |
| /* Check our UUID length against OSSP's; better both be 16 */
 | |
| #if defined(HAVE_UUID_OSSP) && (UUID_LEN != UUID_LEN_BIN)
 | |
| #error UUID length mismatch
 | |
| #endif
 | |
| 
 | |
| /* Define some constants like OSSP's, to make the code more readable */
 | |
| #ifndef HAVE_UUID_OSSP
 | |
| #define UUID_MAKE_MC 0
 | |
| #define UUID_MAKE_V1 1
 | |
| #define UUID_MAKE_V2 2
 | |
| #define UUID_MAKE_V3 3
 | |
| #define UUID_MAKE_V4 4
 | |
| #define UUID_MAKE_V5 5
 | |
| #endif
 | |
| 
 | |
| /*
 | |
|  * A DCE 1.1 compatible source representation of UUIDs, derived from
 | |
|  * the BSD implementation.  BSD already has this; OSSP doesn't need it.
 | |
|  */
 | |
| #ifdef HAVE_UUID_E2FS
 | |
| typedef struct
 | |
| {
 | |
| 	uint32_t	time_low;
 | |
| 	uint16_t	time_mid;
 | |
| 	uint16_t	time_hi_and_version;
 | |
| 	uint8_t		clock_seq_hi_and_reserved;
 | |
| 	uint8_t		clock_seq_low;
 | |
| 	uint8_t		node[6];
 | |
| } dce_uuid_t;
 | |
| #else
 | |
| #define dce_uuid_t uuid_t
 | |
| #endif
 | |
| 
 | |
| /* If not OSSP, we need some endianness-manipulation macros */
 | |
| #ifndef HAVE_UUID_OSSP
 | |
| 
 | |
| #define UUID_TO_NETWORK(uu) \
 | |
| do { \
 | |
| 	uu.time_low = pg_hton32(uu.time_low); \
 | |
| 	uu.time_mid = pg_hton16(uu.time_mid); \
 | |
| 	uu.time_hi_and_version = pg_hton16(uu.time_hi_and_version); \
 | |
| } while (0)
 | |
| 
 | |
| #define UUID_TO_LOCAL(uu) \
 | |
| do { \
 | |
| 	uu.time_low = pg_ntoh32(uu.time_low); \
 | |
| 	uu.time_mid = pg_ntoh16(uu.time_mid); \
 | |
| 	uu.time_hi_and_version = pg_ntoh16(uu.time_hi_and_version); \
 | |
| } while (0)
 | |
| 
 | |
| #define UUID_V3_OR_V5(uu, v) \
 | |
| do { \
 | |
| 	uu.time_hi_and_version &= 0x0FFF; \
 | |
| 	uu.time_hi_and_version |= (v << 12); \
 | |
| 	uu.clock_seq_hi_and_reserved &= 0x3F; \
 | |
| 	uu.clock_seq_hi_and_reserved |= 0x80; \
 | |
| } while(0)
 | |
| 
 | |
| #endif							/* !HAVE_UUID_OSSP */
 | |
| 
 | |
| PG_MODULE_MAGIC;
 | |
| 
 | |
| PG_FUNCTION_INFO_V1(uuid_nil);
 | |
| PG_FUNCTION_INFO_V1(uuid_ns_dns);
 | |
| PG_FUNCTION_INFO_V1(uuid_ns_url);
 | |
| PG_FUNCTION_INFO_V1(uuid_ns_oid);
 | |
| PG_FUNCTION_INFO_V1(uuid_ns_x500);
 | |
| 
 | |
| PG_FUNCTION_INFO_V1(uuid_generate_v1);
 | |
| PG_FUNCTION_INFO_V1(uuid_generate_v1mc);
 | |
| PG_FUNCTION_INFO_V1(uuid_generate_v3);
 | |
| PG_FUNCTION_INFO_V1(uuid_generate_v4);
 | |
| PG_FUNCTION_INFO_V1(uuid_generate_v5);
 | |
| 
 | |
| #ifdef HAVE_UUID_OSSP
 | |
| 
 | |
| static void
 | |
| pguuid_complain(uuid_rc_t rc)
 | |
| {
 | |
| 	char	   *err = uuid_error(rc);
 | |
| 
 | |
| 	if (err != NULL)
 | |
| 		ereport(ERROR,
 | |
| 				(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
 | |
| 				 errmsg("OSSP uuid library failure: %s", err)));
 | |
| 	else
 | |
| 		ereport(ERROR,
 | |
| 				(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
 | |
| 				 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 *
 | |
| uuid_to_string(const uuid_t *uuid)
 | |
| {
 | |
| 	char	   *buf = palloc(UUID_LEN_STR + 1);
 | |
| 	void	   *ptr = buf;
 | |
| 	size_t		len = UUID_LEN_STR + 1;
 | |
| 	uuid_rc_t	rc;
 | |
| 
 | |
| 	rc = uuid_export(uuid, UUID_FMT_STR, &ptr, &len);
 | |
| 	if (rc != UUID_RC_OK)
 | |
| 		pguuid_complain(rc);
 | |
| 
 | |
| 	return buf;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| string_to_uuid(const char *str, uuid_t *uuid)
 | |
| {
 | |
| 	uuid_rc_t	rc;
 | |
| 
 | |
| 	rc = uuid_import(uuid, UUID_FMT_STR, str, UUID_LEN_STR + 1);
 | |
| 	if (rc != UUID_RC_OK)
 | |
| 		pguuid_complain(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static Datum
 | |
| special_uuid_value(const char *name)
 | |
| {
 | |
| 	uuid_t	   *uuid = get_cached_uuid_t(0);
 | |
| 	char	   *str;
 | |
| 	uuid_rc_t	rc;
 | |
| 
 | |
| 	rc = uuid_load(uuid, name);
 | |
| 	if (rc != UUID_RC_OK)
 | |
| 		pguuid_complain(rc);
 | |
| 	str = uuid_to_string(uuid);
 | |
| 
 | |
| 	return DirectFunctionCall1(uuid_in, CStringGetDatum(str));
 | |
| }
 | |
| 
 | |
| /* len is unused with OSSP, but we want to have the same number of args */
 | |
| static Datum
 | |
| uuid_generate_internal(int mode, const uuid_t *ns, const char *name, int len)
 | |
| {
 | |
| 	uuid_t	   *uuid = get_cached_uuid_t(0);
 | |
| 	char	   *str;
 | |
| 	uuid_rc_t	rc;
 | |
| 
 | |
| 	rc = uuid_make(uuid, mode, ns, name);
 | |
| 	if (rc != UUID_RC_OK)
 | |
| 		pguuid_complain(rc);
 | |
| 	str = uuid_to_string(uuid);
 | |
| 
 | |
| 	return DirectFunctionCall1(uuid_in, CStringGetDatum(str));
 | |
| }
 | |
| 
 | |
| 
 | |
| static Datum
 | |
| uuid_generate_v35_internal(int mode, pg_uuid_t *ns, text *name)
 | |
| {
 | |
| 	uuid_t	   *ns_uuid = get_cached_uuid_t(1);
 | |
| 
 | |
| 	string_to_uuid(DatumGetCString(DirectFunctionCall1(uuid_out,
 | |
| 													   UUIDPGetDatum(ns))),
 | |
| 				   ns_uuid);
 | |
| 
 | |
| 	return uuid_generate_internal(mode,
 | |
| 								  ns_uuid,
 | |
| 								  text_to_cstring(name),
 | |
| 								  0);
 | |
| }
 | |
| 
 | |
| #else							/* !HAVE_UUID_OSSP */
 | |
| 
 | |
| static Datum
 | |
| uuid_generate_internal(int v, unsigned char *ns, const char *ptr, int len)
 | |
| {
 | |
| 	char		strbuf[40];
 | |
| 
 | |
| 	switch (v)
 | |
| 	{
 | |
| 		case 0:					/* constant-value uuids */
 | |
| 			strlcpy(strbuf, ptr, 37);
 | |
| 			break;
 | |
| 
 | |
| 		case 1:					/* time/node-based uuids */
 | |
| 			{
 | |
| #ifdef HAVE_UUID_E2FS
 | |
| 				uuid_t		uu;
 | |
| 
 | |
| 				uuid_generate_time(uu);
 | |
| 				uuid_unparse(uu, strbuf);
 | |
| 
 | |
| 				/*
 | |
| 				 * PTR, if set, replaces the trailing characters of the uuid;
 | |
| 				 * this is to support v1mc, where a random multicast MAC is
 | |
| 				 * used instead of the physical one
 | |
| 				 */
 | |
| 				if (ptr && len <= 36)
 | |
| 					strcpy(strbuf + (36 - len), ptr);
 | |
| #else							/* BSD */
 | |
| 				uuid_t		uu;
 | |
| 				uint32_t	status = uuid_s_ok;
 | |
| 				char	   *str = NULL;
 | |
| 
 | |
| 				uuid_create(&uu, &status);
 | |
| 
 | |
| 				if (status == uuid_s_ok)
 | |
| 				{
 | |
| 					uuid_to_string(&uu, &str, &status);
 | |
| 					if (status == uuid_s_ok)
 | |
| 					{
 | |
| 						strlcpy(strbuf, str, 37);
 | |
| 
 | |
| 						/*
 | |
| 						 * In recent NetBSD, uuid_create() has started
 | |
| 						 * producing v4 instead of v1 UUIDs.  Check the
 | |
| 						 * version field and complain if it's not v1.
 | |
| 						 */
 | |
| 						if (strbuf[14] != '1')
 | |
| 							ereport(ERROR,
 | |
| 									(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
 | |
| 							/* translator: %c will be a hex digit */
 | |
| 									 errmsg("uuid_create() produced a version %c UUID instead of the expected version 1",
 | |
| 											strbuf[14])));
 | |
| 
 | |
| 						/*
 | |
| 						 * PTR, if set, replaces the trailing characters of
 | |
| 						 * the uuid; this is to support v1mc, where a random
 | |
| 						 * multicast MAC is used instead of the physical one
 | |
| 						 */
 | |
| 						if (ptr && len <= 36)
 | |
| 							strcpy(strbuf + (36 - len), ptr);
 | |
| 					}
 | |
| 					free(str);
 | |
| 				}
 | |
| 
 | |
| 				if (status != uuid_s_ok)
 | |
| 					ereport(ERROR,
 | |
| 							(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
 | |
| 							 errmsg("uuid library failure: %d",
 | |
| 									(int) status)));
 | |
| #endif
 | |
| 				break;
 | |
| 			}
 | |
| 
 | |
| 		case 3:					/* namespace-based MD5 uuids */
 | |
| 		case 5:					/* namespace-based SHA1 uuids */
 | |
| 			{
 | |
| 				dce_uuid_t	uu;
 | |
| #ifdef HAVE_UUID_BSD
 | |
| 				uint32_t	status = uuid_s_ok;
 | |
| 				char	   *str = NULL;
 | |
| #endif
 | |
| 
 | |
| 				if (v == 3)
 | |
| 				{
 | |
| 					pg_cryptohash_ctx *ctx = pg_cryptohash_create(PG_MD5);
 | |
| 
 | |
| 					if (pg_cryptohash_init(ctx) < 0)
 | |
| 						elog(ERROR, "could not initialize %s context: %s", "MD5",
 | |
| 							 pg_cryptohash_error(ctx));
 | |
| 					if (pg_cryptohash_update(ctx, ns, sizeof(uu)) < 0 ||
 | |
| 						pg_cryptohash_update(ctx, (unsigned char *) ptr, len) < 0)
 | |
| 						elog(ERROR, "could not update %s context: %s", "MD5",
 | |
| 							 pg_cryptohash_error(ctx));
 | |
| 					/* we assume sizeof MD5 result is 16, same as UUID size */
 | |
| 					if (pg_cryptohash_final(ctx, (unsigned char *) &uu,
 | |
| 											sizeof(uu)) < 0)
 | |
| 						elog(ERROR, "could not finalize %s context: %s", "MD5",
 | |
| 							 pg_cryptohash_error(ctx));
 | |
| 					pg_cryptohash_free(ctx);
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					pg_cryptohash_ctx *ctx = pg_cryptohash_create(PG_SHA1);
 | |
| 					unsigned char sha1result[SHA1_DIGEST_LENGTH];
 | |
| 
 | |
| 					if (pg_cryptohash_init(ctx) < 0)
 | |
| 						elog(ERROR, "could not initialize %s context: %s", "SHA1",
 | |
| 							 pg_cryptohash_error(ctx));
 | |
| 					if (pg_cryptohash_update(ctx, ns, sizeof(uu)) < 0 ||
 | |
| 						pg_cryptohash_update(ctx, (unsigned char *) ptr, len) < 0)
 | |
| 						elog(ERROR, "could not update %s context: %s", "SHA1",
 | |
| 							 pg_cryptohash_error(ctx));
 | |
| 					if (pg_cryptohash_final(ctx, sha1result, sizeof(sha1result)) < 0)
 | |
| 						elog(ERROR, "could not finalize %s context: %s", "SHA1",
 | |
| 							 pg_cryptohash_error(ctx));
 | |
| 					pg_cryptohash_free(ctx);
 | |
| 
 | |
| 					memcpy(&uu, sha1result, sizeof(uu));
 | |
| 				}
 | |
| 
 | |
| 				/* the calculated hash is using local order */
 | |
| 				UUID_TO_NETWORK(uu);
 | |
| 				UUID_V3_OR_V5(uu, v);
 | |
| 
 | |
| #ifdef HAVE_UUID_E2FS
 | |
| 				/* uuid_unparse expects local order */
 | |
| 				UUID_TO_LOCAL(uu);
 | |
| 				uuid_unparse((unsigned char *) &uu, strbuf);
 | |
| #else							/* BSD */
 | |
| 				uuid_to_string(&uu, &str, &status);
 | |
| 
 | |
| 				if (status == uuid_s_ok)
 | |
| 					strlcpy(strbuf, str, 37);
 | |
| 
 | |
| 				free(str);
 | |
| 
 | |
| 				if (status != uuid_s_ok)
 | |
| 					ereport(ERROR,
 | |
| 							(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
 | |
| 							 errmsg("uuid library failure: %d",
 | |
| 									(int) status)));
 | |
| #endif
 | |
| 				break;
 | |
| 			}
 | |
| 
 | |
| 		case 4:					/* random uuid */
 | |
| 		default:
 | |
| 			{
 | |
| #ifdef HAVE_UUID_E2FS
 | |
| 				uuid_t		uu;
 | |
| 
 | |
| 				uuid_generate_random(uu);
 | |
| 				uuid_unparse(uu, strbuf);
 | |
| #else							/* BSD */
 | |
| 				snprintf(strbuf, sizeof(strbuf),
 | |
| 						 "%08lx-%04x-%04x-%04x-%04x%08lx",
 | |
| 						 (unsigned long) arc4random(),
 | |
| 						 (unsigned) (arc4random() & 0xffff),
 | |
| 						 (unsigned) ((arc4random() & 0xfff) | 0x4000),
 | |
| 						 (unsigned) ((arc4random() & 0x3fff) | 0x8000),
 | |
| 						 (unsigned) (arc4random() & 0xffff),
 | |
| 						 (unsigned long) arc4random());
 | |
| #endif
 | |
| 				break;
 | |
| 			}
 | |
| 	}
 | |
| 
 | |
| 	return DirectFunctionCall1(uuid_in, CStringGetDatum(strbuf));
 | |
| }
 | |
| 
 | |
| #endif							/* HAVE_UUID_OSSP */
 | |
| 
 | |
| 
 | |
| Datum
 | |
| uuid_nil(PG_FUNCTION_ARGS)
 | |
| {
 | |
| #ifdef HAVE_UUID_OSSP
 | |
| 	return special_uuid_value("nil");
 | |
| #else
 | |
| 	return uuid_generate_internal(0, NULL,
 | |
| 								  "00000000-0000-0000-0000-000000000000", 36);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| Datum
 | |
| uuid_ns_dns(PG_FUNCTION_ARGS)
 | |
| {
 | |
| #ifdef HAVE_UUID_OSSP
 | |
| 	return special_uuid_value("ns:DNS");
 | |
| #else
 | |
| 	return uuid_generate_internal(0, NULL,
 | |
| 								  "6ba7b810-9dad-11d1-80b4-00c04fd430c8", 36);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| Datum
 | |
| uuid_ns_url(PG_FUNCTION_ARGS)
 | |
| {
 | |
| #ifdef HAVE_UUID_OSSP
 | |
| 	return special_uuid_value("ns:URL");
 | |
| #else
 | |
| 	return uuid_generate_internal(0, NULL,
 | |
| 								  "6ba7b811-9dad-11d1-80b4-00c04fd430c8", 36);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| Datum
 | |
| uuid_ns_oid(PG_FUNCTION_ARGS)
 | |
| {
 | |
| #ifdef HAVE_UUID_OSSP
 | |
| 	return special_uuid_value("ns:OID");
 | |
| #else
 | |
| 	return uuid_generate_internal(0, NULL,
 | |
| 								  "6ba7b812-9dad-11d1-80b4-00c04fd430c8", 36);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| Datum
 | |
| uuid_ns_x500(PG_FUNCTION_ARGS)
 | |
| {
 | |
| #ifdef HAVE_UUID_OSSP
 | |
| 	return special_uuid_value("ns:X500");
 | |
| #else
 | |
| 	return uuid_generate_internal(0, NULL,
 | |
| 								  "6ba7b814-9dad-11d1-80b4-00c04fd430c8", 36);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| Datum
 | |
| uuid_generate_v1(PG_FUNCTION_ARGS)
 | |
| {
 | |
| 	return uuid_generate_internal(UUID_MAKE_V1, NULL, NULL, 0);
 | |
| }
 | |
| 
 | |
| 
 | |
| Datum
 | |
| uuid_generate_v1mc(PG_FUNCTION_ARGS)
 | |
| {
 | |
| #ifdef HAVE_UUID_OSSP
 | |
| 	char	   *buf = NULL;
 | |
| #elif defined(HAVE_UUID_E2FS)
 | |
| 	char		strbuf[40];
 | |
| 	char	   *buf;
 | |
| 	uuid_t		uu;
 | |
| 
 | |
| 	uuid_generate_random(uu);
 | |
| 
 | |
| 	/* set IEEE802 multicast and local-admin bits */
 | |
| 	((dce_uuid_t *) &uu)->node[0] |= 0x03;
 | |
| 
 | |
| 	uuid_unparse(uu, strbuf);
 | |
| 	buf = strbuf + 24;
 | |
| #else							/* BSD */
 | |
| 	char		buf[16];
 | |
| 
 | |
| 	/* set IEEE802 multicast and local-admin bits */
 | |
| 	snprintf(buf, sizeof(buf), "-%04x%08lx",
 | |
| 			 (unsigned) ((arc4random() & 0xffff) | 0x0300),
 | |
| 			 (unsigned long) arc4random());
 | |
| #endif
 | |
| 
 | |
| 	return uuid_generate_internal(UUID_MAKE_V1 | UUID_MAKE_MC, NULL,
 | |
| 								  buf, 13);
 | |
| }
 | |
| 
 | |
| 
 | |
| Datum
 | |
| uuid_generate_v3(PG_FUNCTION_ARGS)
 | |
| {
 | |
| 	pg_uuid_t  *ns = PG_GETARG_UUID_P(0);
 | |
| 	text	   *name = PG_GETARG_TEXT_PP(1);
 | |
| 
 | |
| #ifdef HAVE_UUID_OSSP
 | |
| 	return uuid_generate_v35_internal(UUID_MAKE_V3, ns, name);
 | |
| #else
 | |
| 	return uuid_generate_internal(UUID_MAKE_V3, (unsigned char *) ns,
 | |
| 								  VARDATA_ANY(name), VARSIZE_ANY_EXHDR(name));
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| Datum
 | |
| uuid_generate_v4(PG_FUNCTION_ARGS)
 | |
| {
 | |
| 	return uuid_generate_internal(UUID_MAKE_V4, NULL, NULL, 0);
 | |
| }
 | |
| 
 | |
| 
 | |
| Datum
 | |
| uuid_generate_v5(PG_FUNCTION_ARGS)
 | |
| {
 | |
| 	pg_uuid_t  *ns = PG_GETARG_UUID_P(0);
 | |
| 	text	   *name = PG_GETARG_TEXT_PP(1);
 | |
| 
 | |
| #ifdef HAVE_UUID_OSSP
 | |
| 	return uuid_generate_v35_internal(UUID_MAKE_V5, ns, name);
 | |
| #else
 | |
| 	return uuid_generate_internal(UUID_MAKE_V5, (unsigned char *) ns,
 | |
| 								  VARDATA_ANY(name), VARSIZE_ANY_EXHDR(name));
 | |
| #endif
 | |
| }
 |