Clean up array-dimensions parser a bit.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 14 Nov 2000 23:28:13 +0000 (23:28 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 14 Nov 2000 23:28:13 +0000 (23:28 +0000)
This code still needs a lot of love, however ...

src/backend/utils/adt/arrayfuncs.c

index b0855b7740a372b90b966295d925c97352d1ac4c..44f58840c3650d08879f7d22f9f7fe681bc395f0 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.64 2000/07/27 03:50:52 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.65 2000/11/14 23:28:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -100,15 +100,12 @@ array_in(PG_FUNCTION_ARGS)
    Oid         element_type = PG_GETARG_OID(1); /* type of an array element */
    int32       typmod = PG_GETARG_INT32(2); /* typmod for array elements */
    int         typlen;
-   bool        typbyval,
-               done;
+   bool        typbyval;
    char        typdelim;
    Oid         typinput;
    Oid         typelem;
    char       *string_save,
-              *p,
-              *q,
-              *r;
+              *p;
    FmgrInfo    inputproc;
    int         i,
                nitems;
@@ -120,64 +117,83 @@ array_in(PG_FUNCTION_ARGS)
                lBound[MAXDIM];
    char        typalign;
 
+   /* Get info about element type, including its input conversion proc */
    system_cache_lookup(element_type, true, &typlen, &typbyval, &typdelim,
                        &typelem, &typinput, &typalign);
-
    fmgr_info(typinput, &inputproc);
 
+   /* Make a modifiable copy of the input */
+   /* XXX why are we allocating an extra 2 bytes here? */
    string_save = (char *) palloc(strlen(string) + 3);
    strcpy(string_save, string);
 
-   /* --- read array dimensions  ---------- */
-   p = q = string_save;
-   done = false;
-   for (ndim = 0; !done;)
+   /*
+    * If the input string starts with dimension info, read and use that.
+    * Otherwise, we require the input to be in curly-brace style, and we
+    * prescan the input to determine dimensions.
+    *
+    * Dimension info takes the form of one or more [n] or [m:n] items.
+    * The outer loop iterates once per dimension item.
+    */
+   p = string_save;
+   ndim = 0;
+   for (;;)
    {
+       char       *q;
+       int         ub;
+
+       /*
+        * Note: we currently allow whitespace between, but not within,
+        * dimension items.
+        */
        while (isspace((int) *p))
            p++;
-       if (*p == '[')
+       if (*p != '[')
+           break;              /* no more dimension items */
+       p++;
+       if (ndim >= MAXDIM)
+           elog(ERROR, "array_in: more than %d dimensions", MAXDIM);
+       for (q = p; isdigit((int) *q); q++);
+       if (q == p)             /* no digits? */
+           elog(ERROR, "array_in: missing dimension value");
+       if (*q == ':')
        {
-           p++;
-           if ((r = (char *) strchr(p, ':')) == (char *) NULL)
-               lBound[ndim] = 1;
-           else
-           {
-               *r = '\0';
-               lBound[ndim] = atoi(p);
-               p = r + 1;
-           }
-           for (q = p; isdigit((int) *q); q++);
-           if (*q != ']')
-               elog(ERROR, "array_in: missing ']' in array declaration");
+           /* [m:n] format */
            *q = '\0';
-           dim[ndim] = atoi(p);
-           if ((dim[ndim] < 0) || (lBound[ndim] < 0))
-               elog(ERROR, "array_in: array dimensions need to be positive");
-           dim[ndim] = dim[ndim] - lBound[ndim] + 1;
-           if (dim[ndim] < 0)
-               elog(ERROR, "array_in: upper_bound cannot be < lower_bound");
+           lBound[ndim] = atoi(p);
            p = q + 1;
-           ndim++;
+           for (q = p; isdigit((int) *q); q++);
+           if (q == p)         /* no digits? */
+               elog(ERROR, "array_in: missing dimension value");
        }
        else
-           done = true;
+       {
+           /* [n] format */
+           lBound[ndim] = 1;
+       }
+       if (*q != ']')
+           elog(ERROR, "array_in: missing ']' in array declaration");
+       *q = '\0';
+       ub = atoi(p);
+       p = q + 1;
+       if (ub < lBound[ndim])
+           elog(ERROR, "array_in: upper_bound cannot be < lower_bound");
+       dim[ndim] = ub - lBound[ndim] + 1;
+       ndim++;
    }
 
    if (ndim == 0)
    {
-       if (*p == '{')
-       {
-           ndim = ArrayCount(p, dim, typdelim);
-           for (i = 0; i < ndim; i++)
-               lBound[i] = 1;
-       }
-       else
+       /* No array dimensions, so intuit dimensions from brace structure */
+       if (*p != '{')
            elog(ERROR, "array_in: Need to specify dimension");
+       ndim = ArrayCount(p, dim, typdelim);
+       for (i = 0; i < ndim; i++)
+           lBound[i] = 1;
    }
    else
    {
-       while (isspace((int) *p))
-           p++;
+       /* If array dimensions are given, expect '=' operator */
        if (strncmp(p, ASSGN, strlen(ASSGN)) != 0)
            elog(ERROR, "array_in: missing assignment operator");
        p += strlen(ASSGN);