mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
220db7ccd8
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);
|
|
}
|