Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a534068

Browse files
author
Neil Conway
committed
Add a new builtin type, "uuid". This implements a UUID type, similar to
that defined in RFC 4122. This patch includes the basic implementation, plus regression tests. Documentation and perhaps some additional functionality will come later. Catversion bumped. Patch from Gevik Babakhani; review from Peter, Tom, and myself.
1 parent a8e0b66 commit a534068

File tree

17 files changed

+621
-16
lines changed

17 files changed

+621
-16
lines changed

src/backend/utils/adt/Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#
22
# Makefile for utils/adt
33
#
4-
# $PostgreSQL: pgsql/src/backend/utils/adt/Makefile,v 1.62 2007/01/20 17:16:13 petere Exp $
4+
# $PostgreSQL: pgsql/src/backend/utils/adt/Makefile,v 1.63 2007/01/28 16:16:52 neilc Exp $
55
#
66

77
subdir = src/backend/utils/adt
@@ -25,7 +25,8 @@ OBJS = acl.o arrayfuncs.o array_userfuncs.o arrayutils.o bool.o \
2525
tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \
2626
network.o mac.o inet_net_ntop.o inet_net_pton.o \
2727
ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \
28-
ascii.o quote.o pgstatfuncs.o encode.o dbsize.o genfile.o xml.o
28+
ascii.o quote.o pgstatfuncs.o encode.o dbsize.o genfile.o xml.o \
29+
uuid.o
2930

3031
like.o: like.c like_match.c
3132

