Commit 0f2fbbba authored by Tom Lane's avatar Tom Lane

Try to make array_in's behavior a tad less bizarre. Leading whitespace

before a data item is now always skipped, rather than only sometimes.
Backslashes not within double-quoted text are treated reasonably, as
are multiple sequences of quoted text in a single data item.  But it
still seems rather prone to misbehavior if the input is not completely
syntactically correct --- in particular, garbage following a right brace
will be ignored.
parent 134fe5ec
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.75 2002/03/02 00:34:24 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.76 2002/03/16 22:47:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -51,7 +51,7 @@
#define RETURN_NULL(type) do { *isNull = true; return (type) 0; } while (0)
static int ArrayCount(char *str, int *dim, int typdelim);
static int ArrayCount(char *str, int *dim, char typdelim);
static Datum *ReadArrayStr(char *arrayStr, int nitems, int ndim, int *dim,
FmgrInfo *inputproc, Oid typelem, int32 typmod,
char typdelim, int typlen, bool typbyval,
......@@ -245,7 +245,7 @@ array_in(PG_FUNCTION_ARGS)
*-----------------------------------------------------------------------------
*/
static int
ArrayCount(char *str, int *dim, int typdelim)
ArrayCount(char *str, int *dim, char typdelim)
{
int nest_level = 0,
i;
......@@ -253,7 +253,7 @@ ArrayCount(char *str, int *dim, int typdelim)
temp[MAXDIM];
bool scanning_string = false;
bool eoArray = false;
char *q;
char *ptr;
for (i = 0; i < MAXDIM; ++i)
temp[i] = dim[i] = 0;
......@@ -261,65 +261,68 @@ ArrayCount(char *str, int *dim, int typdelim)
if (strncmp(str, "{}", 2) == 0)
return 0;
q = str;
while (eoArray != true)
ptr = str;
while (!eoArray)
{
bool done = false;
bool itemdone = false;
while (!done)
while (!itemdone)
{
switch (*q)
switch (*ptr)
{
case '\\':
/* skip escaped characters (\ and ") inside strings */
if (scanning_string && *(q + 1))
q++;
break;
case '\0':
/*
* Signal a premature end of the string. DZ -
* 2-9-1996
*/
/* Signal a premature end of the string */
elog(ERROR, "malformed array constant: %s", str);
break;
case '\\':
/* skip the escaped character */
if (*(ptr + 1))
ptr++;
else
elog(ERROR, "malformed array constant: %s", str);
break;
case '\"':
scanning_string = !scanning_string;
break;
case '{':
if (!scanning_string)
{
if (nest_level >= MAXDIM)
elog(ERROR, "array_in: illformed array constant");
temp[nest_level] = 0;
nest_level++;
if (ndim < nest_level)
ndim = nest_level;
}
break;
case '}':
if (!scanning_string)
{
if (!ndim)
ndim = nest_level;
if (nest_level == 0)
elog(ERROR, "array_in: illformed array constant");
nest_level--;
if (nest_level)
temp[nest_level - 1]++;
if (nest_level == 0)
eoArray = done = true;
eoArray = itemdone = true;
else
{
/*
* We don't set itemdone here; see comments in
* ReadArrayStr
*/
temp[nest_level - 1]++;
}
}
break;
default:
if (!ndim)
ndim = nest_level;
if (*q == typdelim && !scanning_string)
done = true;
if (*ptr == typdelim && !scanning_string)
itemdone = true;
break;
}
if (!done)
q++;
if (!itemdone)
ptr++;
}
temp[ndim - 1]++;
q++;
if (!eoArray)
while (isspace((unsigned char) *q))
q++;
ptr++;
}
for (i = 0; i < ndim; ++i)
dim[i] = temp[i];
......@@ -359,103 +362,119 @@ ReadArrayStr(char *arrayStr,
int i,
nest_level = 0;
Datum *values;
char *p,
*q,
*r;
char *ptr;
bool scanning_string = false;
bool eoArray = false;
int indx[MAXDIM],
prod[MAXDIM];
bool eoArray = false;
mda_get_prod(ndim, dim, prod);
values = (Datum *) palloc(nitems * sizeof(Datum));
MemSet(values, 0, nitems * sizeof(Datum));
MemSet(indx, 0, sizeof(indx));
q = p = arrayStr;
/* read array enclosed within {} */
ptr = arrayStr;
while (!eoArray)
{
bool done = false;
bool itemdone = false;
int i = -1;
char *itemstart;
/* skip leading whitespace */
while (isspace((unsigned char) *ptr))
ptr++;
itemstart = ptr;
while (!done)
while (!itemdone)
{
switch (*q)
switch (*ptr)
{
case '\0':
/* Signal a premature end of the string */
elog(ERROR, "malformed array constant: %s", arrayStr);
break;
case '\\':
{
char *cptr;
/* Crunch the string on top of the backslash. */
for (r = q; *r != '\0'; r++)
*r = *(r + 1);
for (cptr = ptr; *cptr != '\0'; cptr++)
*cptr = *(cptr + 1);
if (*ptr == '\0')
elog(ERROR, "malformed array constant: %s", arrayStr);
break;
}
case '\"':
if (!scanning_string)
{
while (p != q)
p++;
p++; /* get p past first doublequote */
}
else
*q = '\0';
{
char *cptr;
scanning_string = !scanning_string;
/* Crunch the string on top of the quote. */
for (cptr = ptr; *cptr != '\0'; cptr++)
*cptr = *(cptr + 1);
/* Back up to not miss following character. */
ptr--;
break;
}
case '{':
if (!scanning_string)
{
p++;
nest_level++;
if (nest_level > ndim)
if (nest_level >= ndim)
elog(ERROR, "array_in: illformed array constant");
nest_level++;
indx[nest_level - 1] = 0;
indx[ndim - 1] = 0;
/* skip leading whitespace */
while (isspace((unsigned char) *(ptr+1)))
ptr++;
itemstart = ptr+1;
}
break;
case '}':
if (!scanning_string)
{
if (nest_level == 0)
elog(ERROR, "array_in: illformed array constant");
if (i == -1)
i = ArrayGetOffset0(ndim, indx, prod);
indx[nest_level - 1] = 0;
nest_level--;
if (nest_level == 0)
eoArray = done = true;
eoArray = itemdone = true;
else
{
*q = '\0';
/*
* tricky coding: terminate item value string at
* first '}', but don't process it till we see
* a typdelim char or end of array. This handles
* case where several '}'s appear successively
* in a multidimensional array.
*/
*ptr = '\0';
indx[nest_level - 1]++;
}
}
break;
default:
if (*q == typdelim && !scanning_string)
if (*ptr == typdelim && !scanning_string)
{
if (i == -1)
i = ArrayGetOffset0(ndim, indx, prod);
done = true;
itemdone = true;
indx[ndim - 1]++;
}
break;
}
if (!done)
q++;
if (!itemdone)
ptr++;
}
*q = '\0';
if (i >= nitems)
*ptr++ = '\0';
if (i < 0 || i >= nitems)
elog(ERROR, "array_in: illformed array constant");
values[i] = FunctionCall3(inputproc,
CStringGetDatum(p),
CStringGetDatum(itemstart),
ObjectIdGetDatum(typelem),
Int32GetDatum(typmod));
p = ++q;
/*
* if not at the end of the array skip white space
*/
if (!eoArray)
while (isspace((unsigned char) *q))
{
p++;
q++;
}
}
/*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment