Allow uuid_in() to parse a wider variety of variant input formats for the UUID
authorPeter Eisentraut <peter_e@gmx.net>
Mon, 3 Nov 2008 22:14:40 +0000 (22:14 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Mon, 3 Nov 2008 22:14:40 +0000 (22:14 +0000)
data type.  This patch takes the approach of allowing an optional hyphen after
each group of four hex digits.

Author: Robert Haas <robertmhaas@gmail.com>

doc/src/sgml/datatype.sgml
src/backend/utils/adt/uuid.c

index 26521661b7f205db48eac5503c0d1bab69eac315..d3d2bb5c07b31bafb6a68c57e887da801d2824a6 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.230 2008/10/14 17:12:32 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.231 2008/11/03 22:14:40 petere Exp $ -->
 
  <chapter id="datatype">
   <title id="datatype-title">Data Types</title>
@@ -3550,11 +3550,14 @@ a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
     <productname>PostgreSQL</productname> also accepts the following
     alternative forms for input:
     use of upper-case digits, the standard format surrounded by
-    braces, and omitting the hyphens.  Examples are:
+    braces, omitting some or all hyphens, adding a hyphen after any
+    group of four digits.  Examples are:
 <programlisting>
 A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
 {a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
 a0eebc999c0b4ef8bb6d6bb9bd380a11
+a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
+{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}
 </programlisting>
     Output is always in the standard form.
    </para>
index 216546e5206621fd6106c6046802a8d13158262e..76a012ed57779e3e647d7ba7318432a05c5fad54 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (c) 2007-2008, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/uuid.c,v 1.7 2008/01/01 20:31:21 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/uuid.c,v 1.8 2008/11/03 22:14:40 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -74,60 +74,51 @@ uuid_out(PG_FUNCTION_ARGS)
 }
 
 /*
- * We allow UUIDs in three input formats: 8x-4x-4x-4x-12x,
- * {8x-4x-4x-4x-12x}, and 32x, where "nx" means n hexadecimal digits
- * (only the first format is used for output). We convert the first
- * two formats into the latter format before further processing.
+ * We allow UUIDs as a series of 32 hexadecimal digits with an optional dash
+ * after each group of 4 hexadecimal digits, and optionally surrounded by {}.
+ * (The canonical format 8x-4x-4x-4x-12x, where "nx" means n hexadecimal
+ * digits, is the only one used for output.)
  */
 static void
 string_to_uuid(const char *source, pg_uuid_t *uuid)
 {
-       char            hex_buf[32];    /* not NUL terminated */
-       int                     i;
-       int                     src_len;
-
-       src_len = strlen(source);
-       if (src_len != 32 && src_len != 36 && src_len != 38)
-               goto syntax_error;
+       const char *src = source;
+       int     i, braces = 0;
 
-       if (src_len == 32)
-               memcpy(hex_buf, source, src_len);
-       else
+       if (src[0] == '{')
        {
-               const char *str = source;
-
-               if (src_len == 38)
-               {
-                       if (str[0] != '{' || str[37] != '}')
-                               goto syntax_error;
-
-                       str++;                          /* skip the first character */
-               }
-
-               if (str[8] != '-' || str[13] != '-' ||
-                       str[18] != '-' || str[23] != '-')
-                       goto syntax_error;
-
-               memcpy(hex_buf, str, 8);
-               memcpy(hex_buf + 8, str + 9, 4);
-               memcpy(hex_buf + 12, str + 14, 4);
-               memcpy(hex_buf + 16, str + 19, 4);
-               memcpy(hex_buf + 20, str + 24, 12);
+               ++src;
+               braces = 1;
        }
 
        for (i = 0; i < UUID_LEN; i++)
        {
                char            str_buf[3];
 
-               memcpy(str_buf, &hex_buf[i * 2], 2);
+               if (src[0] == '\0' || src[1] == '\0')
+                       goto syntax_error;
+               memcpy(str_buf, src, 2);
                if (!isxdigit((unsigned char) str_buf[0]) ||
                        !isxdigit((unsigned char) str_buf[1]))
                        goto syntax_error;
 
                str_buf[2] = '\0';
                uuid->data[i] = (unsigned char) strtoul(str_buf, NULL, 16);
+               src += 2;
+               if (src[0] == '-' && (i % 2) == 1 && i < UUID_LEN - 1)
+                       src++;
        }
 
+       if (braces)
+       {
+               if (*src!= '}')
+                       goto syntax_error;
+               ++src;
+       }
+
+       if (*src != '\0')
+               goto syntax_error;
+
        return;
 
 syntax_error: