1 /*-------------------------------------------------------------------------
4 * Functions for the built-in type "uuid".
6 * Copyright (c) 2007, PostgreSQL Global Development Group
9 * $PostgreSQL: pgsql/src/backend/utils/adt/uuid.c,v 1.4 2007/06/05 21:31:06 tgl Exp $
11 *-------------------------------------------------------------------------
16 #include "access/hash.h"
17 #include "libpq/pqformat.h"
18 #include "utils/builtins.h"
19 #include "utils/uuid.h"
21 /* uuid size in bytes */
24 /* pg_uuid_t is declared to be struct pg_uuid_t in uuid.h */
27 unsigned char data[UUID_LEN];
30 static void string_to_uuid(const char *source, pg_uuid_t *uuid);
31 static int uuid_internal_cmp(const pg_uuid_t *arg1, const pg_uuid_t *arg2);
34 uuid_in(PG_FUNCTION_ARGS)
36 char *uuid_str = PG_GETARG_CSTRING(0);
39 uuid = (pg_uuid_t *) palloc(sizeof(*uuid));
40 string_to_uuid(uuid_str, uuid);
41 PG_RETURN_UUID_P(uuid);
45 uuid_out(PG_FUNCTION_ARGS)
47 pg_uuid_t *uuid = PG_GETARG_UUID_P(0);
48 static const char hex_chars[] = "0123456789abcdef";
53 for (i = 0; i < UUID_LEN; i++)
59 * We print uuid values as a string of 8, 4, 4, 4, and then 12
60 * hexadecimal characters, with each group is separated by a
61 * hyphen ("-"). Therefore, add the hyphens at the appropriate
64 if (i == 4 || i == 6 || i == 8 || i == 10)
65 appendStringInfoChar(&buf, '-');
67 hi = uuid->data[i] >> 4;
68 lo = uuid->data[i] & 0x0F;
70 appendStringInfoChar(&buf, hex_chars[hi]);
71 appendStringInfoChar(&buf, hex_chars[lo]);
74 PG_RETURN_CSTRING(buf.data);
78 * We allow UUIDs in three input formats: 8x-4x-4x-4x-12x,
79 * {8x-4x-4x-4x-12x}, and 32x, where "nx" means n hexadecimal digits
80 * (only the first format is used for output). We convert the first
81 * two formats into the latter format before further processing.
84 string_to_uuid(const char *source, pg_uuid_t *uuid)
86 char hex_buf[32]; /* not NUL terminated */
90 src_len = strlen(source);
91 if (src_len != 32 && src_len != 36 && src_len != 38)
95 memcpy(hex_buf, source, src_len);
98 const char *str = source;
102 if (str[0] != '{' || str[37] != '}')
105 str++; /* skip the first character */
108 if (str[8] != '-' || str[13] != '-' ||
109 str[18] != '-' || str[23] != '-')
112 memcpy(hex_buf, str, 8);
113 memcpy(hex_buf + 8, str + 9, 4);
114 memcpy(hex_buf + 12, str + 14, 4);
115 memcpy(hex_buf + 16, str + 19, 4);
116 memcpy(hex_buf + 20, str + 24, 12);
119 for (i = 0; i < UUID_LEN; i++)
123 memcpy(str_buf, &hex_buf[i * 2], 2);
124 if (!isxdigit((unsigned char) str_buf[0]) ||
125 !isxdigit((unsigned char) str_buf[1]))
129 uuid->data[i] = (unsigned char) strtoul(str_buf, NULL, 16);
136 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
137 errmsg("invalid input syntax for uuid: \"%s\"",
142 uuid_recv(PG_FUNCTION_ARGS)
144 StringInfo buffer = (StringInfo) PG_GETARG_POINTER(0);
147 uuid = (pg_uuid_t *) palloc(UUID_LEN);
148 memcpy(uuid->data, pq_getmsgbytes(buffer, UUID_LEN), UUID_LEN);
149 PG_RETURN_POINTER(uuid);
153 uuid_send(PG_FUNCTION_ARGS)
155 pg_uuid_t *uuid = PG_GETARG_UUID_P(0);
156 StringInfoData buffer;
158 pq_begintypsend(&buffer);
159 pq_sendbytes(&buffer, (char *) uuid->data, UUID_LEN);
160 PG_RETURN_BYTEA_P(pq_endtypsend(&buffer));
163 /* internal uuid compare function */
165 uuid_internal_cmp(const pg_uuid_t *arg1, const pg_uuid_t *arg2)
167 return memcmp(arg1->data, arg2->data, UUID_LEN);
171 uuid_lt(PG_FUNCTION_ARGS)
173 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
174 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
176 PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) < 0);
180 uuid_le(PG_FUNCTION_ARGS)
182 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
183 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
185 PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) <= 0);
189 uuid_eq(PG_FUNCTION_ARGS)
191 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
192 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
194 PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) == 0);
198 uuid_ge(PG_FUNCTION_ARGS)
200 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
201 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
203 PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) >= 0);
207 uuid_gt(PG_FUNCTION_ARGS)
209 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
210 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
212 PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) > 0);
216 uuid_ne(PG_FUNCTION_ARGS)
218 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
219 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
221 PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) != 0);
224 /* handler for btree index operator */
226 uuid_cmp(PG_FUNCTION_ARGS)
228 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
229 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
231 PG_RETURN_INT32(uuid_internal_cmp(arg1, arg2));
234 /* hash index support */
236 uuid_hash(PG_FUNCTION_ARGS)
238 pg_uuid_t *key = PG_GETARG_UUID_P(0);
239 return hash_any(key->data, UUID_LEN);