Support BSD and e2fsprogs UUID libraries alongside OSSP UUID library.

Allow the contrib/uuid-ossp extension to be built atop any one of these
three popular UUID libraries.  (The extension's name is now arguably a
misnomer, but we'll keep it the same so as not to cause unnecessary
compatibility issues for users.)

We would not normally consider a change like this post-beta1, but the issue
has been forced by our upgrade to autoconf 2.69, whose more rigorous header
checks are causing OSSP's header files to be rejected on some platforms.
It's been foreseen for some time that we'd have to move away from depending
on OSSP UUID due to lack of upstream maintenance, so this is a down payment
on that problem.

While at it, add some simple regression tests, in hopes of catching any
major incompatibilities between the three implementations.

Matteo Beccati, with some further hacking by me
This commit is contained in:
Tom Lane 2014-05-27 19:42:08 -04:00
parent 616afee14d
commit b8cc8f9473
12 changed files with 927 additions and 181 deletions

374
configure vendored
View File

@ -657,7 +657,7 @@ acx_pthread_config
have_win32_dbghelp
HAVE_IPV6
LIBOBJS
OSSP_UUID_LIBS
UUID_LIBS
ZIC
python_enable_shared
python_additional_libs
@ -705,7 +705,8 @@ with_system_tzdata
with_libxslt
with_libxml
XML2_CONFIG
with_ossp_uuid
UUID_EXTRA_OBJS
with_uuid
with_selinux
with_openssl
krb_srvtab
@ -826,6 +827,7 @@ with_openssl
with_selinux
with_readline
with_libedit_preferred
with_uuid
with_ossp_uuid
with_libxml
with_libxslt
@ -1512,7 +1514,8 @@ Optional Packages:
--without-readline do not use GNU Readline nor BSD Libedit for editing
--with-libedit-preferred
prefer BSD Libedit over GNU Readline
--with-ossp-uuid build contrib/uuid-ossp, requires OSSP UUID library
--with-uuid=LIB build contrib/uuid-ossp using LIB (bsd,e2fs,ossp)
--with-ossp-uuid obsolete spelling of --with-uuid=ossp
--with-libxml build with XML support
--with-libxslt use XSLT support when building contrib/xml2
--with-system-tzdata=DIR
@ -1737,6 +1740,73 @@ fi
} # ac_fn_c_try_cpp
# ac_fn_c_check_func LINENO FUNC VAR
# ----------------------------------
# Tests whether FUNC exists, setting the cache variable VAR accordingly
ac_fn_c_check_func ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
For example, HP-UX 11i <limits.h> declares gettimeofday. */
#define $2 innocuous_$2
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $2 (); below.
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
<limits.h> exists even on freestanding compilers. */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
#undef $2
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char $2 ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined __stub_$2 || defined __stub___$2
choke me
#endif
int
main ()
{
return $2 ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
eval "$3=yes"
else
eval "$3=no"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func
# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists, giving a warning if it cannot be compiled using
@ -2195,73 +2265,6 @@ rm -f conftest.val
} # ac_fn_c_compute_int
# ac_fn_c_check_func LINENO FUNC VAR
# ----------------------------------
# Tests whether FUNC exists, setting the cache variable VAR accordingly
ac_fn_c_check_func ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
For example, HP-UX 11i <limits.h> declares gettimeofday. */
#define $2 innocuous_$2
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $2 (); below.
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
<limits.h> exists even on freestanding compilers. */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
#undef $2
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char $2 ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined __stub_$2 || defined __stub___$2
choke me
#endif
int
main ()
{
return $2 ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
eval "$3=yes"
else
eval "$3=no"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func
# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
# ---------------------------------------------
# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
@ -5614,8 +5617,37 @@ fi
#
# OSSP UUID library
# UUID library
#
# There are at least three UUID libraries in common use: the FreeBSD/NetBSD
# library, the e2fsprogs libuuid (now part of util-linux-ng), and the OSSP
# UUID library. More than one of these might be present on a given platform,
# so we make the user say which one she wants.
#
# Check whether --with-uuid was given.
if test "${with_uuid+set}" = set; then :
withval=$with_uuid;
case $withval in
yes)
as_fn_error $? "argument required for --with-uuid option" "$LINENO" 5
;;
no)
as_fn_error $? "argument required for --with-uuid option" "$LINENO" 5
;;
*)
;;
esac
fi
if test x"$with_uuid" = x"" ; then
with_uuid=no
fi
@ -5640,6 +5672,31 @@ else
fi
if test "$with_ossp_uuid" = yes ; then
with_uuid=ossp
fi
if test "$with_uuid" = bsd ; then
$as_echo "#define HAVE_UUID_BSD 1" >>confdefs.h
UUID_EXTRA_OBJS="md5.o sha1.o"
elif test "$with_uuid" = e2fs ; then
$as_echo "#define HAVE_UUID_E2FS 1" >>confdefs.h
UUID_EXTRA_OBJS="md5.o sha1.o"
elif test "$with_uuid" = ossp ; then
$as_echo "#define HAVE_UUID_OSSP 1" >>confdefs.h
UUID_EXTRA_OBJS=""
elif test "$with_uuid" = no ; then
UUID_EXTRA_OBJS=""
else
as_fn_error $? "--with-uuid must specify one of bsd, e2fs, or ossp" "$LINENO" 5
fi
@ -8775,7 +8832,66 @@ fi
fi
# for contrib/uuid-ossp
if test "$with_ossp_uuid" = yes ; then
if test "$with_uuid" = bsd ; then
# On BSD, the UUID functions are in libc
ac_fn_c_check_func "$LINENO" "uuid_to_string" "ac_cv_func_uuid_to_string"
if test "x$ac_cv_func_uuid_to_string" = xyes; then :
UUID_LIBS=""
else
as_fn_error $? "BSD UUID functions are not present" "$LINENO" 5
fi
elif test "$with_uuid" = e2fs ; then
# On OS X, the UUID functions are in libc
ac_fn_c_check_func "$LINENO" "uuid_generate" "ac_cv_func_uuid_generate"
if test "x$ac_cv_func_uuid_generate" = xyes; then :
UUID_LIBS=""
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate in -luuid" >&5
$as_echo_n "checking for uuid_generate in -luuid... " >&6; }
if ${ac_cv_lib_uuid_uuid_generate+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-luuid $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char uuid_generate ();
int
main ()
{
return uuid_generate ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_uuid_uuid_generate=yes
else
ac_cv_lib_uuid_uuid_generate=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate" >&5
$as_echo "$ac_cv_lib_uuid_uuid_generate" >&6; }
if test "x$ac_cv_lib_uuid_uuid_generate" = xyes; then :
UUID_LIBS="-luuid"
else
as_fn_error $? "library 'uuid' is required for E2FS UUID" "$LINENO" 5
fi
fi
elif test "$with_uuid" = ossp ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_export in -lossp-uuid" >&5
$as_echo_n "checking for uuid_export in -lossp-uuid... " >&6; }
if ${ac_cv_lib_ossp_uuid_uuid_export+:} false; then :
@ -8813,7 +8929,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ossp_uuid_uuid_export" >&5
$as_echo "$ac_cv_lib_ossp_uuid_uuid_export" >&6; }
if test "x$ac_cv_lib_ossp_uuid_uuid_export" = xyes; then :
OSSP_UUID_LIBS="-lossp-uuid"
UUID_LIBS="-lossp-uuid"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_export in -luuid" >&5
$as_echo_n "checking for uuid_export in -luuid... " >&6; }
@ -8852,9 +8968,9 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_export" >&5
$as_echo "$ac_cv_lib_uuid_uuid_export" >&6; }
if test "x$ac_cv_lib_uuid_uuid_export" = xyes; then :
OSSP_UUID_LIBS="-luuid"
UUID_LIBS="-luuid"
else
as_fn_error $? "library 'ossp-uuid' or 'uuid' is required for OSSP-UUID" "$LINENO" 5
as_fn_error $? "library 'ossp-uuid' or 'uuid' is required for OSSP UUID" "$LINENO" 5
fi
fi
@ -9398,7 +9514,86 @@ fi
fi
# for contrib/uuid-ossp
if test "$with_ossp_uuid" = yes ; then
if test "$with_uuid" = bsd ; then
for ac_header in uuid.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "uuid.h" "ac_cv_header_uuid_h" "$ac_includes_default"
if test "x$ac_cv_header_uuid_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UUID_H 1
_ACEOF
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <uuid.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "uuid_to_string" >/dev/null 2>&1; then :
else
as_fn_error $? "header file <uuid.h> does not match BSD UUID library" "$LINENO" 5
fi
rm -f conftest*
else
as_fn_error $? "header file <uuid.h> is required for BSD UUID" "$LINENO" 5
fi
done
elif test "$with_uuid" = e2fs ; then
for ac_header in uuid/uuid.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default"
if test "x$ac_cv_header_uuid_uuid_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UUID_UUID_H 1
_ACEOF
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <uuid/uuid.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "uuid_generate" >/dev/null 2>&1; then :
else
as_fn_error $? "header file <uuid/uuid.h> does not match E2FS UUID library" "$LINENO" 5
fi
rm -f conftest*
else
for ac_header in uuid.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "uuid.h" "ac_cv_header_uuid_h" "$ac_includes_default"
if test "x$ac_cv_header_uuid_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UUID_H 1
_ACEOF
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <uuid.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "uuid_generate" >/dev/null 2>&1; then :
else
as_fn_error $? "header file <uuid.h> does not match E2FS UUID library" "$LINENO" 5
fi
rm -f conftest*
else
as_fn_error $? "header file <uuid/uuid.h> or <uuid.h> is required for E2FS UUID" "$LINENO" 5
fi
done
fi
done
elif test "$with_uuid" = ossp ; then
for ac_header in ossp/uuid.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "ossp/uuid.h" "ac_cv_header_ossp_uuid_h" "$ac_includes_default"
@ -9406,19 +9601,42 @@ if test "x$ac_cv_header_ossp_uuid_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_OSSP_UUID_H 1
_ACEOF
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <ossp/uuid.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "uuid_export" >/dev/null 2>&1; then :
else
as_fn_error $? "header file <ossp/uuid.h> does not match OSSP UUID library" "$LINENO" 5
fi
rm -f conftest*
for ac_header in uuid.h
else
for ac_header in uuid.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "uuid.h" "ac_cv_header_uuid_h" "$ac_includes_default"
if test "x$ac_cv_header_uuid_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UUID_H 1
_ACEOF
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <uuid.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "uuid_export" >/dev/null 2>&1; then :
else
as_fn_error $? "header file <ossp/uuid.h> or <uuid.h> is required for OSSP-UUID" "$LINENO" 5
as_fn_error $? "header file <uuid.h> does not match OSSP UUID library" "$LINENO" 5
fi
rm -f conftest*
else
as_fn_error $? "header file <ossp/uuid.h> or <uuid.h> is required for OSSP UUID" "$LINENO" 5
fi
done

