From b9203ee84953006547f4afd58f405874c87bf0dc Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Fri, 18 Apr 2014 17:02:17 +0200 Subject: 3.1 --- shared/ossp_uuid/pgsql/Makefile | 57 +++++ shared/ossp_uuid/pgsql/uuid.c | 436 +++++++++++++++++++++++++++++++++++++ shared/ossp_uuid/pgsql/uuid.sql.in | 244 +++++++++++++++++++++ shared/ossp_uuid/pgsql/uuid.txt | 36 +++ 4 files changed, 773 insertions(+) create mode 100644 shared/ossp_uuid/pgsql/Makefile create mode 100644 shared/ossp_uuid/pgsql/uuid.c create mode 100644 shared/ossp_uuid/pgsql/uuid.sql.in create mode 100644 shared/ossp_uuid/pgsql/uuid.txt (limited to 'shared/ossp_uuid/pgsql') diff --git a/shared/ossp_uuid/pgsql/Makefile b/shared/ossp_uuid/pgsql/Makefile new file mode 100644 index 00000000..a71bbc21 --- /dev/null +++ b/shared/ossp_uuid/pgsql/Makefile @@ -0,0 +1,57 @@ +## +## Makefile for PostgreSQL extension module +## + +# NOTICE: This requires GNU make as the PostgreSQL PGXS build +# environment is based on GNU make features! +# +# NOTICE: Usually one would just use "PGXS := $(shell pg_config +# --pgxs)" followed by "include $(PGXS)" as the template. The problem +# just is that this way (at least still under PostgreSQL 8.1) one +# cannot pass the "-L../.libs -luuid" to the command which links the +# DSO. Hence we fiddle around with the Makefiles which "PGXS" uses +# itself ourself. + +PG_CONFIG ?= pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +POSTGRES := $(shell $(PG_CONFIG) --bindir)/postgres +top_builddir := $(dir $(PGXS))../.. +include $(top_builddir)/src/Makefile.global + +NAME = uuid +OBJS = uuid.o +SO_MAJOR_VERSION = 1 +SO_MINOR_VERSION = 0 + +override CPPFLAGS := -I.. $(CPPFLAGS) +SHLIB_LINK := -L../.libs -luuid +SHLIB_LINK += $(shell test $(shell uname -s) = FreeBSD && echo "-Wl,-Bsymbolic") +SHLIB_LINK += $(shell test $(shell uname -s) = Darwin && echo "-bundle_loader $(POSTGRES)") +rpath := + +all: uuid.sql all-lib + +enable_shared = yes +include $(top_builddir)/src/Makefile.shlib + +uuid.sql: uuid.sql.in + sed -e 's;MODULE_PATHNAME;$(DESTDIR)$(pkglibdir)/uuid$(DLSUFFIX);g' uuid.sql + +install: all + $(mkinstalldirs) $(DESTDIR)$(pkglibdir) + $(mkinstalldirs) $(DESTDIR)$(datadir) + $(INSTALL_SHLIB) $(shlib) $(DESTDIR)$(pkglibdir)/uuid$(DLSUFFIX) + $(INSTALL_DATA) uuid.sql $(DESTDIR)$(datadir)/uuid.sql + +uninstall: + -rm -f $(DESTDIR)$(pkglibdir)/uuid$(DLSUFFIX) + -rm -f $(DESTDIR)$(datadir)/uuid.sql + +clean distclean: clean-lib + rm -f $(OBJS) + rm -f uuid.sql + +realclean: distclean + +test: + diff --git a/shared/ossp_uuid/pgsql/uuid.c b/shared/ossp_uuid/pgsql/uuid.c new file mode 100644 index 00000000..023eda96 --- /dev/null +++ b/shared/ossp_uuid/pgsql/uuid.c @@ -0,0 +1,436 @@ +/* +** OSSP uuid - Universally Unique Identifier +** Copyright (c) 2004-2007 Ralf S. Engelschall +** Copyright (c) 2004-2007 The OSSP Project +** +** This file is part of OSSP uuid, a library for the generation +** of UUIDs which can found at http://www.ossp.org/pkg/lib/uuid/ +** +** Permission to use, copy, modify, and distribute this software for +** any purpose with or without fee is hereby granted, provided that +** the above copyright notice and this permission notice appear in all +** copies. +** +** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +** +** uuid.c: PostgreSQL Binding (C part) +*/ + +/* own headers */ +#include "uuid.h" + +/* PostgreSQL (part 1/2) headers */ +#include "postgres.h" + +/* system headers */ +#include + +/* PostgreSQL (part 2/2) headers */ +#include "fmgr.h" +#include "lib/stringinfo.h" +#include "access/hash.h" + +/* PostgreSQL module magic cookie + (PostgreSQL >= 8.2 only) */ +#ifdef PG_MODULE_MAGIC +PG_MODULE_MAGIC; +#endif + +/* internal UUID datum data structure */ +typedef struct { + unsigned char uuid_bin[UUID_LEN_BIN]; +} uuid_datum_t; + +/* forward declarations */ +Datum pg_uuid_in (PG_FUNCTION_ARGS); +Datum pg_uuid_out (PG_FUNCTION_ARGS); +Datum pg_uuid_recv (PG_FUNCTION_ARGS); +Datum pg_uuid_send (PG_FUNCTION_ARGS); +Datum pg_uuid_hash (PG_FUNCTION_ARGS); +Datum pg_uuid_make (PG_FUNCTION_ARGS); +Datum pg_uuid_eq (PG_FUNCTION_ARGS); +Datum pg_uuid_ne (PG_FUNCTION_ARGS); +Datum pg_uuid_lt (PG_FUNCTION_ARGS); +Datum pg_uuid_gt (PG_FUNCTION_ARGS); +Datum pg_uuid_le (PG_FUNCTION_ARGS); +Datum pg_uuid_ge (PG_FUNCTION_ARGS); +Datum pg_uuid_cmp (PG_FUNCTION_ARGS); + +/* API function: uuid_in */ +PG_FUNCTION_INFO_V1(pg_uuid_in); +Datum pg_uuid_in(PG_FUNCTION_ARGS) +{ + char *uuid_str; + uuid_datum_t *uuid_datum; + uuid_rc_t rc; + uuid_t *uuid; + void *vp; + size_t len; + + /* sanity check input argument */ + if ((uuid_str = PG_GETARG_CSTRING(0)) == NULL) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("invalid UUID string"))); + if ((len = strlen(uuid_str)) != UUID_LEN_STR) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("invalid UUID string length %d (expected %d)", (int)len, UUID_LEN_STR))); + + /* import as string representation */ + if ((rc = uuid_create(&uuid)) != UUID_RC_OK) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to create UUID object: %s", uuid_error(rc)))); + if ((rc = uuid_import(uuid, UUID_FMT_STR, uuid_str, len)) != UUID_RC_OK) { + uuid_destroy(uuid); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to import UUID string representation: %s", uuid_error(rc)))); + } + + /* export as binary representation */ + if ((uuid_datum = (uuid_datum_t *)palloc(sizeof(uuid_datum_t))) == NULL) { + uuid_destroy(uuid); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to allocate UUID datum"))); + } + vp = &(uuid_datum->uuid_bin); + len = sizeof(uuid_datum->uuid_bin); + if ((rc = uuid_export(uuid, UUID_FMT_BIN, &vp, &len)) != UUID_RC_OK) { + uuid_destroy(uuid); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to export UUID binary representation: %s", uuid_error(rc)))); + } + uuid_destroy(uuid); + + /* return UUID datum */ + PG_RETURN_POINTER(uuid_datum); +} + +/* API function: uuid_out */ +PG_FUNCTION_INFO_V1(pg_uuid_out); +Datum pg_uuid_out(PG_FUNCTION_ARGS) +{ + uuid_datum_t *uuid_datum; + uuid_rc_t rc; + uuid_t *uuid; + char *uuid_str; + void *vp; + size_t len; + + /* sanity check input argument */ + if ((uuid_datum = (uuid_datum_t *)PG_GETARG_POINTER(0)) == NULL) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("invalid UUID datum"))); + + /* import as binary representation */ + if ((rc = uuid_create(&uuid)) != UUID_RC_OK) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to create UUID object: %s", uuid_error(rc)))); + if ((rc = uuid_import(uuid, UUID_FMT_BIN, uuid_datum->uuid_bin, sizeof(uuid_datum->uuid_bin))) != UUID_RC_OK) { + uuid_destroy(uuid); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to import UUID binary representation: %s", uuid_error(rc)))); + } + + /* export as string representation */ + len = UUID_LEN_STR+1; + if ((vp = uuid_str = (char *)palloc(len)) == NULL) { + uuid_destroy(uuid); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to allocate UUID string"))); + } + if ((rc = uuid_export(uuid, UUID_FMT_STR, &vp, &len)) != UUID_RC_OK) { + uuid_destroy(uuid); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to export UUID string representation: %s", uuid_error(rc)))); + } + uuid_destroy(uuid); + + /* return UUID string */ + PG_RETURN_CSTRING(uuid_str); +} + +/* API function: uuid_recv */ +PG_FUNCTION_INFO_V1(pg_uuid_recv); +Datum pg_uuid_recv(PG_FUNCTION_ARGS) +{ + StringInfo uuid_internal; + uuid_datum_t *uuid_datum; + + /* sanity check input argument */ + if ((uuid_internal = (StringInfo)PG_GETARG_POINTER(0)) == NULL) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("invalid UUID StringInfo object"))); + if (uuid_internal->len != UUID_LEN_BIN) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("invalid UUID binary length %d (expected %d)", uuid_internal->len, UUID_LEN_BIN))); + + /* import as binary representation */ + if ((uuid_datum = (uuid_datum_t *)palloc(sizeof(uuid_datum_t))) == NULL) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to allocate UUID datum"))); + memcpy(uuid_datum->uuid_bin, uuid_internal->data, uuid_internal->len); + + /* return UUID datum */ + PG_RETURN_POINTER(uuid_datum); +} + +/* API function: uuid_send */ +PG_FUNCTION_INFO_V1(pg_uuid_send); +Datum pg_uuid_send(PG_FUNCTION_ARGS) +{ + uuid_datum_t *uuid_datum; + bytea *uuid_bytea; + + /* sanity check input argument */ + if ((uuid_datum = (uuid_datum_t *)PG_GETARG_POINTER(0)) == NULL) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("invalid UUID datum"))); + + /* export as binary representation */ + if ((uuid_bytea = (bytea *)palloc(VARHDRSZ + UUID_LEN_BIN)) == NULL) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to allocate UUID bytea"))); +#if defined(SET_VARSIZE) /* PostgreSQL >= 8.3 */ + SET_VARSIZE(uuid_bytea, VARHDRSZ + UUID_LEN_BIN); +#else + uuid_bytea->vl_len = VARHDRSZ + UUID_LEN_BIN; +#endif + memcpy(uuid_bytea->vl_dat, uuid_datum->uuid_bin, UUID_LEN_BIN); + + /* return UUID bytea */ + PG_RETURN_BYTEA_P(uuid_bytea); +} + +/* API function: uuid_make */ +PG_FUNCTION_INFO_V1(pg_uuid_make); +Datum pg_uuid_make(PG_FUNCTION_ARGS) +{ + uuid_t *uuid; + uuid_t *uuid_ns; + uuid_rc_t rc; + int version; + unsigned int mode = 0; + uuid_datum_t *uuid_datum; + char *str_ns; + char *str_name; + void *vp; + size_t len; + + /* sanity check input argument */ + version = (int)PG_GETARG_INT32(0); + switch (version) { + case 1: mode = UUID_MAKE_V1; break; + case 3: mode = UUID_MAKE_V3; break; + case 4: mode = UUID_MAKE_V4; break; + case 5: mode = UUID_MAKE_V5; break; + default: + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("invalid UUID version %d (expected 1, 3, 4 or 5)", version))); + } + if ( ((mode & (UUID_MAKE_V1|UUID_MAKE_V4)) && PG_NARGS() != 1) + || ((mode & (UUID_MAKE_V3|UUID_MAKE_V5)) && PG_NARGS() != 3)) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("invalid number (%d) of arguments", PG_NARGS()))); + + /* make a new UUID */ + if ((rc = uuid_create(&uuid)) != UUID_RC_OK) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to create UUID object: %s", uuid_error(rc)))); + if (version == 3 || version == 5) { + if ((str_ns = PG_GETARG_CSTRING(1)) == NULL) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("invalid namespace UUID string"))); + if ((str_name = PG_GETARG_CSTRING(2)) == NULL) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("invalid name string"))); + if ((rc = uuid_create(&uuid_ns)) != UUID_RC_OK) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to create UUID namespace object: %s", uuid_error(rc)))); + if ((rc = uuid_load(uuid_ns, str_ns)) != UUID_RC_OK) { + if ((rc = uuid_import(uuid_ns, UUID_FMT_STR, str_ns, strlen(str_ns))) != UUID_RC_OK) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to import UUID namespace: %s", uuid_error(rc)))); + } + if ((rc = uuid_make(uuid, mode, uuid_ns, str_name)) != UUID_RC_OK) { + uuid_destroy(uuid); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to make v%d UUID: %s", version, uuid_error(rc)))); + } + uuid_destroy(uuid_ns); + } + else { + if ((rc = uuid_make(uuid, mode)) != UUID_RC_OK) { + uuid_destroy(uuid); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to make v%d UUID: %s", version, uuid_error(rc)))); + } + } + + /* export as binary representation */ + if ((uuid_datum = (uuid_datum_t *)palloc(sizeof(uuid_datum_t))) == NULL) { + uuid_destroy(uuid); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to allocate UUID datum"))); + } + vp = &(uuid_datum->uuid_bin); + len = sizeof(uuid_datum->uuid_bin); + if ((rc = uuid_export(uuid, UUID_FMT_BIN, &vp, &len)) != UUID_RC_OK) { + uuid_destroy(uuid); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to export UUID binary representation: %s", uuid_error(rc)))); + } + uuid_destroy(uuid); + PG_RETURN_POINTER(uuid_datum); +} + +/* API function: uuid_hash */ +PG_FUNCTION_INFO_V1(pg_uuid_hash); +Datum pg_uuid_hash(PG_FUNCTION_ARGS) +{ + uuid_datum_t *uuid_datum; + + /* sanity check input argument */ + if ((uuid_datum = (uuid_datum_t *)PG_GETARG_POINTER(0)) == NULL) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("invalid UUID datum argument"))); + + /* return hash value of the UUID */ + PG_RETURN_INT32(hash_any(uuid_datum->uuid_bin, sizeof(uuid_datum->uuid_bin))); +} + +/* INTERNAL function: _uuid_cmp */ +static int _uuid_cmp(PG_FUNCTION_ARGS) +{ + uuid_datum_t *uuid_datum1; + uuid_datum_t *uuid_datum2; + uuid_t *uuid1; + uuid_t *uuid2; + uuid_rc_t rc; + int result; + + /* sanity check input argument */ + if ((uuid_datum1 = (uuid_datum_t *)PG_GETARG_POINTER(0)) == NULL) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("invalid first UUID datum argument"))); + if ((uuid_datum2 = (uuid_datum_t *)PG_GETARG_POINTER(1)) == NULL) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("invalid second UUID datum argument"))); + + /* load both UUIDs */ + if ((rc = uuid_create(&uuid1)) != UUID_RC_OK) + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to create UUID object: %s", uuid_error(rc)))); + if ((rc = uuid_create(&uuid2)) != UUID_RC_OK) { + uuid_destroy(uuid1); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to create UUID object: %s", uuid_error(rc)))); + } + if ((rc = uuid_import(uuid1, UUID_FMT_BIN, uuid_datum1->uuid_bin, sizeof(uuid_datum1->uuid_bin))) != UUID_RC_OK) { + uuid_destroy(uuid1); + uuid_destroy(uuid2); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to import UUID: %s", uuid_error(rc)))); + } + if ((rc = uuid_import(uuid2, UUID_FMT_BIN, uuid_datum2->uuid_bin, sizeof(uuid_datum2->uuid_bin))) != UUID_RC_OK) { + uuid_destroy(uuid1); + uuid_destroy(uuid2); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to import UUID: %s", uuid_error(rc)))); + } + + /* compare UUIDs */ + if ((rc = uuid_compare(uuid1, uuid2, &result)) != UUID_RC_OK) { + uuid_destroy(uuid1); + uuid_destroy(uuid2); + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("failed to compare UUID objects: %s", uuid_error(rc)))); + } + + /* cleanup */ + uuid_destroy(uuid1); + uuid_destroy(uuid2); + + /* return result */ + return result; +} + +/* API function: uuid_eq */ +PG_FUNCTION_INFO_V1(pg_uuid_eq); +Datum pg_uuid_eq(PG_FUNCTION_ARGS) +{ + int rc; + + rc = _uuid_cmp(fcinfo); + PG_RETURN_BOOL(rc == 0); +} + +/* API function: uuid_ne */ +PG_FUNCTION_INFO_V1(pg_uuid_ne); +Datum pg_uuid_ne(PG_FUNCTION_ARGS) +{ + int rc; + + rc = _uuid_cmp(fcinfo); + PG_RETURN_BOOL(rc != 0); +} + +/* API function: uuid_lt */ +PG_FUNCTION_INFO_V1(pg_uuid_lt); +Datum pg_uuid_lt(PG_FUNCTION_ARGS) +{ + int rc; + + rc = _uuid_cmp(fcinfo); + PG_RETURN_BOOL(rc == -1); +} + +/* API function: uuid_gt */ +PG_FUNCTION_INFO_V1(pg_uuid_gt); +Datum pg_uuid_gt(PG_FUNCTION_ARGS) +{ + int rc; + + rc = _uuid_cmp(fcinfo); + PG_RETURN_BOOL(rc == 1); +} + +/* API function: uuid_le */ +PG_FUNCTION_INFO_V1(pg_uuid_le); +Datum pg_uuid_le(PG_FUNCTION_ARGS) +{ + int rc; + + rc = _uuid_cmp(fcinfo); + PG_RETURN_BOOL(rc < 1); +} + +/* API function: uuid_ge */ +PG_FUNCTION_INFO_V1(pg_uuid_ge); +Datum pg_uuid_ge(PG_FUNCTION_ARGS) +{ + int rc; + + rc = _uuid_cmp(fcinfo); + PG_RETURN_BOOL(rc > -1); +} + +/* API function: uuid_cmp */ +PG_FUNCTION_INFO_V1(pg_uuid_cmp); +Datum pg_uuid_cmp(PG_FUNCTION_ARGS) +{ + int rc; + + rc = _uuid_cmp(fcinfo); + PG_RETURN_INT32(rc); +} + diff --git a/shared/ossp_uuid/pgsql/uuid.sql.in b/shared/ossp_uuid/pgsql/uuid.sql.in new file mode 100644 index 00000000..c2f01fcc --- /dev/null +++ b/shared/ossp_uuid/pgsql/uuid.sql.in @@ -0,0 +1,244 @@ +-- +-- OSSP uuid - Universally Unique Identifier +-- Copyright (c) 2004-2007 Ralf S. Engelschall +-- Copyright (c) 2004-2007 The OSSP Project +-- +-- This file is part of OSSP uuid, a library for the generation +-- of UUIDs which can found at http://www.ossp.org/pkg/lib/uuid/ +-- +-- Permission to use, copy, modify, and distribute this software for +-- any purpose with or without fee is hereby granted, provided that +-- the above copyright notice and this permission notice appear in all +-- copies. +-- +-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +-- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +-- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +-- IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +-- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +-- USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +-- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +-- SUCH DAMAGE. +-- +-- uuid.sql: PostgreSQL Binding (SQL part) +-- + +-- +-- prolog +-- + +SET search_path TO public; +SET client_min_messages TO warning; + +DROP FUNCTION uuid_in(CSTRING) CASCADE; +DROP FUNCTION uuid_out(uuid) CASCADE; +DROP FUNCTION uuid_recv(INTERNAL) CASCADE; +DROP FUNCTION uuid_send(uuid) CASCADE; +DROP TYPE uuid CASCADE; +DROP CAST (CSTRING AS uuid) CASCADE; +DROP CAST (uuid AS CSTRING) CASCADE; + +DROP FUNCTION uuid(CSTRING) CASCADE; +DROP FUNCTION uuid(INTEGER) CASCADE; +DROP FUNCTION uuid(INTEGER, CSTRING, CSTRING) CASCADE; + +DROP FUNCTION uuid_eq(uuid) CASCADE; +DROP FUNCTION uuid_ne(uuid) CASCADE; +DROP FUNCTION uuid_lt(uuid, uuid) CASCADE; +DROP FUNCTION uuid_gt(uuid, uuid) CASCADE; +DROP FUNCTION uuid_le(uuid, uuid) CASCADE; +DROP FUNCTION uuid_ge(uuid, uuid) CASCADE; +DROP OPERATOR =(uuid,uuid) CASCADE; +DROP OPERATOR <>(uuid,uuid) CASCADE; +DROP OPERATOR <(uuid,uuid) CASCADE; +DROP OPERATOR >(uuid,uuid) CASCADE; +DROP OPERATOR <=(uuid,uuid) CASCADE; +DROP OPERATOR >=(uuid,uuid) CASCADE; + +DROP FUNCTION uuid_hash(uuid) CASCADE; +DROP FUNCTION uuid_cmp(uuid, uuid) CASCADE; +DROP OPERATOR CLASS uuid_ops USING hash CASCADE; +DROP OPERATOR CLASS uuid_ops USING btree CASCADE; + +BEGIN; + +-- +-- the UUID data type +-- + +CREATE FUNCTION + uuid_in(CSTRING) RETURNS uuid + STRICT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_in'; + +CREATE FUNCTION + uuid_out(uuid) RETURNS CSTRING + STRICT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_out'; + +CREATE FUNCTION + uuid_recv(INTERNAL) RETURNS uuid + STRICT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_recv'; + +CREATE FUNCTION + uuid_send(uuid) RETURNS BYTEA + STRICT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_send'; + +CREATE TYPE uuid ( + INPUT = uuid_in, -- for SQL input + OUTPUT = uuid_out, -- for SQL output + RECEIVE = uuid_recv, -- for DB input + SEND = uuid_send, -- for DB output + DEFAULT = 'uuid(1)', + INTERNALLENGTH = 16, + ALIGNMENT = char +); + +COMMENT ON TYPE uuid + IS 'UUID type'; + +-- CREATE CAST (CSTRING AS uuid) +-- WITH FUNCTION uuid_in(CSTRING) AS ASSIGNMENT; +-- +-- CREATE CAST (uuid AS CSTRING) +-- WITH FUNCTION uuid_out(uuid) AS ASSIGNMENT; + +-- +-- the UUID constructor function +-- + +CREATE FUNCTION + uuid(CSTRING) RETURNS uuid + IMMUTABLE STRICT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_in'; + +CREATE FUNCTION + uuid(INTEGER) RETURNS uuid + VOLATILE CALLED ON NULL INPUT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_make'; + +CREATE FUNCTION + uuid(INTEGER, CSTRING, CSTRING) RETURNS uuid + VOLATILE CALLED ON NULL INPUT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_make'; + +-- +-- the UUID operators +-- + +CREATE FUNCTION + uuid_eq(uuid, uuid) RETURNS BOOL + IMMUTABLE STRICT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_eq'; + +CREATE FUNCTION + uuid_ne(uuid, uuid) RETURNS BOOL + IMMUTABLE STRICT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_ne'; + +CREATE FUNCTION + uuid_lt(uuid, uuid) RETURNS BOOL + IMMUTABLE STRICT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_lt'; + +CREATE FUNCTION + uuid_gt(uuid, uuid) RETURNS BOOL + IMMUTABLE STRICT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_gt'; + +CREATE FUNCTION + uuid_le(uuid, uuid) RETURNS BOOL + IMMUTABLE STRICT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_le'; + +CREATE FUNCTION + uuid_ge(uuid, uuid) RETURNS BOOL + IMMUTABLE STRICT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_ge'; + +CREATE OPERATOR = ( + leftarg = uuid, + rightarg = uuid, + negator = <>, + procedure = uuid_eq +); + +CREATE OPERATOR <> ( + leftarg = uuid, + rightarg = uuid, + negator = =, + procedure = uuid_ne +); + +CREATE OPERATOR < ( + leftarg = uuid, + rightarg = uuid, + commutator = >, + negator = >=, + procedure = uuid_lt +); + +CREATE OPERATOR > ( + leftarg = uuid, + rightarg = uuid, + commutator = <, + negator = <=, + procedure = uuid_gt +); + +CREATE OPERATOR <= ( + leftarg = uuid, + rightarg = uuid, + commutator = >=, + negator = >, + procedure = uuid_le +); + +CREATE OPERATOR >= ( + leftarg = uuid, + rightarg = uuid, + commutator = <=, + negator = <, + procedure = uuid_ge +); + +-- +-- the UUID support for indexing +-- + +CREATE FUNCTION + uuid_hash(uuid) RETURNS INTEGER + IMMUTABLE STRICT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_hash'; + +CREATE FUNCTION + uuid_cmp(uuid, uuid) RETURNS INTEGER + IMMUTABLE STRICT + LANGUAGE C AS 'MODULE_PATHNAME', 'pg_uuid_cmp'; + +CREATE OPERATOR CLASS uuid_ops + DEFAULT FOR TYPE uuid USING hash AS + OPERATOR 1 =, -- 1: equal + FUNCTION 1 uuid_hash(uuid); + +CREATE OPERATOR CLASS uuid_ops + DEFAULT FOR TYPE uuid USING btree AS + OPERATOR 1 <, -- 1: less than + OPERATOR 2 <=, -- 2: less than or equal + OPERATOR 3 =, -- 3: equal + OPERATOR 4 >=, -- 4: greater than or equal + OPERATOR 5 >, -- 5: greater than + FUNCTION 1 uuid_cmp(uuid, uuid); + +-- +-- epilog +-- + +COMMIT; + diff --git a/shared/ossp_uuid/pgsql/uuid.txt b/shared/ossp_uuid/pgsql/uuid.txt new file mode 100644 index 00000000..c9506de4 --- /dev/null +++ b/shared/ossp_uuid/pgsql/uuid.txt @@ -0,0 +1,36 @@ + + OSSP uuid bindings for PostgreSQL + ================================= + + This is the OSSP uuid binding for the PostgreSQL RDBMS, providing + native UUID data type support. + + Installation + ------------ + + In order to install the OSSP uuid binding into the PostgreSQL database + one has run: + + $ /bin/psql \ + -d \ + -U postgresql \ + -f /share/postgresql/uuid.sql + + Usage + ----- + + psql -d + psql> CREATE TABLE test (id UUID DEFAULT uuid(1), name TEXT); + psql> INSERT INTO test (name) VALUES + ('foo'); + psql> INSERT INTO test (id, name) VALUES + (uuid(1), 'bar'); + psql> INSERT INTO test (id, name) VALUES + (uuid(3, 'ns:URL', 'http://www.ossp.org/'), 'baz'); + psql> INSERT INTO test (id, name) VALUES + (uuid(3, '6ba7b811-9dad-11d1-80b4-00c04fd430c8', + 'http://www.ossp.org/'), 'quux'); + psql> SELECT uuid(4); + psql> SELECT * FROM test WHERE id = uuid(3, 'ns:URL', 'http://www.ossp.org/'); + psql> DROP TABLE test; + -- cgit