mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	strings. This patch introduces four support functions cstring_to_text, cstring_to_text_with_len, text_to_cstring, and text_to_cstring_buffer, and two macros CStringGetTextDatum and TextDatumGetCString. A number of existing macros that provided variants on these themes were removed. Most of the places that need to make such conversions now require just one function or macro call, in place of the multiple notational layers that used to be needed. There are no longer any direct calls of textout or textin, and we got most of the places that were using handmade conversions via memcpy (there may be a few still lurking, though). This commit doesn't make any serious effort to eliminate transient memory leaks caused by detoasting toasted text objects before they reach text_to_cstring. We changed PG_GETARG_TEXT_P to PG_GETARG_TEXT_PP in a few places where it was easy, but much more could be done. Brendan Jurd and Tom Lane
		
			
				
	
	
		
			252 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			252 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*-------------------------------------------------------------------------
 | 
						|
 *
 | 
						|
 * UUID generation functions using the OSSP UUID library
 | 
						|
 *
 | 
						|
 * Copyright (c) 2007-2008 PostgreSQL Global Development Group
 | 
						|
 *
 | 
						|
 * $PostgreSQL: pgsql/contrib/uuid-ossp/uuid-ossp.c,v 1.8 2008/03/25 22:42:42 tgl Exp $
 | 
						|
 *
 | 
						|
 *-------------------------------------------------------------------------
 | 
						|
 */
 | 
						|
 | 
						|
#include "postgres.h"
 | 
						|
#include "fmgr.h"
 | 
						|
#include "utils/builtins.h"
 | 
						|
#include "utils/uuid.h"
 | 
						|
 | 
						|
/*
 | 
						|
 * There's some confusion over the location of the uuid.h header file.
 | 
						|
 * On Debian, it's installed as ossp/uuid.h, while on Fedora, or if you
 | 
						|
 * install ossp-uuid from a tarball, it's installed as uuid.h. Don't know
 | 
						|
 * what other systems do.
 | 
						|
 */
 | 
						|
#ifdef HAVE_OSSP_UUID_H
 | 
						|
#include <ossp/uuid.h>
 | 
						|
#else
 | 
						|
#ifdef HAVE_UUID_H
 | 
						|
#include <uuid.h>
 | 
						|
#else
 | 
						|
#error OSSP uuid.h not found
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
 | 
						|
/* better both be 16 */
 | 
						|
#if (UUID_LEN != UUID_LEN_BIN)
 | 
						|
#error UUID length mismatch
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
PG_MODULE_MAGIC;
 | 
						|
 | 
						|
 | 
						|
Datum		uuid_nil(PG_FUNCTION_ARGS);
 | 
						|
Datum		uuid_ns_dns(PG_FUNCTION_ARGS);
 | 
						|
Datum		uuid_ns_url(PG_FUNCTION_ARGS);
 | 
						|
Datum		uuid_ns_oid(PG_FUNCTION_ARGS);
 | 
						|
Datum		uuid_ns_x500(PG_FUNCTION_ARGS);
 | 
						|
 | 
						|
Datum		uuid_generate_v1(PG_FUNCTION_ARGS);
 | 
						|
Datum		uuid_generate_v1mc(PG_FUNCTION_ARGS);
 | 
						|
Datum		uuid_generate_v3(PG_FUNCTION_ARGS);
 | 
						|
Datum		uuid_generate_v4(PG_FUNCTION_ARGS);
 | 
						|
Datum		uuid_generate_v5(PG_FUNCTION_ARGS);
 | 
						|
 | 
						|
 | 
						|
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);
 | 
						|
 | 
						|
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)));
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
	char	   *str;
 | 
						|
	uuid_rc_t	rc;
 | 
						|
 | 
						|
	rc = uuid_create(&uuid);
 | 
						|
	if (rc != UUID_RC_OK)
 | 
						|
		pguuid_complain(rc);
 | 
						|
	rc = uuid_load(uuid, name);
 | 
						|
	if (rc != UUID_RC_OK)
 | 
						|
		pguuid_complain(rc);
 | 
						|
	str = uuid_to_string(uuid);
 | 
						|
	rc = uuid_destroy(uuid);
 | 
						|
	if (rc != UUID_RC_OK)
 | 
						|
		pguuid_complain(rc);
 | 
						|
 | 
						|
	return DirectFunctionCall1(uuid_in, CStringGetDatum(str));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Datum
 | 
						|