View File

@ -694,10 +694,38 @@ PGAC_ARG_BOOL(with, libedit-preferred, no,
#
# OSSP UUID library
# UUID library
#
PGAC_ARG_BOOL(with, ossp-uuid, no, [build contrib/uuid-ossp, requires OSSP UUID library])
AC_SUBST(with_ossp_uuid)
# There are at least three UUID libraries in common use: the FreeBSD/NetBSD
# library, the e2fsprogs libuuid (now part of util-linux-ng), and the OSSP
# UUID library. More than one of these might be present on a given platform,
# so we make the user say which one she wants.
#
PGAC_ARG_REQ(with, uuid, [LIB], [build contrib/uuid-ossp using LIB (bsd,e2fs,ossp)])
if test x"$with_uuid" = x"" ; then
with_uuid=no
fi
PGAC_ARG_BOOL(with, ossp-uuid, no, [obsolete spelling of --with-uuid=ossp])
if test "$with_ossp_uuid" = yes ; then
with_uuid=ossp
fi
if test "$with_uuid" = bsd ; then
AC_DEFINE([HAVE_UUID_BSD], 1, [Define to 1 if you have BSD UUID support.])
UUID_EXTRA_OBJS="md5.o sha1.o"
elif test "$with_uuid" = e2fs ; then
AC_DEFINE([HAVE_UUID_E2FS], 1, [Define to 1 if you have E2FS UUID support.])
UUID_EXTRA_OBJS="md5.o sha1.o"
elif test "$with_uuid" = ossp ; then
AC_DEFINE([HAVE_UUID_OSSP], 1, [Define to 1 if you have OSSP UUID support.])
UUID_EXTRA_OBJS=""
elif test "$with_uuid" = no ; then
UUID_EXTRA_OBJS=""
else
AC_MSG_ERROR([--with-uuid must specify one of bsd, e2fs, or ossp])
fi
AC_SUBST(with_uuid)
AC_SUBST(UUID_EXTRA_OBJS)
#
@ -948,14 +976,26 @@ if test "$with_selinux" = yes; then
fi
# for contrib/uuid-ossp
if test "$with_ossp_uuid" = yes ; then
if test "$with_uuid" = bsd ; then
# On BSD, the UUID functions are in libc
AC_CHECK_FUNC(uuid_to_string,
[UUID_LIBS=""],
[AC_MSG_ERROR([BSD UUID functions are not present])])
elif test "$with_uuid" = e2fs ; then
# On OS X, the UUID functions are in libc
AC_CHECK_FUNC(uuid_generate,
[UUID_LIBS=""],
[AC_CHECK_LIB(uuid, uuid_generate,
[UUID_LIBS="-luuid"],
[AC_MSG_ERROR([library 'uuid' is required for E2FS UUID])])])
elif test "$with_uuid" = ossp ; then
AC_CHECK_LIB(ossp-uuid, uuid_export,
[OSSP_UUID_LIBS="-lossp-uuid"],
[UUID_LIBS="-lossp-uuid"],
[AC_CHECK_LIB(uuid, uuid_export,
[OSSP_UUID_LIBS="-luuid"],
[AC_MSG_ERROR([library 'ossp-uuid' or 'uuid' is required for OSSP-UUID])])])
[UUID_LIBS="-luuid"],
[AC_MSG_ERROR([library 'ossp-uuid' or 'uuid' is required for OSSP UUID])])])
fi
AC_SUBST(OSSP_UUID_LIBS)
AC_SUBST(UUID_LIBS)
##
@ -1075,10 +1115,27 @@ if test "$with_bonjour" = yes ; then
fi
# for contrib/uuid-ossp
if test "$with_ossp_uuid" = yes ; then
AC_CHECK_HEADERS(ossp/uuid.h, [], [
AC_CHECK_HEADERS(uuid.h, [],
[AC_MSG_ERROR([header file <ossp/uuid.h> or <uuid.h> is required for OSSP-UUID])])])
if test "$with_uuid" = bsd ; then
AC_CHECK_HEADERS(uuid.h,
[AC_EGREP_HEADER([uuid_to_string], uuid.h, [],
[AC_MSG_ERROR([header file <uuid.h> does not match BSD UUID library])])],
[AC_MSG_ERROR([header file <uuid.h> is required for BSD UUID])])
elif test "$with_uuid" = e2fs ; then
AC_CHECK_HEADERS(uuid/uuid.h,
[AC_EGREP_HEADER([uuid_generate], uuid/uuid.h, [],
[AC_MSG_ERROR([header file <uuid/uuid.h> does not match E2FS UUID library])])],
[AC_CHECK_HEADERS(uuid.h,
[AC_EGREP_HEADER([uuid_generate], uuid.h, [],
[AC_MSG_ERROR([header file <uuid.h> does not match E2FS UUID library])])],
[AC_MSG_ERROR([header file <uuid/uuid.h> or <uuid.h> is required for E2FS UUID])])])
elif test "$with_uuid" = ossp ; then
AC_CHECK_HEADERS(ossp/uuid.h,
[AC_EGREP_HEADER([uuid_export], ossp/uuid.h, [],
[AC_MSG_ERROR([header file <ossp/uuid.h> does not match OSSP UUID library])])],
[AC_CHECK_HEADERS(uuid.h,
[AC_EGREP_HEADER([uuid_export], uuid.h, [],
[AC_MSG_ERROR([header file <uuid.h> does not match OSSP UUID library])])],
[AC_MSG_ERROR([header file <ossp/uuid.h> or <uuid.h> is required for OSSP UUID])])])
fi
if test "$PORTNAME" = "win32" ; then

