mirror of
https://github.com/postgres/postgres.git
synced 2025-06-29 10:41:53 +03:00
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.
This commit is contained in:
@ -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;
|
||||
nest_level--;
|
||||
if (nest_level)
|
||||
temp[nest_level - 1]++;
|
||||
if (nest_level == 0)
|
||||
eoArray = done = true;
|
||||
elog(ERROR, "array_in: illformed array constant");
|
||||
nest_level--;
|
||||
if (nest_level == 0)
|
||||
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;
|
||||
|
||||
while (!done)
|
||||
/* skip leading whitespace */
|
||||
while (isspace((unsigned char) *ptr))
|
||||
ptr++;
|
||||
itemstart = ptr;
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user