src/backend/utils/adt/uuid.c

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* uuid.c
4+
* Functions for the built-in type "uuid".
5+
*
6+
* Copyright (c) 2007, PostgreSQL Global Development Group
7+
*
8+
* IDENTIFICATION
9+
* $PostgreSQL: pgsql/src/backend/utils/adt/uuid.c,v 1.1 2007/01/28 16:16:52 neilc Exp $
10+
*
11+
*-------------------------------------------------------------------------
12+
*/
13+
14+
#include "postgres.h"
15+
16+
#include "access/hash.h"
17+
#include "libpq/pqformat.h"
18+
#include "utils/builtins.h"
19+
#include "utils/uuid.h"
20+
21+
/* Accepted GUID formats */
22+
23+
/* UUID_FMT1 is the default output format */
24+
#define UUID_FMT1 "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
25+
#define UUID_FMT2 "{%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx}"
26+
#define UUID_FMT3 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
27+
28+
/* UUIDs are accepted in any of the following textual input formats. */
29+
#define UUID_CHK_FMT1 "00000000-0000-0000-0000-000000000000"
30+
#define UUID_CHK_FMT2 "{00000000-0000-0000-0000-000000000000}"
31+
#define UUID_CHK_FMT3 "00000000000000000000000000000000"
32+
33+
#define PRINT_SIZE 40
34+
35+
/* uuid size in bytes */
36+
#define UUID_LEN 16
37+
38+
/* The uuid_t type is declared as struct uuid_t in uuid.h */
39+
struct uuid_t
40+
{
41+
char data[UUID_LEN];
42+
};
43+
44+
static void uuid_data_from_string(const char *source, unsigned char *data);
45+
static void string_from_uuid_data(const char *fmt, const char *data, char *uuid_str);
46+
static bool parse_uuid_string(const char *fmt, const char *chk_fmt,
47+
const char *source, unsigned char *data);
48+
static bool is_valid_format(const char *source, const char *fmt);
49+
static int32 uuid_internal_cmp(uuid_t *arg1, uuid_t *arg2);
50+
51+
Datum
52+
uuid_in(PG_FUNCTION_ARGS)
53+
{
54+
char *uuid_str = PG_GETARG_CSTRING(0);
55+
uuid_t *uuid;
56+
uint8 data[UUID_LEN];
57+
58+
uuid_data_from_string(uuid_str, data);
59+
uuid = (uuid_t *) palloc(sizeof(uuid_t));
60+
memcpy(uuid->data, data, UUID_LEN);
61+
PG_RETURN_UUID_P(uuid);
62+
}
63+
64+
Datum
65+
uuid_out(PG_FUNCTION_ARGS)
66+
{
67+
uuid_t *uuid = (uuid_t *) PG_GETARG_POINTER(0);
68+
char *uuid_str;
69+
70+
uuid_str = (char *) palloc(PRINT_SIZE);
71+
string_from_uuid_data(UUID_FMT1, uuid->data, uuid_str);
72+
PG_RETURN_CSTRING(uuid_str);
73+
}
74+
75+
/* string to uuid convertor by various format types */
76+
static void
77+
uuid_data_from_string(const char *source, unsigned char *data)
78+
{
79+
if (!parse_uuid_string(UUID_FMT1, UUID_CHK_FMT1, source, data) &&
80+
!parse_uuid_string(UUID_FMT2, UUID_CHK_FMT2, source, data) &&
81+
!parse_uuid_string(UUID_FMT3, UUID_CHK_FMT3, source, data))
82+
{
83+
ereport(ERROR,
84+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
85+
errmsg("invalid input syntax for uuid: \"%s\"",
86+
source)));
87+
}
88+
}
89+
90+
/* check the validity of a uuid string by a given format */
91+
static bool
92+
is_valid_format(const char *source, const char *fmt)
93+
{
94+
int i;
95+
int fmtlen = strlen(fmt);
96+
97+
/* check length first */
98+
if (fmtlen != strlen(source))
99+
return false;
100+
101+
for (i = 0; i < fmtlen; i++)
102+
{
103+
int fc;
104+
int sc;
105+
bool valid_chr;
106+
107+
fc = fmt[i];
108+
sc = source[i];
109+
110+
/* false if format chr is { or - and source is not */
111+
if (fc != '0' && fc != sc)
112+
return false;
113+
114+
/* check for valid char in source */
115+
valid_chr = (sc >= '0' && sc <= '9') ||
116+
(sc >= 'a' && sc <= 'f' ) ||
117+
(sc >= 'A' && sc <= 'F' );
118+
119+
if (fc == '0' && !valid_chr)
120+
return false;
121+
}
122+
123+
return true;
124+
}
125+
126+
/* parse the uuid string to a format and return true if okay */
127+
static bool
128+
parse_uuid_string(const char *fmt, const char *chk_fmt,
129+
const char *source, unsigned char *data)
130+
{
131+
int result = sscanf(source, fmt,
132+
&data[0], &data[1], &data[2], &data[3], &data[4],
133+
&data[5], &data[6], &data[7], &data[8], &data[9],
134+
&data[10], &data[11], &data[12], &data[13],
135+
&data[14], &data[15]);
136+
137+
return (result == 16) && is_valid_format(source, chk_fmt);
138+
}
139+
140+
/* create a string representation of the uuid */
141+
static void
142+
string_from_uuid_data(const char *fmt, const char *data, char *uuid_str)
143+
{
144+
snprintf(uuid_str, PRINT_SIZE, fmt,
145+
data[0], data[1], data[2], data[3], data[4],
146+
data[5], data[6], data[7], data[8], data[9],
147+
data[10], data[11], data[12], data[13],
148+
data[14], data[15]);
149+
}
150+
151+
Datum
152+
uuid_recv(PG_FUNCTION_ARGS)
153+
{
154+
StringInfo buffer = (StringInfo) PG_GETARG_POINTER(0);
155+
uuid_t *uuid;
156+
157+
uuid = (uuid_t *) palloc(UUID_LEN);
158+
memcpy(uuid->data, pq_getmsgbytes(buffer, UUID_LEN), UUID_LEN);
159+
PG_RETURN_POINTER(uuid);
160+
}
161+
162+
Datum
163+
uuid_send(PG_FUNCTION_ARGS)
164+
{
165+
uuid_t *uuid = PG_GETARG_UUID_P(0);
166+
StringInfoData buffer;
167+
168+
pq_begintypsend(&buffer);
169+
pq_sendbytes(&buffer, uuid->data, UUID_LEN);
170+
PG_RETURN_BYTEA_P(pq_endtypsend(&buffer));
171+
}
172+
173+
/* internal uuid compare function */
174+
static int32
175+
uuid_internal_cmp(uuid_t *arg1, uuid_t *arg2)
176+
{
177+
return memcmp(arg1->data, arg2->data, UUID_LEN);
178+
}
179+
180+
Datum
181+
uuid_lt(PG_FUNCTION_ARGS)
182+
{
183+
uuid_t *arg1 = PG_GETARG_UUID_P(0);
184+
uuid_t *arg2 = PG_GETARG_UUID_P(1);
185+
186+
PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) < 0);
187+
}
188+
189+
Datum
190+
uuid_le(PG_FUNCTION_ARGS)
191+
{
192+
uuid_t *arg1 = PG_GETARG_UUID_P(0);
193+
uuid_t *arg2 = PG_GETARG_UUID_P(1);
194+
195+
PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) <= 0);
196+
}
197+
198+
Datum
199+
uuid_eq(PG_FUNCTION_ARGS)
200+
{
201+
uuid_t *arg1 = PG_GETARG_UUID_P(0);
202+
uuid_t *arg2 = PG_GETARG_UUID_P(1);
203+
204+
PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) == 0);
205+
}
206+
207+
Datum
208+
uuid_ge(PG_FUNCTION_ARGS)
209+
{
210+
uuid_t *arg1 = PG_GETARG_UUID_P(0);
211+
uuid_t *arg2 = PG_GETARG_UUID_P(1);
212+
213+
PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) >= 0);
214+
}
215+
216+
Datum
217+
uuid_gt(PG_FUNCTION_ARGS)
218+
{
219+
uuid_t *arg1 = PG_GETARG_UUID_P(0);
220+
uuid_t *arg2 = PG_GETARG_UUID_P(1);
221+
222+
PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) > 0);
223+
}
224+
225+
Datum
226+
uuid_ne(PG_FUNCTION_ARGS)
227+
{
228+
uuid_t *arg1 = PG_GETARG_UUID_P(0);
229+
uuid_t *arg2 = PG_GETARG_UUID_P(1);
230+
231+
PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) != 0);
232+
}
233+
234+
/* handler for btree index operator */
235+
Datum
236+
uuid_cmp(PG_FUNCTION_ARGS)
237+
{
238+
uuid_t *arg1 = PG_GETARG_UUID_P(0);
239+
uuid_t *arg2 = PG_GETARG_UUID_P(1);
240+
241+
PG_RETURN_INT32(uuid_internal_cmp(arg1, arg2));
242+
}
243+
244+
/* hash index support */
245+
Datum
246+
uuid_hash(PG_FUNCTION_ARGS)
247+
{
248+
uuid_t *key = PG_GETARG_UUID_P(0);
249+
return hash_any((unsigned char *) key, sizeof(uuid_t));
250+
}
251+
252+
/* cast text to uuid */
253+
Datum
254+
text_uuid(PG_FUNCTION_ARGS)
255+
{
256+
text *input = PG_GETARG_TEXT_P(0);
257+
int length;
258+
char *str;
259+
Datum result;
260+
261+
length = VARSIZE(input) - VARHDRSZ;
262+
str = palloc(length + 1);
263+
memcpy(str, VARDATA(input), length);
264+
*(str + length) = '\0';
265+
266+
result = DirectFunctionCall1(uuid_in, CStringGetDatum(str));
267+
pfree(str);
268+
PG_RETURN_DATUM(result);
269+
}
270+
271+
/* cast uuid to text */
272+
Datum
273+
uuid_text(PG_FUNCTION_ARGS)
274+
{
275+
uuid_t *uuid = PG_GETARG_UUID_P(0);
276+
Datum uuid_str = DirectFunctionCall1(uuid_out, UUIDPGetDatum(uuid));
277+
278+
PG_RETURN_DATUM(DirectFunctionCall1(textin, uuid_str));
279+
}