View File

@ -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

6
contrib/uuid-ossp/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
/md5.c
/sha1.c
# Generated subdirectories
/log/
/results/
/tmp_check/

View File

@ -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) $< .

View File

@ -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)

View File

@ -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();

View File

@ -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
/* better both be 16 */
#if (UUID_LEN != UUID_LEN_BIN)
#undef uuid_hash
/*
* 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,44 +189,9 @@ special_uuid_value(const char *name)
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");
}
/* 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)
uuid_generate_internal(int mode, const uuid_t *ns, const char *name, int len)
{
uuid_t *uuid;
char *str;
@ -172,20 +212,6 @@ uuid_generate_internal(int mode, const uuid_t *ns, const char *name)
}
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)
{
@ -201,7 +227,8 @@ uuid_generate_v35_internal(int mode, pg_uuid_t *ns, text *name)
result = uuid_generate_internal(mode,
ns_uuid,
text_to_cstring(name));
text_to_cstring(name),
0);
rc = uuid_destroy(ns_uuid);
if (rc != UUID_RC_OK)
@ -210,6 +237,248 @@ uuid_generate_v35_internal(int mode, pg_uuid_t *ns, text *name)
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");
#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)
@ -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
}

View File

@ -869,17 +869,46 @@ su - postgres
</listitem>
</varlistentry>
<varlistentry>
<term><option>--with-uuid=<replaceable>LIBRARY</replaceable></option></term>
<listitem>
<para>
Build the <![%standalone-include[uuid-ossp]]>
<![%standalone-ignore[<xref linkend="uuid-ossp">]]> module
(which provides functions to generate UUIDs), using the specified
UUID library.<indexterm><primary>UUID</primary></indexterm>
<replaceable>LIBRARY</replaceable> must be one of:
</para>
<itemizedlist>
<listitem>
<para>
<option>bsd</> to use the UUID functions found in FreeBSD, NetBSD,
and some other BSD-derived systems
</para>
</listitem>
<listitem>
<para>
<option>e2fs</> to use the UUID library created by
the <literal>e2fsprogs</> project; this library is present in most
Linux systems and in Mac OS X, and can be obtained for other
platforms as well
</para>
</listitem>
<listitem>
<para>
<option>ossp</> to use the <ulink
url="http://www.ossp.org/pkg/lib/uuid/">OSSP UUID library</ulink>
</para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--with-ossp-uuid</option></term>
<listitem>
<para>
Build components using the <ulink
url="http://www.ossp.org/pkg/lib/uuid/">OSSP UUID
library</ulink>. Specifically, build the
<![%standalone-include[uuid-ossp]]>
<![%standalone-ignore[<xref linkend="uuid-ossp">]]> module,
which provides functions to generate
UUIDs.<indexterm><primary>UUID</primary></indexterm>
Obsolete equivalent of <literal>--with-uuid=ossp</literal>.
</para>
</listitem>
</varlistentry>

View File

@ -13,20 +13,6 @@
are also functions to produce certain special UUID constants.
</para>
<para>
This module depends on the OSSP UUID library, which can be found at
<ulink url="http://www.ossp.org/pkg/lib/uuid/"></ulink>.
</para>
<note>
<para>
The OSSP UUID library is not well maintained, and is becoming increasingly
difficult to port to newer platforms. If you only need randomly-generated
(version 4) UUIDs, consider using the <function>gen_random_uuid()</>
function from the <xref linkend="pgcrypto"> module instead.
</para>
</note>
<sect2>
<title><literal>uuid-ossp</literal> Functions</title>
@ -172,6 +158,39 @@ SELECT uuid_generate_v3(uuid_ns_url(), 'http://www.postgresql.org');
</table>
</sect2>
<sect2>
<title>Building <filename>uuid-ossp</></title>
<para>
Historically this module depended on the OSSP UUID library, which accounts
for the module's name. While the OSSP UUID library can still be found
at <ulink url="http://www.ossp.org/pkg/lib/uuid/"></ulink>, it is not well
maintained, and is becoming increasingly difficult to port to newer
platforms. <filename>uuid-ossp</> can now be built without the OSSP
library on some platforms. On FreeBSD, NetBSD, and some other BSD-derived
platforms, suitable UUID creation functions are included in the
core <filename>libc</> library. On Linux, Mac OS X, and some other
platforms, suitable functions are provided in the <filename>libuuid</>
library, which originally came from the <literal>e2fsprogs</> project
(though on modern Linux it is considered part
of <literal>util-linux-ng</>). When invoking <filename>configure</>,
specify <option>--with-uuid=bsd</option> to use the BSD functions,
or <option>--with-uuid=e2fs</option> to
use <literal>e2fsprogs</>' <filename>libuuid</>, or
<option>--with-uuid=ossp</option> to use the OSSP UUID library.
More than one of these libraries might be available on a particular
machine, so <filename>configure</> does not automatically choose one.
</para>
<note>
<para>
If you only need randomly-generated (version 4) UUIDs,
consider using the <function>gen_random_uuid()</> function
from the <xref linkend="pgcrypto"> module instead.
</para>
</note>
</sect2>
<sect2>
<title>Author</title>

View File

@ -163,11 +163,11 @@ with_perl = @with_perl@
with_python = @with_python@
with_tcl = @with_tcl@
with_openssl = @with_openssl@
with_ossp_uuid = @with_ossp_uuid@
with_selinux = @with_selinux@
with_libxml = @with_libxml@
with_libxslt = @with_libxslt@
with_system_tzdata = @with_system_tzdata@
with_uuid = @with_uuid@
with_zlib = @with_zlib@
enable_rpath = @enable_rpath@
enable_nls = @enable_nls@
@ -240,7 +240,8 @@ DLLWRAP = @DLLWRAP@
LIBS = @LIBS@
LDAP_LIBS_FE = @LDAP_LIBS_FE@
LDAP_LIBS_BE = @LDAP_LIBS_BE@
OSSP_UUID_LIBS = @OSSP_UUID_LIBS@
UUID_LIBS = @UUID_LIBS@
UUID_EXTRA_OBJS = @UUID_EXTRA_OBJS@
LD = @LD@
with_gnu_ld = @with_gnu_ld@
ld_R_works = @ld_R_works@

View File

@ -602,9 +602,21 @@
/* Define to 1 if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
/* Define to 1 if you have BSD UUID support. */
#undef HAVE_UUID_BSD
/* Define to 1 if you have E2FS UUID support. */
#undef HAVE_UUID_E2FS
/* Define to 1 if you have the <uuid.h> header file. */
#undef HAVE_UUID_H
/* Define to 1 if you have OSSP UUID support. */
#undef HAVE_UUID_OSSP
/* Define to 1 if you have the <uuid/uuid.h> header file. */
#undef HAVE_UUID_UUID_H
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF