Hi, While ago (sep-2006) I sent a patch for the UUID datatype, Did anyone have time to review it yet?
Here it is again :) Regards, Gevik
*** ./backend/utils/adt/Makefile.orig 2006-09-19 12:05:41.000000000 +0200 --- ./backend/utils/adt/Makefile 2006-09-19 12:06:47.000000000 +0200 *************** *** 15,21 **** endif endif ! OBJS = acl.o arrayfuncs.o array_userfuncs.o arrayutils.o bool.o \ cash.o char.o date.o datetime.o datum.o domains.o \ float.o format_type.o \ geo_ops.o geo_selfuncs.o int.o int8.o like.o lockfuncs.o \ --- 15,21 ---- endif endif ! OBJS = uuid.o acl.o arrayfuncs.o array_userfuncs.o arrayutils.o bool.o \ cash.o char.o date.o datetime.o datum.o domains.o \ float.o format_type.o \ geo_ops.o geo_selfuncs.o int.o int8.o like.o lockfuncs.o \ *** ./include/catalog/pg_amop.h.orig 2006-09-19 12:05:39.000000000 +0200 --- ./include/catalog/pg_amop.h 2006-09-19 12:06:47.000000000 +0200 *************** *** 594,599 **** --- 594,601 ---- DATA(insert ( 2232 0 1 f 2334 )); /* aclitem_ops */ DATA(insert ( 2235 0 1 f 974 )); + /* uuid */ + DATA(insert ( 2868 0 1 f 2866 )); /* * gist box_ops *************** *** 886,889 **** --- 888,898 ---- DATA(insert ( 2780 0 3 t 2752 )); DATA(insert ( 2780 0 4 t 1070 )); + /* btree uuid */ + DATA(insert ( 2873 0 1 f 2869 )); + DATA(insert ( 2873 0 2 f 2871 )); + DATA(insert ( 2873 0 3 f 2866 )); + DATA(insert ( 2873 0 4 f 2872)); + DATA(insert ( 2873 0 5 f 2870 )); + #endif /* PG_AMOP_H */ *** ./include/catalog/pg_amproc.h.orig 2006-09-19 12:05:39.000000000 +0200 --- ./include/catalog/pg_amproc.h 2006-09-19 12:06:47.000000000 +0200 *************** *** 125,130 **** --- 125,132 ---- DATA(insert ( 2233 0 1 380 )); DATA(insert ( 2234 0 1 381 )); DATA(insert ( 2789 0 1 2794 )); + /*uuid*/ + DATA(insert ( 2873 0 1 2863 )); /* hash */ *************** *** 161,166 **** --- 163,171 ---- DATA(insert ( 2231 0 1 456 )); DATA(insert ( 2232 0 1 455 )); DATA(insert ( 2235 0 1 329 )); + /* uuid */ + DATA(insert ( 2868 0 1 2874 )); + /* gist */ *** ./include/catalog/pg_cast.h.orig 2006-09-19 12:05:39.000000000 +0200 --- ./include/catalog/pg_cast.h 2006-09-19 12:06:47.000000000 +0200 *************** *** 196,201 **** --- 196,206 ---- /* Cross-category casts between int4 and "char" */ DATA(insert ( 18 23 77 e )); DATA(insert ( 23 18 78 e )); + /* uuid */ + DATA(insert ( 25 2854 2876 a )); + DATA(insert ( 2854 25 2877 a )); + DATA(insert ( 1043 2854 2878 a )); + DATA(insert ( 2854 1043 2879 a )); /* * Datetime category *** ./include/catalog/pg_opclass.h.orig 2006-09-19 12:05:39.000000000 +0200 --- ./include/catalog/pg_opclass.h 2006-09-19 12:06:47.000000000 +0200 *************** *** 208,211 **** --- 208,216 ---- DATA(insert OID = 2779 ( 2742 _reltime_ops PGNSP PGUID 1024 t 703 )); DATA(insert OID = 2780 ( 2742 _tinterval_ops PGNSP PGUID 1025 t 704 )); + /* uuid */ + DATA(insert OID = 2873 ( 403 uuid_ops PGNSP PGUID 2854 t 0 )); + DATA(insert OID = 2868 ( 405 uuid_ops PGNSP PGUID 2854 t 0 )); + + #endif /* PG_OPCLASS_H */ *** ./include/catalog/pg_operator.h.orig 2006-09-19 12:05:39.000000000 +0200 --- ./include/catalog/pg_operator.h 2006-09-19 12:06:47.000000000 +0200 *************** *** 883,888 **** --- 883,898 ---- DATA(insert OID = 2751 ( "@" PGNSP PGUID b f 2277 2277 16 2752 0 0 0 0 0 arraycontains contsel contjoinsel )); DATA(insert OID = 2752 ( "~" PGNSP PGUID b f 2277 2277 16 2751 0 0 0 0 0 arraycontained contsel contjoinsel )); + /* uuid operators */ + + DATA(insert OID = 2866 ( "=" PGNSP PGUID b t 2854 2854 16 2866 2867 2869 2869 2869 2870 uuid_eq eqsel eqjoinsel )); + DATA(insert OID = 2867 ( "<>" PGNSP PGUID b f 2854 2854 16 2867 2866 0 0 0 0 uuid_ne neqsel neqjoinsel )); + DATA(insert OID = 2869 ( "<" PGNSP PGUID b f 2854 2854 16 2870 2872 0 0 0 0 uuid_lt scalarltsel scalarltjoinsel )); + DATA(insert OID = 2870 ( ">" PGNSP PGUID b f 2854 2854 16 2869 2871 0 0 0 0 uuid_gt scalargtsel scalargtjoinsel )); + DATA(insert OID = 2871 ( "<=" PGNSP PGUID b f 2854 2854 16 2872 2870 0 0 0 0 uuid_le scalarltsel scalarltjoinsel )); + DATA(insert OID = 2872 ( ">=" PGNSP PGUID b f 2854 2854 16 2871 2869 0 0 0 0 uuid_ge scalargtsel scalargtjoinsel )); + + /* * function prototypes *** ./include/catalog/pg_proc.h.orig 2006-09-19 12:05:39.000000000 +0200 --- ./include/catalog/pg_proc.h 2006-09-19 12:37:38.000000000 +0200 *************** *** 3940,3945 **** --- 3940,3980 ---- DATA(insert OID = 2749 ( arraycontained PGNSP PGUID 12 f f t f i 2 16 "2277 2277" _null_ _null_ _null_ arraycontained - _null_ )); DESCR("anyarray contained"); + /* uuid */ + DATA(insert OID = 2855 ( uuid_in PGNSP PGUID 12 f f t f i 1 2854 "2275" _null_ _null_ _null_ uuid_in - _null_ )); + DESCR("I/O"); + DATA(insert OID = 2856 ( uuid_out PGNSP PGUID 12 f f t f i 1 2275 "2854" _null_ _null_ _null_ uuid_out - _null_ )); + DESCR("I/O"); + DATA(insert OID = 2857 ( uuid_lt PGNSP PGUID 12 f f t f i 2 16 "2854 2854" _null_ _null_ _null_ uuid_lt - _null_ )); + DESCR("less-than"); + DATA(insert OID = 2858 ( uuid_le PGNSP PGUID 12 f f t f i 2 16 "2854 2854" _null_ _null_ _null_ uuid_le - _null_ )); + DESCR("less-than-or-equel"); + DATA(insert OID = 2859 ( uuid_eq PGNSP PGUID 12 f f t f i 2 16 "2854 2854" _null_ _null_ _null_ uuid_eq - _null_ )); + DESCR("equal"); + DATA(insert OID = 2860 ( uuid_ge PGNSP PGUID 12 f f t f i 2 16 "2854 2854" _null_ _null_ _null_ uuid_ge - _null_ )); + DESCR("greater-than-or-equal"); + DATA(insert OID = 2861 ( uuid_gt PGNSP PGUID 12 f f t f i 2 16 "2854 2854" _null_ _null_ _null_ uuid_gt - _null_ )); + DESCR("greater-than"); + DATA(insert OID = 2862 ( uuid_ne PGNSP PGUID 12 f f t f i 2 16 "2854 2854" _null_ _null_ _null_ uuid_ne - _null_ )); + DESCR("not-equal"); + DATA(insert OID = 2863 ( uuid_cmp PGNSP PGUID 12 f f t f i 2 23 "2854 2854" _null_ _null_ _null_ uuid_cmp - _null_ )); + DESCR("btree less-equal-greater"); + DATA(insert OID = 2864 ( uuid_recv PGNSP PGUID 12 f f t f i 1 2854 "2281" _null_ _null_ _null_ uuid_recv - _null_ )); + DESCR("I/O"); + DATA(insert OID = 2865 ( uuid_send PGNSP PGUID 12 f f t f i 1 17 "2854" _null_ _null_ _null_ uuid_send - _null_ )); + DESCR("I/O"); + DATA(insert OID = 2874 ( uuid_hash PGNSP PGUID 12 f f t f i 1 23 "2854" _null_ _null_ _null_ uuid_hash - _null_ )); + DESCR("hash"); + DATA(insert OID = 2876 ( uuid PGNSP PGUID 12 f f t f i 1 2854 "25" _null_ _null_ _null_ text_uuid - _null_ )); + DESCR("convert text to uuid"); + DATA(insert OID = 2877 ( text PGNSP PGUID 12 f f t f i 1 25 "2854" _null_ _null_ _null_ uuid_text - _null_ )); + DESCR("convert uuid to text"); + DATA(insert OID = 2878 ( uuid PGNSP PGUID 12 f f t f i 1 2854 "1043" _null_ _null_ _null_ varchar_uuid - _null_ )); + DESCR("convert varchar to uuid"); + DATA(insert OID = 2879 ( varchar PGNSP PGUID 12 f f t f i 1 1043 "2854" _null_ _null_ _null_ uuid_varchar - _null_ )); + DESCR("convert uuid to varchar"); + + /* * Symbolic values for provolatile column: these indicate whether the result * of a function is dependent *only* on the values of its explicit arguments, *** ./include/catalog/pg_type.h.orig 2006-09-19 12:05:39.000000000 +0200 --- ./include/catalog/pg_type.h 2006-09-19 12:06:47.000000000 +0200 *************** *** 548,553 **** --- 548,561 ---- 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 type */ + DATA(insert OID = 2854 ( 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/GUID datatype"); + #define UUIDOID 2854 + DATA(insert OID = 2875 ( _uuid PGNSP PGUID -1 f b t \054 0 2854 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ )); + + + /* * prototypes for functions in pg_type.c */ *** ./include/utils/builtins.h.orig 2006-09-19 12:05:39.000000000 +0200 --- ./include/utils/builtins.h 2006-09-19 12:06:47.000000000 +0200 *************** *** 21,26 **** --- 21,47 ---- * Defined in adt/ */ + /* 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); + extern Datum varchar_uuid(PG_FUNCTION_ARGS); + extern Datum uuid_varchar(PG_FUNCTION_ARGS); + extern Datum uuid_new_guid(PG_FUNCTION_ARGS); + + + /* acl.c */ extern Datum has_table_privilege_name_name(PG_FUNCTION_ARGS); extern Datum has_table_privilege_name_id(PG_FUNCTION_ARGS); *** ./test/regress/parallel_schedule.orig 2006-09-19 13:17:21.000000000 +0200 --- ./test/regress/parallel_schedule 2006-09-19 13:18:35.000000000 +0200 *************** *** 2,8 **** # The first group of parallel test # $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.35 2006/08/30 23:34:22 tgl Exp $ # ---------- ! test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric # Depends on things setup during char, varchar and text test: strings --- 2,8 ---- # The first group of parallel test # $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.35 2006/08/30 23:34:22 tgl Exp $ # ---------- ! test: uuid boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric # Depends on things setup during char, varchar and text test: strings *** ./test/regress/serial_schedule.orig 2006-09-19 13:17:11.000000000 +0200 --- ./test/regress/serial_schedule 2006-09-19 13:17:50.000000000 +0200 *************** *** 1,5 **** --- 1,6 ---- # $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.33 2006/08/30 23:34:22 tgl Exp $ # This should probably be in an order similar to parallel_schedule. + test: uuid test: boolean test: char test: name *** ./test/regress/sql/uuid.sql.orig 1970-01-01 01:00:00.000000000 +0100 --- ./test/regress/sql/uuid.sql 2006-09-19 13:34:51.000000000 +0200 *************** *** 0 **** --- 1,67 ---- + --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()) + ); + + -- test 1: inserting by 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'); + + -- test 2: retriving the inserted datat + select guid_field from guid1; + + -- test 3: ordering test + select guid_field from guid1 order by guid_field asc; + select guid_field from guid1 order by guid_field desc; + + -- test 4: = opertator test + select count(*) from guid1 where guid_field = '33333333-3333-3333-3333-333333333333'; + + -- test 5: <> opertator test + select count(*) from guid1 where guid_field <> '11111111111111111111111111111111'; + + -- test 6: < operator test + select count(*) from guid1 where guid_field < '22222222-2222-2222-2222-222222222222'; + + -- test 7: <= operator test + select count(*) from guid1 where guid_field <= '22222222-2222-2222-2222-222222222222'; + + -- test 8: > operator test + select count(*) from guid1 where guid_field > '22222222-2222-2222-2222-222222222222'; + + -- test 9 => 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); + + + -- 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; *** ./test/regress/expected/uuid.out.orig 1970-01-01 01:00:00.000000000 +0100 --- ./test/regress/expected/uuid.out 2006-09-19 13:38:25.000000000 +0200 *************** *** 0 **** --- 1,122 ---- + --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()) + ); + + -- test 1: inserting by 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'); + -- test 2: retriving the inserted datat + select guid_field from guid1; + guid_field + -------------------------------------- + 11111111-1111-1111-1111-111111111111 + 22222222-2222-2222-2222-222222222222 + 33333333-3333-3333-3333-333333333333 + (3 rows) + + + -- test 3: 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) + + + -- test 4: = opertator test + select count(*) from guid1 where guid_field = '33333333-3333-3333-3333-333333333333'; + count + ------- + 1 + (1 row) + + + -- test 5: <> opertator test + select count(*) from guid1 where guid_field <> '11111111111111111111111111111111'; + count + ------- + 2 + (1 row) + + + -- test 6: < operator test + select count(*) from guid1 where guid_field < '22222222-2222-2222-2222-222222222222'; + count + ------- + 1 + (1 row) + + + -- test 7: <= operator test + select count(*) from guid1 where guid_field <= '22222222-2222-2222-2222-222222222222'; + count + ------- + 2 + (1 row) + + + -- test 8: > operator test + select count(*) from guid1 where guid_field > '22222222-2222-2222-2222-222222222222'; + count + ------- + 1 + (1 row) + + -- test 9 => 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); + + -- 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; *** ./backend/utils/adt/uuid.c.orig 1970-01-01 01:00:00.000000000 +0100 --- ./backend/utils/adt/uuid.c 2006-09-19 12:36:43.000000000 +0200 *************** *** 0 **** --- 1,267 ---- + /*------------------------------------------------------------------------- + * + * uuid.h + * Header file for the SQL datatypes UUID. + * + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group + * + *------------------------------------------------------------------------- + */ + + #include "postgres.h" + #include "access/hash.h" + #include "libpq/pqformat.h" + #include "utils/builtins.h" + #include "utils/uuid.h" + + /* + * function handles input for the uuid datatype + */ + Datum uuid_in(PG_FUNCTION_ARGS) + { + uuid_t *uuid; + uint8 data[UUID_LEN]; + + char *uuid_str = PG_GETARG_CSTRING(0); + + create_uuiddata_from_string(uuid_str,data); + + uuid = (uuid_t *) palloc(sizeof(uuid_t)); + memcpy(uuid->data,data,UUID_LEN); + + PG_RETURN_UUID_P(uuid); + } + + /* + * function handles output for the uuid datatype + */ + Datum uuid_out(PG_FUNCTION_ARGS) + { + uuid_t *uuid = (uuid_t *) PG_GETARG_POINTER(0); + + char *uuid_str; + + uuid_str = (char *)palloc(PRINT_SIZE); + create_string_form_uuid_data(UUID_FMT1,uuid->data,uuid_str); + + PG_RETURN_CSTRING(uuid_str); + } + + /* uuid binary receive handler */ + Datum uuid_recv(PG_FUNCTION_ARGS) + { + uuid_t *uuid; + StringInfo buffer = (StringInfo) PG_GETARG_POINTER(0); + + uuid = (uuid_t *)palloc(UUID_LEN); + memcpy(uuid->data,pq_getmsgbytes(buffer,UUID_LEN),UUID_LEN); + PG_RETURN_POINTER(uuid); + } + + /* uuid binary send handler */ + 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)); + } + + /* handler for < operator */ + Datum uuid_lt(PG_FUNCTION_ARGS) + { + bool result; + uuid_t *arg1 = PG_GETARG_UUID_P(0); + uuid_t *arg2 = PG_GETARG_UUID_P(1); + + result = uuid_internal_cmp(arg1,arg2) < 0; + + PG_RETURN_BOOL(result); + } + + /* handler for <= operator */ + Datum uuid_le(PG_FUNCTION_ARGS) + { + bool result; + uuid_t *arg1 = PG_GETARG_UUID_P(0); + uuid_t *arg2 = PG_GETARG_UUID_P(1); + + result = uuid_internal_cmp(arg1,arg2) <= 0; + + PG_RETURN_BOOL(result); + } + + + /* handler for = operator */ + Datum uuid_eq(PG_FUNCTION_ARGS) + { + bool result; + uuid_t *arg1 = PG_GETARG_UUID_P(0); + uuid_t *arg2 = PG_GETARG_UUID_P(1); + + result = uuid_internal_cmp(arg1,arg2) == 0; + + PG_RETURN_BOOL(result); + } + + /* handler for >= operator */ + Datum uuid_ge(PG_FUNCTION_ARGS) + { + bool result; + uuid_t *arg1 = PG_GETARG_UUID_P(0); + uuid_t *arg2 = PG_GETARG_UUID_P(1); + + result = uuid_internal_cmp(arg1,arg2) >= 0; + + PG_RETURN_BOOL(result); + } + + /* handler for > operator */ + Datum uuid_gt(PG_FUNCTION_ARGS) + { + bool result; + uuid_t *arg1 = PG_GETARG_UUID_P(0); + uuid_t *arg2 = PG_GETARG_UUID_P(1); + + result = uuid_internal_cmp(arg1,arg2) > 0; + + PG_RETURN_BOOL(result); + } + + + /* handler for <> operator */ + Datum uuid_ne(PG_FUNCTION_ARGS) + { + bool result; + uuid_t *arg1 = PG_GETARG_UUID_P(0); + uuid_t *arg2 = PG_GETARG_UUID_P(1); + + result = uuid_internal_cmp(arg1,arg2) != 0; + + PG_RETURN_BOOL(result); + } + + /* handler for btree index operator */ + Datum uuid_cmp(PG_FUNCTION_ARGS) + { + int32 result; + + uuid_t *arg1 = PG_GETARG_UUID_P(0); + uuid_t *arg2 = PG_GETARG_UUID_P(1); + + result = uuid_internal_cmp(arg1,arg2); + PG_RETURN_INT32(result); + } + + /* 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 varchar to uuid */ + Datum varchar_uuid(PG_FUNCTION_ARGS) + { + VarChar* input = PG_GETARG_VARCHAR_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); + return result; + } + + /* cast uuid to varchar */ + Datum uuid_varchar(PG_FUNCTION_ARGS) + { + uuid_t *uuid = PG_GETARG_UUID_P(0); + Datum result; + Datum uuid_str = DirectFunctionCall1(uuid_out, UUIDPGetDatum(uuid)); + + result = DirectFunctionCall3(varcharin, uuid_str, + ObjectIdGetDatum(0), Int32GetDatum(-1)); + return result; + } + + /* internal uuid compare function */ + int32 uuid_internal_cmp(uuid_t *arg1,uuid_t *arg2) + { + return memcmp(arg1->data,arg2->data,UUID_LEN); + } + + /* string to uuid convertor by various format types*/ + void create_uuiddata_from_string(const char* source,unsigned char *data) + { + if(!parse_uuid_string(UUID_FMT1,source,data)) + { + if(!parse_uuid_string(UUID_FMT2,source,data)) + { + if(!parse_uuid_string(UUID_FMT3,source,data)) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for uuid: \"%s\"", + source))); + } + } + } + } + + /* create a string representation of the uuid */ + void create_string_form_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]); + } + + /* parse the uuid string to a format and return true if okay */ + bool parse_uuid_string(const char* 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; + } + + + /* 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); + return result; + } + + /* cast uuid to text */ + Datum uuid_text(PG_FUNCTION_ARGS) + { + uuid_t *uuid = PG_GETARG_UUID_P(0); + Datum result; + Datum uuid_str = DirectFunctionCall1(uuid_out, UUIDPGetDatum(uuid)); + + result = DirectFunctionCall1(textin, uuid_str); + return result; + } *** ./include/utils/uuid.h.orig 1970-01-01 01:00:00.000000000 +0100 --- ./include/utils/uuid.h 2006-09-19 12:38:20.000000000 +0200 *************** *** 0 **** --- 1,61 ---- + /*------------------------------------------------------------------------- + * + * uuid.h + * Header file for the SQL datatypes UUID. + * + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group + * + *------------------------------------------------------------------------- + */ + #ifndef UUID_H + #define UUID_H + + /* Accepted GUID formats */ + + #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}" + // also the default output type + #define UUID_FMT3 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" + + /* The guid size */ + #define UUID_LEN 16 + /* output length */ + #define PRINT_SIZE 40 + + /* 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)) + + /* uuid type structure */ + + typedef struct uuid_t { + char data[UUID_LEN]; + } uuid_t; + + + void create_uuiddata_from_string(const char* source,unsigned char *data); + bool parse_uuid_string(const char* fmt,const char* source,unsigned char* data); + void create_string_form_uuid_data(const char* fmt,const char *data,char *uuid_str); + int32 uuid_internal_cmp(uuid_t *arg1,uuid_t *arg2); + + 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); + extern Datum varchar_uuid(PG_FUNCTION_ARGS); + extern Datum uuid_varchar(PG_FUNCTION_ARGS); + + #endif /* UUID_H */
---------------------------(end of broadcast)--------------------------- TIP 7: You can help support the PostgreSQL project by donating at http://www.postgresql.org/about/donate