src/include/catalog/catversion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.376 2007/01/22 01:35:21 tgl Exp $
40+
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.377 2007/01/28 16:16:52 neilc Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 200701211
56+
#define CATALOG_VERSION_NO 200701281
5757

5858
#endif

src/include/catalog/pg_amop.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
3030
* Portions Copyright (c) 1994, Regents of the University of California
3131
*
32-
* $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.77 2007/01/05 22:19:52 momjian Exp $
32+
* $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.78 2007/01/28 16:16:52 neilc Exp $
3333
*
3434
* NOTES
3535
* the genbki.sh script reads this file and generates .bki
@@ -487,6 +487,16 @@ DATA(insert ( 397 2277 2277 3 f 1070 403 ));
487487
DATA(insert ( 397 2277 2277 4 f 1075 403 ));
488488
DATA(insert ( 397 2277 2277 5 f 1073 403 ));
489489

490+
/*
491+
* btree uuid_ops
492+
*/
493+
494+
DATA(insert ( 2968 2950 2950 1 f 2974 403 ));
495+
DATA(insert ( 2968 2950 2950 2 f 2976 403 ));
496+
DATA(insert ( 2968 2950 2950 3 f 2972 403 ));
497+
DATA(insert ( 2968 2950 2950 4 f 2977 403 ));
498+
DATA(insert ( 2968 2950 2950 5 f 2975 403 ));
499+
490500
/*
491501
* hash index _ops
492502
*/
@@ -548,6 +558,9 @@ DATA(insert ( 2231 1042 1042 1 f 2328 405 ));
548558
DATA(insert ( 2232 19 19 1 f 2334 405 ));
549559
/* aclitem_ops */
550560
DATA(insert ( 2235 1033 1033 1 f 974 405 ));
561+
/* uuid_ops */
562+
DATA(insert ( 2969 2950 2950 1 f 2972 405 ));
563+
551564

