From: Tom Lane Date: Tue, 14 Nov 2000 23:28:13 +0000 (+0000) Subject: Clean up array-dimensions parser a bit. X-Git-Tag: REL7_1_BETA~171 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=85b762b49997b8f10913db9a015765f408f6f72c;p=postgresql Clean up array-dimensions parser a bit. This code still needs a lot of love, however ... --- diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index b0855b7740..44f58840c3 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -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);