Folks, As commented by Peter, I have done some re-styling. Some additional tests and format checking have been added to this patch. > Put your file at the end of the OBJS variable (or in some sort of > sensible order). Done.
> > Put your file at the end of the tests (or in some sort of sensible > order). Done. > Refrain from self-evident comments, such as > > + /* > + * function handles input for the uuid datatype > + */ > + Datum uuid_in(PG_FUNCTION_ARGS) > > You can probably delete all comments in your patch by that criterion. Some changed, but not all has been removed for readability reasons. > This sort of super-verbose coding might be alright, but it gets tiring > when done systematically for no reason: > > + result = DirectFunctionCall1(textin, uuid_str); > + return result; Some changed, but not all. > The uuid.c file claims it is uuid.h. Changed. > > Move the stuff from builtins.h to uuid.h. Not changed. please see: http://archives.postgresql.org/pgsql-patches/2007-01/msg00362.php > Move the stuff from uuid.h that is not needed anywhere else to uuid.c. Done. > No // comments. Done. > > Don't number the tests. We might want to insert something later and > that would mess everything up. Done. > > Capitalize the SQL test scripts as in other files. Done. > > Remove gratuitous whitespace changes (there are many). Done. AFAICS > > Also remove the whitespace at the end of lines. Done. AFAICS > > Make some reasonable effort to align the catalog entries for > readability. > Done. Any more comments? Regards, Gevik.
############################################################### # Patch created by PostgreSQL Patch Generator 1.0 # Written by Gevik Babakhani 2007 (BSD) # # Apply this patch: # cd ./mydir.../pgsql/ # patch -p0 < this.patch.file.diff # # Date created: Fri, 26 Jan 2007 12:55:29 +0100 # # New files: # ./src/backend/utils/adt/uuid.c # ./src/include/utils/uuid.h # ./src/test/regress/expected/uuid.out # ./src/test/regress/sql/uuid.sql # Modified files: # ./src/backend/utils/adt/Makefile # ./src/include/catalog/pg_amop.h # ./src/include/catalog/pg_amproc.h # ./src/include/catalog/pg_cast.h # ./src/include/catalog/pg_opclass.h # ./src/include/catalog/pg_operator.h # ./src/include/catalog/pg_opfamily.h # ./src/include/catalog/pg_proc.h # ./src/include/catalog/pg_type.h # ./src/include/utils/builtins.h # ./src/test/regress/parallel_schedule # ./src/test/regress/serial_schedule ############################################################## *** ./src/backend/utils/adt/Makefile.orig 2007-01-24 16:35:05.000000000 +0100 --- ./src/backend/utils/adt/Makefile 2007-01-26 08:12:27.000000000 +0100 *************** *** 25,31 **** 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 like.o: like.c like_match.c --- 25,32 ---- 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 \ ! uuid.o like.o: like.c like_match.c *** ./src/backend/utils/adt/uuid.c.orig 1970-01-01 01:00:00.000000000 +0100 --- ./src/backend/utils/adt/uuid.c 2007-01-26 11:25:12.000000000 +0100 *************** *** 0 **** --- 1,298 ---- + /*------------------------------------------------------------------------- + * + * uuid.c + * Functions for the built-in type "uuid". + * + * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + *------------------------------------------------------------------------- + */ + + #include "postgres.h" + #include "access/hash.h" + #include "libpq/pqformat.h" + #include "utils/builtins.h" + #include "utils/uuid.h" + + /* Accepted GUID formats */ + + /* this one 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" + + /* these are uuid styles coresponding to above to check the actual uuid string + for format validity */ + #define UUID_CHK_FMT1 "00000000-0000-0000-0000-000000000000" + #define UUID_CHK_FMT2 "{00000000-0000-0000-0000-000000000000}" + #define UUID_CHK_FMT3 "00000000000000000000000000000000" + + /* output length */ + #define PRINT_SIZE 40 + + /* declarations */ + static void create_uuiddata_from_string(const char* source,unsigned char *data); + static bool parse_uuid_string(const char* fmt,const char* chk_fmt,const char* source,unsigned char* data); + static void create_string_form_uuid_data(const char* fmt,const char* data,char* uuid_str); + static int32 uuid_internal_cmp(uuid_t *arg1,uuid_t *arg2); + static Datum cast_text_to_uuid(text *input); + static bool is_valid_format(const char* source,const char* format); + + /* 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)); + } + + /* base function to cast varchat/text to uuid */ + Datum cast_text_to_uuid(text *input) + { + 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 varchar to uuid */ + Datum varchar_uuid(PG_FUNCTION_ARGS) + { + VarChar* input = PG_GETARG_VARCHAR_P(0); + return cast_text_to_uuid(input); + } + + /* cast text to uuid */ + Datum text_uuid(PG_FUNCTION_ARGS) + { + text* input = PG_GETARG_TEXT_P(0); + return cast_text_to_uuid(input); + } + + /* cast uuid to varchar */ + Datum uuid_varchar(PG_FUNCTION_ARGS) + { + uuid_t *uuid = PG_GETARG_UUID_P(0); + Datum uuid_str = DirectFunctionCall1(uuid_out, UUIDPGetDatum(uuid)); + + return DirectFunctionCall3(varcharin, uuid_str, + ObjectIdGetDatum(0), Int32GetDatum(-1)); + } + + /* 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,UUID_CHK_FMT1,source,data)) + { + if(!parse_uuid_string(UUID_FMT2,UUID_CHK_FMT2,source,data)) + { + if(!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))); + } + } + } + } + + /* 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]); + } + + /* check the validity of a uuid string by a given format */ + bool is_valid_format(const char *source,const char* format) + { + int a,sc,fc; + bool chr_check; + int fmtlen = strlen(format); + // check the size first + if(fmtlen != strlen(source)) + return false; + + for(a = 0; a != fmtlen; a++) + { + fc = format[a]; + sc = source[a]; + + /* false if format chr is { or - and source is not */ + if(fc != '0') + if(fc != sc) + return false; + /* check for valid char in source */ + chr_check = ( + (sc >= '0' && sc <= '9') || + (sc >= 'a' && sc <= 'f' ) || + (sc >= 'A' && sc <= 'F' ) + ); + + if(fc == '0' && !chr_check) + return false; + } + return true; + } + + /* parse the uuid string to a format and return true if okay */ + 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); + } + + /* 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)); + + return DirectFunctionCall1(textin, uuid_str); + } *** ./src/include/catalog/pg_amop.h.orig 2007-01-24 16:35:03.000000000 +0100 --- ./src/include/catalog/pg_amop.h 2007-01-26 11:37:39.000000000 +0100 *************** *** 1,3 **** --- 1,5 ---- + + /*------------------------------------------------------------------------- * * pg_amop.h *************** *** 487,492 **** --- 489,504 ---- 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,553 **** --- 560,568 ---- 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 *** ./src/include/catalog/pg_amproc.h.orig 2007-01-24 16:35:03.000000000 +0100 --- ./src/include/catalog/pg_amproc.h 2007-01-26 11:40:01.000000000 +0100 *************** *** 1,3 **** --- 1,5 ---- + + /*------------------------------------------------------------------------- * * pg_amproc.h *************** *** 127,132 **** --- 129,135 ---- 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,165 **** --- 163,169 ---- 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 */ *** ./src/include/catalog/pg_cast.h.orig 2007-01-24 16:35:03.000000000 +0100 --- ./src/include/catalog/pg_cast.h 2007-01-26 11:45:57.000000000 +0100 *************** *** 397,400 **** --- 397,406 ---- 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 )); + DATA(insert (1043 2950 2966 a )); + DATA(insert (2950 1043 2967 a )); + #endif /* PG_CAST_H */ *** ./src/include/catalog/pg_opclass.h.orig 2007-01-24 16:35:03.000000000 +0100 --- ./src/include/catalog/pg_opclass.h 2007-01-26 12:36:26.000000000 +0100 *************** *** 1,3 **** --- 1,5 ---- + + /*------------------------------------------------------------------------- * * pg_opclass.h *************** *** 200,204 **** --- 202,208 ---- 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 */ *** ./src/include/catalog/pg_operator.h.orig 2007-01-24 16:35:03.000000000 +0100 --- ./src/include/catalog/pg_operator.h 2007-01-26 12:39:03.000000000 +0100 *************** *** 1,3 **** --- 1,5 ---- + + /*------------------------------------------------------------------------- * * pg_operator.h *************** *** 895,900 **** --- 897,910 ---- 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 *** ./src/include/catalog/pg_opfamily.h.orig 2007-01-24 16:35:03.000000000 +0100 --- ./src/include/catalog/pg_opfamily.h 2007-01-26 12:40:39.000000000 +0100 *************** *** 1,3 **** --- 1,5 ---- + + /*------------------------------------------------------------------------- * * pg_opfamily.h *************** *** 134,138 **** --- 136,143 ---- 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 */ *** ./src/include/catalog/pg_proc.h.orig 2007-01-24 16:35:03.000000000 +0100 --- ./src/include/catalog/pg_proc.h 2007-01-26 12:43:42.000000000 +0100 *************** *** 1,3 **** --- 1,5 ---- + + /*------------------------------------------------------------------------- * * pg_proc.h *************** *** 4046,4051 **** --- 4048,4086 ---- 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"); + DATA(insert OID = 2966 ( uuid PGNSP PGUID 12 1 0 f f t f i 1 2950 "1043" _null_ _null_ _null_ varchar_uuid - _null_ )); + DESCR("convert varchar to uuid"); + DATA(insert OID = 2967 ( varchar PGNSP PGUID 12 1 0 f f t f i 1 1043 "2950" _null_ _null_ _null_ uuid_varchar - _null_ )); + DESCR("convert uuid to varchar"); /* * Symbolic values for provolatile column: these indicate whether the result *** ./src/include/catalog/pg_type.h.orig 2007-01-24 16:35:03.000000000 +0100 --- ./src/include/catalog/pg_type.h 2007-01-26 12:44:30.000000000 +0100 *************** *** 1,3 **** --- 1,5 ---- + + /*------------------------------------------------------------------------- * * pg_type.h *************** *** 561,566 **** --- 563,573 ---- 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/GUID 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 */ *** ./src/include/utils/builtins.h.orig 2007-01-24 16:35:03.000000000 +0100 --- ./src/include/utils/builtins.h 2007-01-24 16:43:26.000000000 +0100 *************** *** 926,929 **** --- 926,947 ---- /* 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); + extern Datum varchar_uuid(PG_FUNCTION_ARGS); + extern Datum uuid_varchar(PG_FUNCTION_ARGS); + #endif /* BUILTINS_H */ *** ./src/include/utils/uuid.h.orig 1970-01-01 01:00:00.000000000 +0100 --- ./src/include/utils/uuid.h 2007-01-26 08:46:45.000000000 +0100 *************** *** 0 **** --- 1,27 ---- + /*------------------------------------------------------------------------- + * + * uuid.h + * Header file for the SQL datatypes UUID. + * + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group + * + *------------------------------------------------------------------------- + */ + #ifndef UUID_H + #define UUID_H + + /* guid size in bytes */ + #define UUID_LEN 16 + + /* uuid type structure */ + typedef struct uuid_t { + char data[UUID_LEN]; + } 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 */ *** ./src/test/regress/expected/uuid.out.orig 1970-01-01 01:00:00.000000000 +0100 --- ./src/test/regress/expected/uuid.out 2007-01-26 11:15:05.000000000 +0100 *************** *** 0 **** --- 1,157 ---- + -- 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'); + -- retriving 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) + + -- = opertator test + SELECT COUNT(*) FROM guid1 WHERE guid_field = '33333333-3333-3333-3333-333333333333'; + count + ------- + 1 + (1 row) + + -- <> opertator 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); + -- 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) + + -- insert 32768 random records + TRUNCATE TABLE guid1; + INSERT INTO guid1(guid_field) VALUES(md5(now())); + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + SELECT COUNT(*) FROM guid1; + count + ------- + 32768 + (1 row) + + -- clean up + DROP TABLE guid1,guid2 cascade; *** ./src/test/regress/parallel_schedule.orig 2007-01-24 16:35:06.000000000 +0100 --- ./src/test/regress/parallel_schedule 2007-01-26 08:13:55.000000000 +0100 *************** *** 2,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 $ # ---------- ! 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.37 2007/01/20 17:15:43 neilc Exp $ # ---------- ! 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 *** ./src/test/regress/serial_schedule.orig 2007-01-24 16:35:06.000000000 +0100 --- ./src/test/regress/serial_schedule 2007-01-26 08:14:57.000000000 +0100 *************** *** 106,108 **** --- 106,109 ---- test: xml test: stats test: tablespace + test: uuid *** ./src/test/regress/sql/uuid.sql.orig 1970-01-01 01:00:00.000000000 +0100 --- ./src/test/regress/sql/uuid.sql 2007-01-26 11:14:23.000000000 +0100 *************** *** 0 **** --- 1,97 ---- + -- 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'); + + -- retriving 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; + + -- = opertator test + SELECT COUNT(*) FROM guid1 WHERE guid_field = '33333333-3333-3333-3333-333333333333'; + + -- <> opertator 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); + + -- 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; + + -- insert 32768 random records + TRUNCATE TABLE guid1; + INSERT INTO guid1(guid_field) VALUES(md5(now())); + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + INSERT INTO guid1(guid_field) SELECT md5(now() || random() || (SELECT COUNT(*) FROM guid1)) FROM guid1; + + SELECT COUNT(*) FROM guid1; + + -- clean up + DROP TABLE guid1,guid2 cascade;
---------------------------(end of broadcast)--------------------------- TIP 1: if posting/reading through Usenet, please send an appropriate subscribe-nomail command to [EMAIL PROTECTED] so that your message can get through to the mailing list cleanly