diff options
Diffstat (limited to 'src/backend/utils/adt/arrayfuncs.c')
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 125 |
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; } |