Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "postgres.h"
00015
00016 #include "access/hash.h"
00017 #include "libpq/pqformat.h"
00018 #include "utils/builtins.h"
00019 #include "utils/uuid.h"
00020
00021
00022 #define UUID_LEN 16
00023
00024
00025 struct pg_uuid_t
00026 {
00027 unsigned char data[UUID_LEN];
00028 };
00029
00030 static void string_to_uuid(const char *source, pg_uuid_t *uuid);
00031 static int uuid_internal_cmp(const pg_uuid_t *arg1, const pg_uuid_t *arg2);
00032
00033 Datum
00034 uuid_in(PG_FUNCTION_ARGS)
00035 {
00036 char *uuid_str = PG_GETARG_CSTRING(0);
00037 pg_uuid_t *uuid;
00038
00039 uuid = (pg_uuid_t *) palloc(sizeof(*uuid));
00040 string_to_uuid(uuid_str, uuid);
00041 PG_RETURN_UUID_P(uuid);
00042 }
00043
00044 Datum
00045 uuid_out(PG_FUNCTION_ARGS)
00046 {
00047 pg_uuid_t *uuid = PG_GETARG_UUID_P(0);
00048 static const char hex_chars[] = "0123456789abcdef";
00049 StringInfoData buf;
00050 int i;
00051
00052 initStringInfo(&buf);
00053 for (i = 0; i < UUID_LEN; i++)
00054 {
00055 int hi;
00056 int lo;
00057
00058
00059
00060
00061
00062
00063 if (i == 4 || i == 6 || i == 8 || i == 10)
00064 appendStringInfoChar(&buf, '-');
00065
00066 hi = uuid->data[i] >> 4;
00067 lo = uuid->data[i] & 0x0F;
00068
00069 appendStringInfoChar(&buf, hex_chars[hi]);
00070 appendStringInfoChar(&buf, hex_chars[lo]);
00071 }
00072
00073 PG_RETURN_CSTRING(buf.data);
00074 }
00075
00076
00077
00078
00079
00080
00081
00082 static void
00083 string_to_uuid(const char *source, pg_uuid_t *uuid)
00084 {
00085 const char *src = source;
00086 bool braces = false;
00087 int i;
00088
00089 if (src[0] == '{')
00090 {
00091 src++;
00092 braces = true;
00093 }
00094
00095 for (i = 0; i < UUID_LEN; i++)
00096 {
00097 char str_buf[3];
00098
00099 if (src[0] == '\0' || src[1] == '\0')
00100 goto syntax_error;
00101 memcpy(str_buf, src, 2);
00102 if (!isxdigit((unsigned char) str_buf[0]) ||
00103 !isxdigit((unsigned char) str_buf[1]))
00104 goto syntax_error;
00105
00106 str_buf[2] = '\0';
00107 uuid->data[i] = (unsigned char) strtoul(str_buf, NULL, 16);
00108 src += 2;
00109 if (src[0] == '-' && (i % 2) == 1 && i < UUID_LEN - 1)
00110 src++;
00111 }
00112
00113 if (braces)
00114 {
00115 if (*src != '}')
00116 goto syntax_error;
00117 src++;
00118 }
00119
00120 if (*src != '\0')
00121 goto syntax_error;
00122
00123 return;
00124
00125 syntax_error:
00126 ereport(ERROR,
00127 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00128 errmsg("invalid input syntax for uuid: \"%s\"",
00129 source)));
00130 }
00131
00132 Datum
00133 uuid_recv(PG_FUNCTION_ARGS)
00134 {
00135 StringInfo buffer = (StringInfo) PG_GETARG_POINTER(0);
00136 pg_uuid_t *uuid;
00137
00138 uuid = (pg_uuid_t *) palloc(UUID_LEN);
00139 memcpy(uuid->data, pq_getmsgbytes(buffer, UUID_LEN), UUID_LEN);
00140 PG_RETURN_POINTER(uuid);
00141 }
00142
00143 Datum
00144 uuid_send(PG_FUNCTION_ARGS)
00145 {
00146 pg_uuid_t *uuid = PG_GETARG_UUID_P(0);
00147 StringInfoData buffer;
00148
00149 pq_begintypsend(&buffer);
00150 pq_sendbytes(&buffer, (char *) uuid->data, UUID_LEN);
00151 PG_RETURN_BYTEA_P(pq_endtypsend(&buffer));
00152 }
00153
00154
00155 static int
00156 uuid_internal_cmp(const pg_uuid_t *arg1, const pg_uuid_t *arg2)
00157 {
00158 return memcmp(arg1->data, arg2->data, UUID_LEN);
00159 }
00160
00161 Datum
00162 uuid_lt(PG_FUNCTION_ARGS)
00163 {
00164 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
00165 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
00166
00167 PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) < 0);
00168 }
00169
00170 Datum
00171 uuid_le(PG_FUNCTION_ARGS)
00172 {
00173 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
00174 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
00175
00176 PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) <= 0);
00177 }
00178
00179 Datum
00180 uuid_eq(PG_FUNCTION_ARGS)
00181 {
00182 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
00183 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
00184
00185 PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) == 0);
00186 }
00187
00188 Datum
00189 uuid_ge(PG_FUNCTION_ARGS)
00190 {
00191 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
00192 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
00193
00194 PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) >= 0);
00195 }
00196
00197 Datum
00198 uuid_gt(PG_FUNCTION_ARGS)
00199 {
00200 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
00201 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
00202
00203 PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) > 0);
00204 }
00205
00206 Datum
00207 uuid_ne(PG_FUNCTION_ARGS)
00208 {
00209 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
00210 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
00211
00212 PG_RETURN_BOOL(uuid_internal_cmp(arg1, arg2) != 0);
00213 }
00214
00215
00216 Datum
00217 uuid_cmp(PG_FUNCTION_ARGS)
00218 {
00219 pg_uuid_t *arg1 = PG_GETARG_UUID_P(0);
00220 pg_uuid_t *arg2 = PG_GETARG_UUID_P(1);
00221
00222 PG_RETURN_INT32(uuid_internal_cmp(arg1, arg2));
00223 }
00224
00225
00226 Datum
00227 uuid_hash(PG_FUNCTION_ARGS)
00228 {
00229 pg_uuid_t *key = PG_GETARG_UUID_P(0);
00230
00231 return hash_any(key->data, UUID_LEN);
00232 }