aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/arrayfuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/arrayfuncs.c')
-rw-r--r--src/backend/utils/adt/arrayfuncs.c125
1 files changed, 75 insertions, 50 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 59a0852d07c..0d3d46b9a52 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -90,14 +90,15 @@ typedef struct ArrayIteratorData
} ArrayIteratorData;
static bool array_isspace(char ch);
-static int ArrayCount(const char *str, int *dim, char typdelim);
-static void ReadArrayStr(char *arrayStr, const char *origStr,
+static int ArrayCount(const char *str, int *dim, char typdelim,
+ Node *escontext);
+static bool ReadArrayStr(char *arrayStr, const char *origStr,
int nitems, int ndim, int *dim,
FmgrInfo *inputproc, Oid typioparam, int32 typmod,
char typdelim,
int typlen, bool typbyval, char typalign,
Datum *values, bool *nulls,
- bool *hasnulls, int32 *nbytes);
+ bool *hasnulls, int32 *nbytes, Node *escontext);
static void ReadArrayBinary(StringInfo buf, int nitems,
FmgrInfo *receiveproc, Oid typioparam, int32 typmod,
int typlen, bool typbyval, char typalign,
@@ -177,6 +178,7 @@ 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 */
+ Node *escontext = fcinfo->context;
int typlen;
bool typbyval;
char typalign;
@@ -258,7 +260,7 @@ array_in(PG_FUNCTION_ARGS)
break; /* no more dimension items */
p++;
if (ndim >= MAXDIM)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
ndim + 1, MAXDIM)));
@@ -266,7 +268,7 @@ array_in(PG_FUNCTION_ARGS)
for (q = p; isdigit((unsigned char) *q) || (*q == '-') || (*q == '+'); q++)
/* skip */ ;
if (q == p) /* no digits? */
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", string),
errdetail("\"[\" must introduce explicitly-specified array dimensions.")));
@@ -280,7 +282,7 @@ array_in(PG_FUNCTION_ARGS)
for (q = p; isdigit((unsigned char) *q) || (*q == '-') || (*q == '+'); q++)
/* skip */ ;
if (q == p) /* no digits? */
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", string),
errdetail("Missing array dimension value.")));
@@ -291,7 +293,7 @@ array_in(PG_FUNCTION_ARGS)
lBound[ndim] = 1;
}
if (*q != ']')
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", string),
errdetail("Missing \"%s\" after array dimensions.",
@@ -301,7 +303,7 @@ array_in(PG_FUNCTION_ARGS)
ub = atoi(p);
p = q + 1;
if (ub < lBound[ndim])
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
errmsg("upper bound cannot be less than lower bound")));
@@ -313,11 +315,13 @@ array_in(PG_FUNCTION_ARGS)
{
/* No array dimensions, so intuit dimensions from brace structure */
if (*p != '{')
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", string),
errdetail("Array value must start with \"{\" or dimension information.")));
- ndim = ArrayCount(p, dim, typdelim);
+ ndim = ArrayCount(p, dim, typdelim, escontext);
+ if (ndim < 0)
+ PG_RETURN_NULL();
for (i = 0; i < ndim; i++)
lBound[i] = 1;
}
@@ -328,7 +332,7 @@ array_in(PG_FUNCTION_ARGS)
/* If array dimensions are given, expect '=' operator */
if (strncmp(p, ASSGN, strlen(ASSGN)) != 0)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", string),
errdetail("Missing \"%s\" after array dimensions.",
@@ -342,20 +346,22 @@ array_in(PG_FUNCTION_ARGS)
* were given
*/
if (*p != '{')
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", string),
errdetail("Array contents must start with \"{\".")));
- ndim_braces = ArrayCount(p, dim_braces, typdelim);
+ ndim_braces = ArrayCount(p, dim_braces, typdelim, escontext);
+ if (ndim_braces < 0)
+ PG_RETURN_NULL();
if (ndim_braces != ndim)
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", string),
errdetail("Specified array dimensions do not match array contents.")));
for (i = 0; i < ndim; ++i)
{
if (dim[i] != dim_braces[i])
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", string),
errdetail("Specified array dimensions do not match array contents.")));
@@ -372,8 +378,11 @@ array_in(PG_FUNCTION_ARGS)
#endif
/* This checks for overflow of the array dimensions */
- nitems = ArrayGetNItems(ndim, dim);
- ArrayCheckBounds(ndim, dim, lBound);
+ nitems = ArrayGetNItemsSafe(ndim, dim, escontext);
+ if (nitems < 0)
+ PG_RETURN_NULL();
+ if (!ArrayCheckBoundsSafe(ndim, dim, lBound, escontext))
+ PG_RETURN_NULL();
/* Empty array? */
if (nitems == 0)
@@ -381,13 +390,14 @@ array_in(PG_FUNCTION_ARGS)
dataPtr = (Datum *) palloc(nitems * sizeof(Datum));
nullsPtr = (bool *) palloc(nitems * sizeof(bool));
- ReadArrayStr(p, string,
- nitems, ndim, dim,
- &my_extra->proc, typioparam, typmod,
- typdelim,
- typlen, typbyval, typalign,
- dataPtr, nullsPtr,
- &hasnulls, &nbytes);
+ if (!ReadArrayStr(p, string,
+ nitems, ndim, dim,
+ &my_extra->proc, typioparam, typmod,
+ typdelim,
+ typlen, typbyval, typalign,
+ dataPtr, nullsPtr,
+ &hasnulls, &nbytes, escontext))
+ PG_RETURN_NULL();
if (hasnulls)
{
dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nitems);
@@ -451,9 +461,12 @@ array_isspace(char ch)
*
* Returns number of dimensions as function result. The axis lengths are
* returned in dim[], which must be of size MAXDIM.
+ *
+ * If we detect an error, fill *escontext with error details and return -1
+ * (unless escontext isn't provided, in which case errors will be thrown).
*/
static int
-ArrayCount(const char *str, int *dim, char typdelim)
+ArrayCount(const char *str, int *dim, char typdelim, Node *escontext)
{
int nest_level = 0,
i;
@@ -488,11 +501,10 @@ ArrayCount(const char *str, int *dim, char typdelim)
{
case '\0':
/* Signal a premature end of the string */
- ereport(ERROR,
+ ereturn(escontext, -1,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", str),
errdetail("Unexpected end of input.")));
- break;
case '\\':
/*
@@ -504,7 +516,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
parse_state != ARRAY_ELEM_STARTED &&
parse_state != ARRAY_QUOTED_ELEM_STARTED &&
parse_state != ARRAY_ELEM_DELIMITED)
- ereport(ERROR,
+ ereturn(escontext, -1,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", str),
errdetail("Unexpected \"%c\" character.",
@@ -515,7 +527,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
if (*(ptr + 1))
ptr++;
else
- ereport(ERROR,
+ ereturn(escontext, -1,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", str),
errdetail("Unexpected end of input.")));
@@ -530,7 +542,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
if (parse_state != ARRAY_LEVEL_STARTED &&
parse_state != ARRAY_QUOTED_ELEM_STARTED &&
parse_state != ARRAY_ELEM_DELIMITED)
- ereport(ERROR,
+ ereturn(escontext, -1,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", str),
errdetail("Unexpected array element.")));
@@ -551,14 +563,14 @@ ArrayCount(const char *str, int *dim, char typdelim)
if (parse_state != ARRAY_NO_LEVEL &&
parse_state != ARRAY_LEVEL_STARTED &&
parse_state != ARRAY_LEVEL_DELIMITED)
- ereport(ERROR,
+ ereturn(escontext, -1,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", str),
errdetail("Unexpected \"%c\" character.",
'{')));
parse_state = ARRAY_LEVEL_STARTED;
if (nest_level >= MAXDIM)
- ereport(ERROR,
+ ereturn(escontext, -1,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
nest_level + 1, MAXDIM)));
@@ -581,14 +593,14 @@ ArrayCount(const char *str, int *dim, char typdelim)
parse_state != ARRAY_QUOTED_ELEM_COMPLETED &&
parse_state != ARRAY_LEVEL_COMPLETED &&
!(nest_level == 1 && parse_state == ARRAY_LEVEL_STARTED))
- ereport(ERROR,
+ ereturn(escontext, -1,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", str),
errdetail("Unexpected \"%c\" character.",
'}')));
parse_state = ARRAY_LEVEL_COMPLETED;
if (nest_level == 0)
- ereport(ERROR,
+ ereturn(escontext, -1,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", str),
errdetail("Unmatched \"%c\" character.", '}')));
@@ -596,7 +608,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
if (nelems_last[nest_level] != 0 &&
nelems[nest_level] != nelems_last[nest_level])
- ereport(ERROR,
+ ereturn(escontext, -1,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", str),
errdetail("Multidimensional arrays must have "
@@ -630,7 +642,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
parse_state != ARRAY_ELEM_COMPLETED &&
parse_state != ARRAY_QUOTED_ELEM_COMPLETED &&
parse_state != ARRAY_LEVEL_COMPLETED)
- ereport(ERROR,
+ ereturn(escontext, -1,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", str),
errdetail("Unexpected \"%c\" character.",
@@ -653,7 +665,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
if (parse_state != ARRAY_LEVEL_STARTED &&
parse_state != ARRAY_ELEM_STARTED &&
parse_state != ARRAY_ELEM_DELIMITED)
- ereport(ERROR,
+ ereturn(escontext, -1,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", str),
errdetail("Unexpected array element.")));
@@ -673,7 +685,7 @@ ArrayCount(const char *str, int *dim, char typdelim)
while (*ptr)
{
if (!array_isspace(*ptr++))
- ereport(ERROR,
+ ereturn(escontext, -1,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"", str),
errdetail("Junk after closing right brace.")));
@@ -713,11 +725,16 @@ ArrayCount(const char *str, int *dim, char typdelim)
* *hasnulls: set true iff there are any null elements.
* *nbytes: set to total size of data area needed (including alignment
* padding but not including array header overhead).
+ * *escontext: if this points to an ErrorSaveContext, details of
+ * any error are reported there.
+ *
+ * Result:
+ * true for success, false for failure (if escontext is provided).
*
* Note that values[] and nulls[] are allocated by the caller, and must have
* nitems elements.
*/
-static void
+static bool
ReadArrayStr(char *arrayStr,
const char *origStr,
int nitems,
@@ -733,7 +750,8 @@ ReadArrayStr(char *arrayStr,
Datum *values,
bool *nulls,
bool *hasnulls,
- int32 *nbytes)
+ int32 *nbytes,
+ Node *escontext)
{
int i,
nest_level = 0;
@@ -784,7 +802,7 @@ ReadArrayStr(char *arrayStr,
{
case '\0':
/* Signal a premature end of the string */
- ereport(ERROR,
+ ereturn(escontext, false,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"",
origStr)));
@@ -793,7 +811,7 @@ ReadArrayStr(char *arrayStr,
/* Skip backslash, copy next character as-is. */
srcptr++;
if (*srcptr == '\0')
- ereport(ERROR,
+ ereturn(escontext, false,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"",
origStr)));
@@ -823,7 +841,7 @@ ReadArrayStr(char *arrayStr,
if (!in_quotes)
{
if (nest_level >= ndim)
- ereport(ERROR,
+ ereturn(escontext, false,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"",
origStr)));
@@ -838,7 +856,7 @@ ReadArrayStr(char *arrayStr,
if (!in_quotes)
{
if (nest_level == 0)
- ereport(ERROR,
+ ereturn(escontext, false,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"",
origStr)));
@@ -891,7 +909,7 @@ ReadArrayStr(char *arrayStr,
*dstendptr = '\0';
if (i < 0 || i >= nitems)
- ereport(ERROR,
+ ereturn(escontext, false,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("malformed array literal: \"%s\"",
origStr)));
@@ -900,14 +918,20 @@ ReadArrayStr(char *arrayStr,
pg_strcasecmp(itemstart, "NULL") == 0)
{
/* it's a NULL item */
- values[i] = InputFunctionCall(inputproc, NULL,
- typioparam, typmod);
+ if (!InputFunctionCallSafe(inputproc, NULL,
+ typioparam, typmod,
+ escontext,
+ &values[i]))
+ return false;
nulls[i] = true;
}
else
{
- values[i] = InputFunctionCall(inputproc, itemstart,
- typioparam, typmod);
+ if (!InputFunctionCallSafe(inputproc, itemstart,
+ typioparam, typmod,
+ escontext,
+ &values[i]))
+ return false;
nulls[i] = false;
}
}
@@ -930,7 +954,7 @@ ReadArrayStr(char *arrayStr,
totbytes = att_align_nominal(totbytes, typalign);
/* check for overflow of total request */
if (!AllocSizeIsValid(totbytes))
- ereport(ERROR,
+ ereturn(escontext, false,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("array size exceeds the maximum allowed (%d)",
(int) MaxAllocSize)));
@@ -938,6 +962,7 @@ ReadArrayStr(char *arrayStr,
}
*hasnulls = hasnull;
*nbytes = totbytes;
+ return true;
}