uuid_nil(PG_FUNCTION_ARGS)
 | 
						|
{
 | 
						|
	return special_uuid_value("nil");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Datum
 | 
						|
uuid_ns_dns(PG_FUNCTION_ARGS)
 | 
						|
{
 | 
						|
	return special_uuid_value("ns:DNS");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Datum
 | 
						|
uuid_ns_url(PG_FUNCTION_ARGS)
 | 
						|
{
 | 
						|
	return special_uuid_value("ns:URL");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Datum
 | 
						|
uuid_ns_oid(PG_FUNCTION_ARGS)
 | 
						|
{
 | 
						|
	return special_uuid_value("ns:OID");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Datum
 | 
						|
uuid_ns_x500(PG_FUNCTION_ARGS)
 | 
						|
{
 | 
						|
	return special_uuid_value("ns:X500");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static Datum
 | 
						|
uuid_generate_internal(int mode, const uuid_t * ns, const char *name)
 | 
						|
{
 | 
						|
	uuid_t	   *uuid;
 | 
						|
	char	   *str;
 | 
						|
	uuid_rc_t	rc;
 | 
						|
 | 
						|
	rc = uuid_create(&uuid);
 | 
						|
	if (rc != UUID_RC_OK)
 | 
						|
		pguuid_complain(rc);
 | 
						|
	rc = uuid_make(uuid, mode, ns, name);
 | 
						|
	if (rc != UUID_RC_OK)
 | 
						|
		pguuid_complain(rc);
 | 
						|
	str = uuid_to_string(uuid);
 | 
						|
	rc = uuid_destroy(uuid);
 | 
						|
	if (rc != UUID_RC_OK)
 | 
						|
		pguuid_complain(rc);
 | 
						|
 | 
						|
	return DirectFunctionCall1(uuid_in, CStringGetDatum(str));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Datum
 | 
						|
uuid_generate_v1(PG_FUNCTION_ARGS)
 | 
						|
{
 | 
						|
	return uuid_generate_internal(UUID_MAKE_V1, NULL, NULL);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Datum
 | 
						|
uuid_generate_v1mc(PG_FUNCTION_ARGS)
 | 
						|
{
 | 
						|
	return uuid_generate_internal(UUID_MAKE_V1 | UUID_MAKE_MC, NULL, NULL);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static Datum
 | 
						|
uuid_generate_v35_internal(int mode, pg_uuid_t *ns, text *name)
 | 
						|
{
 | 
						|
	uuid_t	   *ns_uuid;
 | 
						|
	Datum		result;
 | 
						|
	uuid_rc_t	rc;
 | 
						|
 | 
						|
	rc = uuid_create(&ns_uuid);
 | 
						|
	if (rc != UUID_RC_OK)
 | 
						|
		pguuid_complain(rc);
 | 
						|
	string_to_uuid(DatumGetCString(DirectFunctionCall1(uuid_out, UUIDPGetDatum(ns))),
 | 
						|
				   ns_uuid);
 | 
						|
 | 
						|
	result = uuid_generate_internal(mode,
 | 
						|
									ns_uuid,
 | 
						|
									text_to_cstring(name));
 | 
						|
 | 
						|
	rc = uuid_destroy(ns_uuid);
 | 
						|
	if (rc != UUID_RC_OK)
 | 
						|
		pguuid_complain(rc);
 | 
						|
 | 
						|
	return result;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Datum
 | 
						|
uuid_generate_v3(PG_FUNCTION_ARGS)
 | 
						|
{
 | 
						|
	pg_uuid_t  *ns = PG_GETARG_UUID_P(0);
 | 
						|
	text	   *name = PG_GETARG_TEXT_P(1);
 | 
						|
 | 
						|
	return uuid_generate_v35_internal(UUID_MAKE_V3, ns, name);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Datum
 | 
						|
uuid_generate_v4(PG_FUNCTION_ARGS)
 | 
						|
{
 | 
						|
	return uuid_generate_internal(UUID_MAKE_V4, NULL, NULL);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Datum
 | 
						|
uuid_generate_v5(PG_FUNCTION_ARGS)
 | 
						|
{
 | 
						|
	pg_uuid_t  *ns = PG_GETARG_UUID_P(0);
 | 
						|
	text	   *name = PG_GETARG_TEXT_P(1);
 | 
						|
 | 
						|
	return uuid_generate_v35_internal(UUID_MAKE_V5, ns, name);
 | 
						|
}
 |