552565
/*
553566
* gist box_ops

src/include/catalog/pg_amproc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
2323
* Portions Copyright (c) 1994, Regents of the University of California
2424
*
25-
* $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.62 2007/01/05 22:19:52 momjian Exp $
25+
* $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.63 2007/01/28 16:16:52 neilc Exp $
2626
*
2727
* NOTES
2828
* the genbki.sh script reads this file and generates .bki
@@ -127,6 +127,7 @@ DATA(insert ( 2099 790 790 1 377 ));
127127
DATA(insert ( 2233 703 703 1 380 ));
128128
DATA(insert ( 2234 704 704 1 381 ));
129129
DATA(insert ( 2789 27 27 1 2794 ));
130+
DATA(insert ( 2968 2950 2950 1 2960 ));
130131

131132

132133
/* hash */
@@ -160,6 +161,7 @@ DATA(insert ( 2229 25 25 1 456 ));
160161
DATA(insert ( 2231 1042 1042 1 456 ));
161162
DATA(insert ( 2232 19 19 1 455 ));
162163
DATA(insert ( 2235 1033 1033 1 329 ));
164+
DATA(insert ( 2969 2950 2950 1 2963 ));
163165

164166

165167
/* gist */

src/include/catalog/pg_cast.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
* Copyright (c) 2002-2007, PostgreSQL Global Development Group
1212
*
13-
* $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.28 2007/01/05 22:19:52 momjian Exp $
13+
* $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.29 2007/01/28 16:16:52 neilc Exp $
1414
*
1515
* NOTES
1616
* the genbki.sh script reads this file and generates .bki
@@ -397,4 +397,8 @@ DATA(insert ( 1560 1560 1685 i ));
397397
DATA(insert ( 1562 1562 1687 i ));
398398
DATA(insert ( 1700 1700 1703 i ));
399399

400+
/* casts to and from uuid */
401+
DATA(insert ( 25 2950 2964 a ));
402+
DATA(insert ( 2950 25 2965 a ));
403+
400404
#endif /* PG_CAST_H */

0 commit comments

Comments
 (0)