aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/Makefile5
-rw-r--r--src/backend/utils/adt/uuid.c279
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/catalog/pg_amop.h15
-rw-r--r--src/include/catalog/pg_amproc.h4
-rw-r--r--src/include/catalog/pg_cast.h6
-rw-r--r--src/include/catalog/pg_opclass.h4
-rw-r--r--src/include/catalog/pg_operator.h10
-rw-r--r--src/include/catalog/pg_opfamily.h5
-rw-r--r--src/include/catalog/pg_proc.h31
-rw-r--r--src/include/catalog/pg_type.h7
-rw-r--r--src/include/utils/builtins.h18
-rw-r--r--src/include/utils/uuid.h27
-rw-r--r--src/test/regress/expected/uuid.out136
-rw-r--r--src/test/regress/parallel_schedule4
-rw-r--r--src/test/regress/serial_schedule3
-rw-r--r--src/test/regress/sql/uuid.sql79
17 files changed, 621 insertions, 16 deletions
diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile
index 238fb8e862f..ad3b848607b 100644
--- a/src/backend/utils/adt/Makefile
+++ b/src/backend/utils/adt/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for utils/adt
#
-# $PostgreSQL: pgsql/src/backend/utils/adt/Makefile,v 1.62 2007/01/20 17:16:13 petere Exp $
+# $PostgreSQL: pgsql/src/backend/utils/adt/Makefile,v 1.63 2007/01/28 16:16:52 neilc Exp $
#
subdir = src/backend/utils/adt
@@ -25,7 +25,8 @@ OBJS = acl.o arrayfuncs.o array_userfuncs.o arrayutils.o bool.o \
tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \
network.o mac.o inet_net_ntop.o inet_net_pton.o \
ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \
- ascii.o quote.o pgstatfuncs.o encode.o dbsize.o genfile.o xml.o
+ ascii.o quote.o pgstatfuncs.o encode.o dbsize.o genfile.o xml.o \
+ uuid.o
like.o: like.c like_match.c
diff --git a/src/backend/utils/adt/uuid.c b/src/backend/utils/adt/uuid.c
new file mode 100644
index 00000000000..124d430dbfa
--- /dev/null
+++ b/src/backend/utils/adt/uuid.c
@@ -0,0 +1,279 @@
+/*-------------------------------------------------------------------------
+ *
+ * uuid.c
+ * Functions for the built-in type "uuid".
+ *
+ * Copyright (c) 2007, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * $PostgreSQL: pgsql/src/backend/utils/adt/uuid.c,v 1.1 2007/01/28 16:16:52 neilc Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/hash.h"
+#include "libpq/pqformat.h"
+#include "utils/builtins.h"
+#include "utils/uuid.h"
+
+/* Accepted GUID formats */
+
+/* UUID_FMT1 is the default output format */
+#define UUID_FMT1 "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
+#define UUID_FMT2 "{%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx}"
+#define UUID_FMT3 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
+
+/* UUIDs are accepted in any of the following textual input formats. */
+#define UUID_CHK_FMT1 "00000000-0000-0000-0000-000000000000"
+#define UUID_CHK_FMT2 "{00000000-0000-0000-0000-000000000000}"
+#define UUID_CHK_FMT3 "00000000000000000000000000000000"
+
+#define PRINT_SIZE 40
+
+/* uuid size in bytes */
+#define UUID_LEN 16
+
+/* The uuid_t type is declared as struct uuid_t in uuid.h */
+struct uuid_t
+{
+ char data[UUID_LEN];
+};
+
+static void uuid_data_from_string(const char *source, unsigned char *data);
+static void string_from_uuid_data(const char *fmt, const char *data, char *uuid_str);
+static bool parse_uuid_string(const char *fmt, const char *chk_fmt,
+ const char *source, unsigned char *data);
+static bool is_valid_format(const char *source, const char *fmt);
+static int32 uuid_internal_cmp(uuid_t *arg1, uuid_t *arg2);
+
+Datum
+uuid_in(PG_FUNCTION_ARGS)
+{
+ char *uuid_str = PG_GETARG_CSTRING(0);
+ uuid_t *uuid;
+ uint8 data[UUID_LEN];
+
+ uuid_data_from_string(uuid_str, data);
+ uuid = (uuid_t *) palloc(sizeof(uuid_t));
+ memcpy(uuid->data, data, UUID_LEN);
+ PG_RETURN_UUID_P(uuid);
+}
+
+Datum
+uuid_out(PG_FUNCTION_ARGS)
+{
+ uuid_t *uuid = (uuid_t *) PG_GETARG_POINTER(0);
+ char *uuid_str;
+
+ uuid_str = (char *) palloc(PRINT_SIZE);
+ string_from_uuid_data(UUID_FMT1, uuid->data, uuid_str);
+ PG_RETURN_CSTRING(uuid_str);
+}
+
+/* string to uuid convertor by various format types */
+static void
+uuid_data_from_string(const char *source, unsigned char *data)
+{
+ if (!parse_uuid_string(UUID_FMT1, UUID_CHK_FMT1, source, data) &&
+ !parse_uuid_string(UUID_FMT2, UUID_CHK_FMT2, source, data) &&
+ !parse_uuid_string(UUID_FMT3, UUID_CHK_FMT3, source, data))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for uuid: \"%s\"",
+ source)));
+ }
+}
+
+/* check the validity of a uuid string by a given format */
+static bool
+is_valid_format(const char *source, const char *fmt)
+{
+ int i;
+ int fmtlen = strlen(fmt);
+
+ /* check length first */
+ if (fmtlen != strlen(source))
+ return false;
+
+ for (i = 0; i < fmtlen; i++)
+ {
+ int fc;
+ int sc;
+ bool valid_chr;
+
+ fc = fmt[i];
+ sc = source[i];
+
+ /* false if format chr is { or - and source is not */
+ if (fc != '0' && fc != sc)
+ return false;
+
+ /* check for valid char in source */
+ valid_chr = (sc >= '0' && sc <= '9') ||
+ (sc >= 'a' && sc <= 'f' ) ||
+ (sc >= 'A' && sc <= 'F' );
+
+ if (fc == '0' && !valid_chr)
+ return false;
+ }
+
+ return true;
+}
+
+/* parse the uuid string to a format and return true if okay */
+static bool
+parse_uuid_string(const char *fmt, const char *chk_fmt,
+ const char *source, unsigned char *data)
+{
+ int result = sscanf(source, fmt,
+ &data[0], &data[1], &data[2], &data[3], &data[4],
+ &data[5], &data[6], &data[7], &data[8], &data[9],
+ &data[10], &data[11], &data[12], &data[13],
+ &data[14], &data[15]);
+
+ return (result == 16) && is_valid_format(source, chk_fmt);
+}
+
+/* create a string representation of the uuid */
+static void
+string_from_uuid_data(const char *fmt, const char *data, char *uuid_str)
+{
+ snprintf(uuid_str, PRINT_SIZE, fmt,
+ data[0], data[1], data[2], data[3], data[4],
+ data[5], data[6], data[7], data[8], data[9],
+ data[10], data[11], data[12], data[13],
+ data[14], data[15]);
+}
+
+Datum
+uuid_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buffer = (StringInfo) PG_GETARG_POINTER(0);
+ uuid_t *uuid;
+
+ uuid = (uuid_t *) palloc(UUID_LEN);
+ memcpy(uuid->data, pq_getmsgbytes(buffer, UUID_LEN), UUID_LEN);
+ PG_RETURN_POINTER(uuid);
+}
+
+Datum
+uuid_send(PG_FUNCTION_ARGS)
+{
+ uuid_t *uuid = PG_GETARG_UUID_P(0);
+ StringInfoData buffer;
+
+ pq_begintypsend(&buffer);
+ pq_sendbytes(&buffer, uuid->data, UUID_LEN);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buffer));
+}
+
+/* internal uuid compare function */
+static int32
+uuid_internal_cmp(uuid_t *arg1, uuid_t *arg2)
+{
+ return memcmp(arg1->data, arg2->data, UUID_LEN);
+}
+
+Datum
+uuid_lt(PG_FUNCTION_ARGS)
+{
+ uuid_t *arg1 = PG_GETARG_UUID_P(0);
+ uuid_t *arg2 = PG_GETARG_UUID_P(1);
+
+ PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) < 0);
+}
+
+Datum
+uuid_le(PG_FUNCTION_ARGS)
+{
+ uuid_t *arg1 = PG_GETARG_UUID_P(0);
+ uuid_t *arg2 = PG_GETARG_UUID_P(1);
+
+ PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) <= 0);
+}
+
+Datum
+uuid_eq(PG_FUNCTION_ARGS)
+{
+ uuid_t *arg1 = PG_GETARG_UUID_P(0);
+ uuid_t *arg2 = PG_GETARG_UUID_P(1);
+
+ PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) == 0);
+}
+
+Datum
+uuid_ge(PG_FUNCTION_ARGS)
+{
+ uuid_t *arg1 = PG_GETARG_UUID_P(0);
+ uuid_t *arg2 = PG_GETARG_UUID_P(1);
+
+ PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) >= 0);
+}
+
+Datum
+uuid_gt(PG_FUNCTION_ARGS)
+{
+ uuid_t *arg1 = PG_GETARG_UUID_P(0);
+ uuid_t *arg2 = PG_GETARG_UUID_P(1);
+
+ PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) > 0);
+}
+
+Datum
+uuid_ne(PG_FUNCTION_ARGS)
+{
+ uuid_t *arg1 = PG_GETARG_UUID_P(0);
+ uuid_t *arg2 = PG_GETARG_UUID_P(1);
+
+ PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) != 0);
+}
+
+/* handler for btree index operator */
+Datum
+uuid_cmp(PG_FUNCTION_ARGS)
+{
+ uuid_t *arg1 = PG_GETARG_UUID_P(0);
+ uuid_t *arg2 = PG_GETARG_UUID_P(1);
+
+ PG_RETURN_INT32(uuid_internal_cmp(arg1, arg2));
+}
+
+/* hash index support */
+Datum
+uuid_hash(PG_FUNCTION_ARGS)
+{
+ uuid_t *key = PG_GETARG_UUID_P(0);
+ return hash_any((unsigned char *) key, sizeof(uuid_t));
+}
+
+/* cast text to uuid */
+Datum
+text_uuid(PG_FUNCTION_ARGS)
+{
+ text *input = PG_GETARG_TEXT_P(0);
+ int length;
+ char *str;
+ Datum result;
+
+ length = VARSIZE(input) - VARHDRSZ;
+ str = palloc(length + 1);
+ memcpy(str, VARDATA(input), length);
+ *(str + length) = '\0';
+
+ result = DirectFunctionCall1(uuid_in, CStringGetDatum(str));
+ pfree(str);
+ PG_RETURN_DATUM(result);
+}
+
+/* cast uuid to text */
+Datum
+uuid_text(PG_FUNCTION_ARGS)
+{
+ uuid_t *uuid = PG_GETARG_UUID_P(0);
+ Datum uuid_str = DirectFunctionCall1(uuid_out, UUIDPGetDatum(uuid));
+
+ PG_RETURN_DATUM(DirectFunctionCall1(textin, uuid_str));
+}
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index ccf5f90357e..89dfefe30fb 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.376 2007/01/22 01:35:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.377 2007/01/28 16:16:52 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200701211
+#define CATALOG_VERSION_NO 200701281
#endif
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index 7137c6e1c34..01e47df7d9c 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -29,7 +29,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.77 2007/01/05 22:19:52 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.78 2007/01/28 16:16:52 neilc Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -487,6 +487,16 @@ DATA(insert ( 397 2277 2277 3 f 1070 403 ));
DATA(insert ( 397 2277 2277 4 f 1075 403 ));
DATA(insert ( 397 2277 2277 5 f 1073 403 ));
+/*
+ * btree uuid_ops
+ */
+
+DATA(insert ( 2968 2950 2950 1 f 2974 403 ));
+DATA(insert ( 2968 2950 2950 2 f 2976 403 ));
+DATA(insert ( 2968 2950 2950 3 f 2972 403 ));
+DATA(insert ( 2968 2950 2950 4 f 2977 403 ));
+DATA(insert ( 2968 2950 2950 5 f 2975 403 ));
+
/*
* hash index _ops
*/
@@ -548,6 +558,9 @@ DATA(insert ( 2231 1042 1042 1 f 2328 405 ));
DATA(insert ( 2232 19 19 1 f 2334 405 ));
/* aclitem_ops */
DATA(insert ( 2235 1033 1033 1 f 974 405 ));
+/* uuid_ops */
+DATA(insert ( 2969 2950 2950 1 f 2972 405 ));
+
/*
* gist box_ops
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
index bc77f54a384..64db6483417 100644
--- a/src/include/catalog/pg_amproc.h
+++ b/src/include/catalog/pg_amproc.h
@@ -22,7 +22,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.62 2007/01/05 22:19:52 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.63 2007/01/28 16:16:52 neilc Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -127,6 +127,7 @@ DATA(insert ( 2099 790 790 1 377 ));
DATA(insert ( 2233 703 703 1 380 ));
DATA(insert ( 2234 704 704 1 381 ));
DATA(insert ( 2789 27 27 1 2794 ));
+DATA(insert ( 2968 2950 2950 1 2960 ));
/* hash */
@@ -160,6 +161,7 @@ DATA(insert ( 2229 25 25 1 456 ));
DATA(insert ( 2231 1042 1042 1 456 ));
DATA(insert ( 2232 19 19 1 455 ));
DATA(insert ( 2235 1033 1033 1 329 ));
+DATA(insert ( 2969 2950 2950 1 2963 ));
/* gist */
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
index 2c5a2e9e9c5..a66b8c5b2e6 100644
--- a/src/include/catalog/pg_cast.h
+++ b/src/include/catalog/pg_cast.h
@@ -10,7 +10,7 @@
*
* Copyright (c) 2002-2007, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.28 2007/01/05 22:19:52 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.29 2007/01/28 16:16:52 neilc Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -397,4 +397,8 @@ DATA(insert ( 1560 1560 1685 i ));
DATA(insert ( 1562 1562 1687 i ));
DATA(insert ( 1700 1700 1703 i ));
+/* casts to and from uuid */
+DATA(insert ( 25 2950 2964 a ));
+DATA(insert ( 2950 25 2965 a ));
+
#endif /* PG_CAST_H */
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
index 21c7d54ae8e..148f02db2a9 100644
--- a/src/include/catalog/pg_opclass.h
+++ b/src/include/catalog/pg_opclass.h
@@ -28,7 +28,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.73 2007/01/05 22:19:52 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.74 2007/01/28 16:16:52 neilc Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -200,5 +200,7 @@ DATA(insert ( 2742 _timestamp_ops PGNSP PGUID 2745 1115 t 1114 ));
DATA(insert ( 2742 _money_ops PGNSP PGUID 2745 791 t 790 ));
DATA(insert ( 2742 _reltime_ops PGNSP PGUID 2745 1024 t 703 ));
DATA(insert ( 2742 _tinterval_ops PGNSP PGUID 2745 1025 t 704 ));
+DATA(insert ( 403 uuid_ops PGNSP PGUID 2968 2950 t 0 ));
+DATA(insert ( 405 uuid_ops PGNSP PGUID 2969 2950 t 0 ));
#endif /* PG_OPCLASS_H */
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index 26a15f7139e..6411da05c3a 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.148 2007/01/05 22:19:53 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.149 2007/01/28 16:16:52 neilc Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -895,6 +895,14 @@ DATA(insert OID = 2875 ( "@" PGNSP PGUID b f f 601 628 16 0 0 on_sl - - )
DATA(insert OID = 2876 ( "@" PGNSP PGUID b f f 601 603 16 0 0 on_sb - - ));
DATA(insert OID = 2877 ( "~" PGNSP PGUID b f f 1034 1033 16 0 0 aclcontains - - ));
+/* uuid operators */
+DATA(insert OID = 2972 ( "=" PGNSP PGUID b t t 2950 2950 16 2972 2973 uuid_eq eqsel eqjoinsel ));
+DATA(insert OID = 2973 ( "<>" PGNSP PGUID b f f 2950 2950 16 2973 2972 uuid_ne neqsel neqjoinsel ));
+DATA(insert OID = 2974 ( "<" PGNSP PGUID b f f 2950 2950 16 2975 2977 uuid_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2975 ( ">" PGNSP PGUID b f f 2950 2950 16 2974 2976 uuid_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2976 ( "<=" PGNSP PGUID b f f 2950 2950 16 2977 2975 uuid_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2977 ( ">=" PGNSP PGUID b f f 2950 2950 16 2976 2974 uuid_ge scalargtsel scalargtjoinsel ));
+
/*
* function prototypes
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
index 1f91e58f3fb..63d1b277643 100644
--- a/src/include/catalog/pg_opfamily.h
+++ b/src/include/catalog/pg_opfamily.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_opfamily.h,v 1.2 2007/01/05 22:19:53 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_opfamily.h,v 1.3 2007/01/28 16:16:52 neilc Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -134,5 +134,8 @@ DATA(insert OID = 2593 ( 783 box_ops PGNSP PGUID ));
DATA(insert OID = 2594 ( 783 poly_ops PGNSP PGUID ));
DATA(insert OID = 2595 ( 783 circle_ops PGNSP PGUID ));
DATA(insert OID = 2745 ( 2742 array_ops PGNSP PGUID ));
+DATA(insert OID = 2968 ( 403 uuid_ops PGNSP PGUID ));
+DATA(insert OID = 2969 ( 405 uuid_ops PGNSP PGUID ));
+
#endif /* PG_OPFAMILY_H */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index c0c9a3cfd05..eaee3410962 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.440 2007/01/22 01:35:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.441 2007/01/28 16:16:52 neilc Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@@ -4046,6 +4046,35 @@ DESCR("aggregate transition function");
DATA(insert OID = 2901 ( xmlagg PGNSP PGUID 12 1 0 t f f f i 1 142 "142" _null_ _null_ _null_ aggregate_dummy - _null_ ));
DESCR("concatenate XML values");
+/* uuid */
+DATA(insert OID = 2952 ( uuid_in PGNSP PGUID 12 1 0 f f t f i 1 2950 "2275" _null_ _null_ _null_ uuid_in - _null_ ));
+DESCR("I/O");
+DATA(insert OID = 2953 ( uuid_out PGNSP PGUID 12 1 0 f f t f i 1 2275 "2950" _null_ _null_ _null_ uuid_out - _null_ ));
+DESCR("I/O");
+DATA(insert OID = 2954 ( uuid_lt PGNSP PGUID 12 1 0 f f t f i 2 16 "2950 2950" _null_ _null_ _null_ uuid_lt - _null_ ));
+DESCR("less-than");
+DATA(insert OID = 2955 ( uuid_le PGNSP PGUID 12 1 0 f f t f i 2 16 "2950 2950" _null_ _null_ _null_ uuid_le - _null_ ));
+DESCR("less-than-or-equal");
+DATA(insert OID = 2956 ( uuid_eq PGNSP PGUID 12 1 0 f f t f i 2 16 "2950 2950" _null_ _null_ _null_ uuid_eq - _null_ ));
+DESCR("equal");
+DATA(insert OID = 2957 ( uuid_ge PGNSP PGUID 12 1 0 f f t f i 2 16 "2950 2950" _null_ _null_ _null_ uuid_ge - _null_ ));
+DESCR("greater-than-or-equal");
+DATA(insert OID = 2958 ( uuid_gt PGNSP PGUID 12 1 0 f f t f i 2 16 "2950 2950" _null_ _null_ _null_ uuid_gt - _null_ ));
+DESCR("greater-than");
+DATA(insert OID = 2959 ( uuid_ne PGNSP PGUID 12 1 0 f f t f i 2 16 "2950 2950" _null_ _null_ _null_ uuid_ne - _null_ ));
+DESCR("not-equal");
+DATA(insert OID = 2960 ( uuid_cmp PGNSP PGUID 12 1 0 f f t f i 2 23 "2950 2950" _null_ _null_ _null_ uuid_cmp - _null_ ));
+DESCR("btree less-equal-greater");
+DATA(insert OID = 2961 ( uuid_recv PGNSP PGUID 12 1 0 f f t f i 1 2950 "2281" _null_ _null_ _null_ uuid_recv - _null_ ));
+DESCR("I/O");
+DATA(insert OID = 2962 ( uuid_send PGNSP PGUID 12 1 0 f f t f i 1 17 "2950" _null_ _null_ _null_ uuid_send - _null_ ));
+DESCR("I/O");
+DATA(insert OID = 2963 ( uuid_hash PGNSP PGUID 12 1 0 f f t f i 1 23 "2950" _null_ _null_ _null_ uuid_hash - _null_ ));
+DESCR("hash");
+DATA(insert OID = 2964 ( uuid PGNSP PGUID 12 1 0 f f t f i 1 2950 "25" _null_ _null_ _null_ text_uuid - _null_ ));
+DESCR("convert text to uuid");
+DATA(insert OID = 2965 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "2950" _null_ _null_ _null_ uuid_text - _null_ ));
+DESCR("convert uuid to text");
/*
* Symbolic values for provolatile column: these indicate whether the result
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index ebaa13049ef..89849c25fcb 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.179 2007/01/05 22:19:53 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.180 2007/01/28 16:16:54 neilc Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -561,6 +561,11 @@ DATA(insert OID = 2282 ( opaque PGNSP PGUID 4 t p t \054 0 0 opaque_in opaque
DATA(insert OID = 2283 ( anyelement PGNSP PGUID 4 t p t \054 0 0 anyelement_in anyelement_out - - - - - i p f 0 -1 0 _null_ _null_ ));
#define ANYELEMENTOID 2283
+/* uuid */
+DATA(insert OID = 2950 ( uuid PGNSP PGUID 16 f b t \054 0 0 uuid_in uuid_out uuid_recv uuid_send - - - c p f 0 -1 0 _null_ _null_ ));
+DESCR("UUID datatype");
+DATA(insert OID = 2951 ( _uuid PGNSP PGUID -1 f b t \054 0 2950 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ ));
+
/*
* prototypes for functions in pg_type.c
*/
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 3368e2c024f..aee4095654c 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.286 2007/01/16 21:41:14 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.287 2007/01/28 16:16:54 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -926,4 +926,20 @@ extern Datum pg_prepared_statement(PG_FUNCTION_ARGS);
/* utils/mmgr/portalmem.c */
extern Datum pg_cursor(PG_FUNCTION_ARGS);
+/* uuid.c */
+extern Datum uuid_in(PG_FUNCTION_ARGS);
+extern Datum uuid_out(PG_FUNCTION_ARGS);
+extern Datum uuid_send(PG_FUNCTION_ARGS);
+extern Datum uuid_recv(PG_FUNCTION_ARGS);
+extern Datum uuid_lt(PG_FUNCTION_ARGS);
+extern Datum uuid_le(PG_FUNCTION_ARGS);
+extern Datum uuid_eq(PG_FUNCTION_ARGS);
+extern Datum uuid_ge(PG_FUNCTION_ARGS);
+extern Datum uuid_gt(PG_FUNCTION_ARGS);
+extern Datum uuid_ne(PG_FUNCTION_ARGS);
+extern Datum uuid_cmp(PG_FUNCTION_ARGS);
+extern Datum uuid_hash(PG_FUNCTION_ARGS);
+extern Datum text_uuid(PG_FUNCTION_ARGS);
+extern Datum uuid_text(PG_FUNCTION_ARGS);
+
#endif /* BUILTINS_H */
diff --git a/src/include/utils/uuid.h b/src/include/utils/uuid.h
new file mode 100644
index 00000000000..12cb00a0b71
--- /dev/null
+++ b/src/include/utils/uuid.h
@@ -0,0 +1,27 @@
+/*-------------------------------------------------------------------------
+ *
+ * uuid.h
+ * Header file for the "uuid" data type.
+ *
+ * Copyright (c) 2007, PostgreSQL Global Development Group
+ *
+ * $PostgreSQL: pgsql/src/include/utils/uuid.h,v 1.1 2007/01/28 16:16:54 neilc Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef UUID_H
+#define UUID_H
+
+/* guid size in bytes */
+#define UUID_LEN 16
+
+/* opaque struct; defined in uuid.c */
+typedef struct uuid_t uuid_t;
+
+/* fmgr interface macros */
+#define UUIDPGetDatum(X) PointerGetDatum(X)
+#define PG_RETURN_UUID_P(X) return UUIDPGetDatum(X)
+#define DatumGetUUIDP(X) ((uuid_t *) DatumGetPointer(X))
+#define PG_GETARG_UUID_P(X) DatumGetUUIDP(PG_GETARG_DATUM(X))
+
+#endif /* UUID_H */
diff --git a/src/test/regress/expected/uuid.out b/src/test/regress/expected/uuid.out
new file mode 100644
index 00000000000..9f714ad2e14
--- /dev/null
+++ b/src/test/regress/expected/uuid.out
@@ -0,0 +1,136 @@
+-- regression test for the uuid datatype
+-- creating test tables
+CREATE TABLE guid1
+(
+ guid_field UUID,
+ text_field TEXT DEFAULT(now())
+);
+CREATE TABLE guid2
+(
+ guid_field UUID,
+ text_field TEXT DEFAULT(now())
+);
+-- inserting invalid data tests
+-- too long
+INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111F');
+ERROR: invalid input syntax for uuid: "11111111-1111-1111-1111-111111111111F"
+-- too short
+INSERT INTO guid1(guid_field) VALUES('{11111111-1111-1111-1111-11111111111}');
+ERROR: invalid input syntax for uuid: "{11111111-1111-1111-1111-11111111111}"
+-- valid data but invalid format
+INSERT INTO guid1(guid_field) VALUES('111-11111-1111-1111-1111-111111111111');
+ERROR: invalid input syntax for uuid: "111-11111-1111-1111-1111-111111111111"
+INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222 ');
+ERROR: invalid input syntax for uuid: "{22222222-2222-2222-2222-222222222222 "
+-- invalid data
+INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-G111-111111111111');
+ERROR: invalid input syntax for uuid: "11111111-1111-1111-G111-111111111111"
+INSERT INTO guid1(guid_field) VALUES('11+11111-1111-1111-1111-111111111111');
+ERROR: invalid input syntax for uuid: "11+11111-1111-1111-1111-111111111111"
+--inserting three input formats
+INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111');
+INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222}');
+INSERT INTO guid1(guid_field) VALUES('33333333333333333333333333333333');
+-- retrieving the inserted data
+SELECT guid_field FROM guid1;
+ guid_field
+--------------------------------------
+ 11111111-1111-1111-1111-111111111111
+ 22222222-2222-2222-2222-222222222222
+ 33333333-3333-3333-3333-333333333333
+(3 rows)
+
+-- ordering test
+SELECT guid_field FROM guid1 ORDER BY guid_field ASC;
+ guid_field
+--------------------------------------
+ 11111111-1111-1111-1111-111111111111
+ 22222222-2222-2222-2222-222222222222
+ 33333333-3333-3333-3333-333333333333
+(3 rows)
+
+SELECT guid_field FROM guid1 ORDER BY guid_field DESC;
+ guid_field
+--------------------------------------
+ 33333333-3333-3333-3333-333333333333
+ 22222222-2222-2222-2222-222222222222
+ 11111111-1111-1111-1111-111111111111
+(3 rows)
+
+-- = operator test
+SELECT COUNT(*) FROM guid1 WHERE guid_field = '33333333-3333-3333-3333-333333333333';
+ count
+-------
+ 1
+(1 row)
+
+-- <> operator test
+SELECT COUNT(*) FROM guid1 WHERE guid_field <> '11111111111111111111111111111111';
+ count
+-------
+ 2
+(1 row)
+
+-- < operator test
+SELECT COUNT(*) FROM guid1 WHERE guid_field < '22222222-2222-2222-2222-222222222222';
+ count
+-------
+ 1
+(1 row)
+
+-- <= operator test
+SELECT COUNT(*) FROM guid1 WHERE guid_field <= '22222222-2222-2222-2222-222222222222';
+ count
+-------
+ 2
+(1 row)
+
+-- > operator test
+SELECT COUNT(*) FROM guid1 WHERE guid_field > '22222222-2222-2222-2222-222222222222';
+ count
+-------
+ 1
+(1 row)
+
+-- >= operator test
+SELECT COUNT(*) FROM guid1 WHERE guid_field >= '22222222-2222-2222-2222-222222222222';
+ count
+-------
+ 2
+(1 row)
+
+-- btree and hash index creation test
+CREATE INDEX guid1_btree ON guid1 USING BTREE (guid_field);
+CREATE INDEX guid1_hash ON guid1 USING HASH (guid_field);
+-- unique index test
+CREATE UNIQUE INDEX guid1_unique_BTREE ON guid1 USING BTREE (guid_field);
+-- should fail
+INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111');
+ERROR: duplicate key violates unique constraint "guid1_unique_btree"
+-- check to see whether the new indexes are actually there
+SELECT count(*) FROM pg_class WHERE relkind='i' AND relname LIKE 'guid%';
+ count
+-------
+ 3
+(1 row)
+
+-- populating the test tables with additional records
+INSERT INTO guid1(guid_field) VALUES('44444444-4444-4444-4444-444444444444');
+INSERT INTO guid2(guid_field) VALUES('11111111-1111-1111-1111-111111111111');
+INSERT INTO guid2(guid_field) VALUES('{22222222-2222-2222-2222-222222222222}');
+INSERT INTO guid2(guid_field) VALUES('33333333333333333333333333333333');
+-- join test
+SELECT COUNT(*) FROM guid1 g1 INNER JOIN guid2 g2 ON g1.guid_field = g2.guid_field;
+ count
+-------
+ 3
+(1 row)
+
+SELECT COUNT(*) FROM guid1 g1 LEFT JOIN guid2 g2 ON g1.guid_field = g2.guid_field WHERE g2.guid_field IS NULL;
+ count
+-------
+ 1
+(1 row)
+
+-- clean up
+DROP TABLE guid1, guid2 CASCADE;
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index c2e53fb5c35..efc1f1fef6e 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -1,8 +1,8 @@
# ----------
# The first group of parallel test
-# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.37 2007/01/20 17:15:43 neilc Exp $
+# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.38 2007/01/28 16:16:54 neilc Exp $
# ----------
-test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric
+test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric uuid
# Depends on things setup during char, varchar and text
test: strings
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 4c1c63c62e0..75e8b83138b 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -1,4 +1,4 @@
-# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.35 2007/01/20 17:15:43 neilc Exp $
+# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.36 2007/01/28 16:16:54 neilc Exp $
# This should probably be in an order similar to parallel_schedule.
test: boolean
test: char
@@ -13,6 +13,7 @@ test: float4
test: float8
test: bit
test: numeric
+test: uuid
test: strings
test: numerology
test: point
diff --git a/src/test/regress/sql/uuid.sql b/src/test/regress/sql/uuid.sql
new file mode 100644
index 00000000000..93153da9d70
--- /dev/null
+++ b/src/test/regress/sql/uuid.sql
@@ -0,0 +1,79 @@
+-- regression test for the uuid datatype
+-- creating test tables
+CREATE TABLE guid1
+(
+ guid_field UUID,
+ text_field TEXT DEFAULT(now())
+);
+CREATE TABLE guid2
+(
+ guid_field UUID,
+ text_field TEXT DEFAULT(now())
+);
+
+-- inserting invalid data tests
+-- too long
+INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111F');
+-- too short
+INSERT INTO guid1(guid_field) VALUES('{11111111-1111-1111-1111-11111111111}');
+-- valid data but invalid format
+INSERT INTO guid1(guid_field) VALUES('111-11111-1111-1111-1111-111111111111');
+INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222 ');
+-- invalid data
+INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-G111-111111111111');
+INSERT INTO guid1(guid_field) VALUES('11+11111-1111-1111-1111-111111111111');
+
+--inserting three input formats
+INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111');
+INSERT INTO guid1(guid_field) VALUES('{22222222-2222-2222-2222-222222222222}');
+INSERT INTO guid1(guid_field) VALUES('33333333333333333333333333333333');
+
+-- retrieving the inserted data
+SELECT guid_field FROM guid1;
+
+-- ordering test
+SELECT guid_field FROM guid1 ORDER BY guid_field ASC;
+SELECT guid_field FROM guid1 ORDER BY guid_field DESC;
+
+-- = operator test
+SELECT COUNT(*) FROM guid1 WHERE guid_field = '33333333-3333-3333-3333-333333333333';
+
+-- <> operator test
+SELECT COUNT(*) FROM guid1 WHERE guid_field <> '11111111111111111111111111111111';
+
+-- < operator test
+SELECT COUNT(*) FROM guid1 WHERE guid_field < '22222222-2222-2222-2222-222222222222';
+
+-- <= operator test
+SELECT COUNT(*) FROM guid1 WHERE guid_field <= '22222222-2222-2222-2222-222222222222';
+
+-- > operator test
+SELECT COUNT(*) FROM guid1 WHERE guid_field > '22222222-2222-2222-2222-222222222222';
+
+-- >= operator test
+SELECT COUNT(*) FROM guid1 WHERE guid_field >= '22222222-2222-2222-2222-222222222222';
+
+-- btree and hash index creation test
+CREATE INDEX guid1_btree ON guid1 USING BTREE (guid_field);
+CREATE INDEX guid1_hash ON guid1 USING HASH (guid_field);
+
+-- unique index test
+CREATE UNIQUE INDEX guid1_unique_BTREE ON guid1 USING BTREE (guid_field);
+-- should fail
+INSERT INTO guid1(guid_field) VALUES('11111111-1111-1111-1111-111111111111');
+
+-- check to see whether the new indexes are actually there
+SELECT count(*) FROM pg_class WHERE relkind='i' AND relname LIKE 'guid%';
+
+-- populating the test tables with additional records
+INSERT INTO guid1(guid_field) VALUES('44444444-4444-4444-4444-444444444444');
+INSERT INTO guid2(guid_field) VALUES('11111111-1111-1111-1111-111111111111');
+INSERT INTO guid2(guid_field) VALUES('{22222222-2222-2222-2222-222222222222}');
+INSERT INTO guid2(guid_field) VALUES('33333333333333333333333333333333');
+
+-- join test
+SELECT COUNT(*) FROM guid1 g1 INNER JOIN guid2 g2 ON g1.guid_field = g2.guid_field;
+SELECT COUNT(*) FROM guid1 g1 LEFT JOIN guid2 g2 ON g1.guid_field = g2.guid_field WHERE g2.guid_field IS NULL;
+
+-- clean up
+DROP TABLE guid1, guid2 CASCADE;