summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/Makefile2
-rw-r--r--contrib/uuid-ossp/.gitignore6
-rw-r--r--contrib/uuid-ossp/Makefile16
-rw-r--r--contrib/uuid-ossp/expected/uuid_ossp.out91
-rw-r--r--contrib/uuid-ossp/sql/uuid_ossp.sql22
-rw-r--r--contrib/uuid-ossp/uuid-ossp.c401
6 files changed, 474 insertions, 64 deletions
diff --git a/contrib/Makefile b/contrib/Makefile
index 8dc40f7de00..b37d0dd2c31 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -64,7 +64,7 @@ else
ALWAYS_SUBDIRS += sslinfo
endif
-ifeq ($(with_ossp_uuid),yes)
+ifneq ($(with_uuid),no)
SUBDIRS += uuid-ossp
else
ALWAYS_SUBDIRS += uuid-ossp
diff --git a/contrib/uuid-ossp/.gitignore b/contrib/uuid-ossp/.gitignore
new file mode 100644
index 00000000000..6c989c78729
--- /dev/null
+++ b/contrib/uuid-ossp/.gitignore
@@ -0,0 +1,6 @@
+/md5.c
+/sha1.c
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/uuid-ossp/Makefile b/contrib/uuid-ossp/Makefile
index 9b2d2e3ff93..335cc7ef50a 100644
--- a/contrib/uuid-ossp/Makefile
+++ b/contrib/uuid-ossp/Makefile
@@ -1,12 +1,21 @@
# contrib/uuid-ossp/Makefile
MODULE_big = uuid-ossp
-OBJS = uuid-ossp.o
+OBJS = uuid-ossp.o $(UUID_EXTRA_OBJS)
EXTENSION = uuid-ossp
DATA = uuid-ossp--1.0.sql uuid-ossp--unpackaged--1.0.sql
-SHLIB_LINK += $(OSSP_UUID_LIBS)
+REGRESS = uuid_ossp
+
+SHLIB_LINK += $(UUID_LIBS)
+
+# We copy some needed files verbatim from pgcrypto
+pgcrypto_src = $(top_srcdir)/contrib/pgcrypto
+
+PG_CPPFLAGS = -I$(pgcrypto_src)
+
+EXTRA_CLEAN = md5.c sha1.c
ifdef USE_PGXS
PG_CONFIG = pg_config
@@ -18,3 +27,6 @@ top_builddir = ../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif
+
+md5.c sha1.c: % : $(pgcrypto_src)/%
+ rm -f $@ && $(LN_S) $< .
diff --git a/contrib/uuid-ossp/expected/uuid_ossp.out b/contrib/uuid-ossp/expected/uuid_ossp.out
new file mode 100644
index 00000000000..986843c8976
--- /dev/null
+++ b/contrib/uuid-ossp/expected/uuid_ossp.out
@@ -0,0 +1,91 @@
+CREATE EXTENSION "uuid-ossp";
+SELECT uuid_nil();
+ uuid_nil
+--------------------------------------
+ 00000000-0000-0000-0000-000000000000
+(1 row)
+
+SELECT uuid_ns_dns();
+ uuid_ns_dns
+--------------------------------------
+ 6ba7b810-9dad-11d1-80b4-00c04fd430c8
+(1 row)
+
+SELECT uuid_ns_url();
+ uuid_ns_url
+--------------------------------------
+ 6ba7b811-9dad-11d1-80b4-00c04fd430c8
+(1 row)
+
+SELECT uuid_ns_oid();
+ uuid_ns_oid
+--------------------------------------
+ 6ba7b812-9dad-11d1-80b4-00c04fd430c8
+(1 row)
+
+SELECT uuid_ns_x500();
+ uuid_ns_x500
+--------------------------------------
+ 6ba7b814-9dad-11d1-80b4-00c04fd430c8
+(1 row)
+
+SELECT uuid_generate_v1() < uuid_generate_v1();
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT uuid_generate_v1() < uuid_generate_v1mc();
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT substr(uuid_generate_v1()::text, 25) = substr(uuid_generate_v1()::text, 25);
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT substr(uuid_generate_v1()::text, 25) <> substr(uuid_generate_v1mc()::text, 25);
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT substr(uuid_generate_v1mc()::text, 25) <> substr(uuid_generate_v1mc()::text, 25);
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT ('x' || substr(uuid_generate_v1mc()::text, 25, 2))::bit(8) & '00000011';
+ ?column?
+----------
+ 00000011
+(1 row)
+
+SELECT uuid_generate_v3(uuid_ns_dns(), 'www.widgets.com');
+ uuid_generate_v3
+--------------------------------------
+ 3d813cbb-47fb-32ba-91df-831e1593ac29
+(1 row)
+
+SELECT uuid_generate_v5(uuid_ns_dns(), 'www.widgets.com');
+ uuid_generate_v5
+--------------------------------------
+ 21f7f8de-8051-5b89-8680-0195ef798b6a
+(1 row)
+
+SELECT uuid_generate_v4()::text ~ '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$';
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT uuid_generate_v4() <> uuid_generate_v4();
+ ?column?
+----------
+ t
+(1 row)
+
diff --git a/contrib/uuid-ossp/sql/uuid_ossp.sql b/contrib/uuid-ossp/sql/uuid_ossp.sql
new file mode 100644
index 00000000000..29fba21b3f7
--- /dev/null
+++ b/contrib/uuid-ossp/sql/uuid_ossp.sql
@@ -0,0 +1,22 @@
+CREATE EXTENSION "uuid-ossp";
+
+SELECT uuid_nil();
+SELECT uuid_ns_dns();
+SELECT uuid_ns_url();
+SELECT uuid_ns_oid();
+SELECT uuid_ns_x500();
+
+SELECT uuid_generate_v1() < uuid_generate_v1();
+SELECT uuid_generate_v1() < uuid_generate_v1mc();
+
+SELECT substr(uuid_generate_v1()::text, 25) = substr(uuid_generate_v1()::text, 25);
+SELECT substr(uuid_generate_v1()::text, 25) <> substr(uuid_generate_v1mc()::text, 25);
+SELECT substr(uuid_generate_v1mc()::text, 25) <> substr(uuid_generate_v1mc()::text, 25);
+
+SELECT ('x' || substr(uuid_generate_v1mc()::text, 25, 2))::bit(8) & '00000011';
+
+SELECT uuid_generate_v3(uuid_ns_dns(), 'www.widgets.com');
+SELECT uuid_generate_v5(uuid_ns_dns(), 'www.widgets.com');
+
+SELECT uuid_generate_v4()::text ~ '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$';
+SELECT uuid_generate_v4() <> uuid_generate_v4();
diff --git a/contrib/uuid-ossp/uuid-ossp.c b/contrib/uuid-ossp/uuid-ossp.c
index 8f99084df34..f8c33d2b469 100644
--- a/contrib/uuid-ossp/uuid-ossp.c
+++ b/contrib/uuid-ossp/uuid-ossp.c
@@ -1,40 +1,113 @@
/*-------------------------------------------------------------------------
*
- * UUID generation functions using the OSSP UUID library
+ * UUID generation functions using the BSD, E2FS or OSSP UUID library
*
* Copyright (c) 2007-2014, PostgreSQL Global Development Group
*
+ * Portions Copyright (c) 2009 Andrew Gierth
+ *
* contrib/uuid-ossp/uuid-ossp.c
*
*-------------------------------------------------------------------------
*/
#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.
+ * 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.
*/
-#ifdef HAVE_OSSP_UUID_H
-#include <ossp/uuid.h>
-#else
+#define uuid_hash bsd_uuid_hash
+
#ifdef HAVE_UUID_H
#include <uuid.h>
-#else
-#error OSSP uuid.h not found
#endif
+#ifdef HAVE_OSSP_UUID_H
+#include <ossp/uuid.h>
#endif
+#ifdef HAVE_UUID_UUID_H
+#include <uuid/uuid.h>
+#endif
+
+#undef uuid_hash
-/* better both be 16 */
-#if (UUID_LEN != UUID_LEN_BIN)
+/*
+ * Some BSD variants offer md5 and sha1 implementations but Linux does not,
+ * so we use a copy of the ones from pgcrypto. Not needed with OSSP, though.
+ */
+#ifndef HAVE_UUID_OSSP
+#include "md5.h"
+#include "sha1.h"
+#endif
+
+
+/* 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 = htonl(uu.time_low); \
+ uu.time_mid = htons(uu.time_mid); \
+ uu.time_hi_and_version = htons(uu.time_hi_and_version); \
+} while (0)
+
+#define UUID_TO_LOCAL(uu) \
+do { \
+ uu.time_low = ntohl(uu.time_low); \
+ uu.time_mid = ntohs(uu.time_mid); \
+ uu.time_hi_and_version = ntohs(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;
@@ -51,6 +124,8 @@ 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)
{
@@ -114,100 +189,294 @@ special_uuid_value(const char *name)
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;
+ 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));
+}
+
+
+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),
+ 0);
+
+ rc = uuid_destroy(ns_uuid);
+ if (rc != UUID_RC_OK)
+ pguuid_complain(rc);
+
+ return result;
+}
+
+#else /* !HAVE_UUID_OSSP */
+
+static Datum
+uuid_generate_internal(int v, unsigned char *ns, 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);
+
+ /*
+ * 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);
+ }
+ if (str)
+ 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)
+ {
+ MD5_CTX ctx;
+
+ MD5Init(&ctx);
+ MD5Update(&ctx, ns, sizeof(uu));
+ MD5Update(&ctx, (unsigned char *) ptr, len);
+ MD5Final((unsigned char *) &uu, &ctx);
+ }
+ else
+ {
+ SHA1_CTX ctx;
+
+ SHA1Init(&ctx);
+ SHA1Update(&ctx, ns, sizeof(uu));
+ SHA1Update(&ctx, (unsigned char *) ptr, len);
+ SHA1Final((unsigned char *) &uu, &ctx);
+ }
+
+ /* 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);
+
+ if (str)
+ 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");
-}
-
-
-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));
+#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);
+ return uuid_generate_internal(UUID_MAKE_V1, NULL, NULL, 0);
}
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);
+#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 result;
+ return uuid_generate_internal(UUID_MAKE_V1 | UUID_MAKE_MC, NULL,
+ buf, 13);
}
@@ -217,14 +486,19 @@ uuid_generate_v3(PG_FUNCTION_ARGS)
pg_uuid_t *ns = PG_GETARG_UUID_P(0);
text *name = PG_GETARG_TEXT_P(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(name), VARSIZE(name) - VARHDRSZ);
+#endif
}
Datum
uuid_generate_v4(PG_FUNCTION_ARGS)
{
- return uuid_generate_internal(UUID_MAKE_V4, NULL, NULL);
+ return uuid_generate_internal(UUID_MAKE_V4, NULL, NULL, 0);
}
@@ -234,5 +508,10 @@ uuid_generate_v5(PG_FUNCTION_ARGS)
pg_uuid_t *ns = PG_GETARG_UUID_P(0);
text *name = PG_GETARG_TEXT_P(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(name), VARSIZE(name) - VARHDRSZ);
+#endif
}