diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2014-12-02 18:23:16 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2014-12-02 18:23:27 -0500 |
commit | 475aedd1ef0c0f9fc9d675dd2286380d14804975 (patch) | |
tree | b237c4f2504714f8dc8ee3fca32754ef0a106abc /src/backend/utils/adt/arrayfuncs.c | |
parent | 0fd38e13706e6bd4b2a4ce4e0570d0aa4ad65345 (diff) | |
download | postgresql-475aedd1ef0c0f9fc9d675dd2286380d14804975.tar.gz postgresql-475aedd1ef0c0f9fc9d675dd2286380d14804975.zip |
Improve error messages for malformed array input strings.
Make the error messages issued by array_in() uniformly follow the style
ERROR: malformed array literal: "actual input string"
DETAIL: specific complaint here
and rewrite many of the specific complaints to be clearer.
The immediate motivation for doing this is a complaint from Josh Berkus
that json_to_record() produced an unintelligible error message when
dealing with an array item, because it tries to feed the JSON-format
array value to array_in(). Really it ought to be smart enough to
perform JSON-to-Postgres array conversion, but that's a future feature
not a bug fix. In the meantime, this change is something we agreed
we could back-patch into 9.4, and it should help de-confuse things a bit.
Diffstat (limited to 'src/backend/utils/adt/arrayfuncs.c')
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 76 |
1 files changed, 52 insertions, 24 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 743351b95e0..933c6b035c6 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -247,11 +247,13 @@ array_in(PG_FUNCTION_ARGS) errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", ndim + 1, MAXDIM))); - for (q = p; isdigit((unsigned char) *q) || (*q == '-') || (*q == '+'); q++); + for (q = p; isdigit((unsigned char) *q) || (*q == '-') || (*q == '+'); q++) + /* skip */ ; if (q == p) /* no digits? */ ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("missing dimension value"))); + errmsg("malformed array literal: \"%s\"", string), + errdetail("\"[\" must introduce explicitly-specified array dimensions."))); if (*q == ':') { @@ -259,11 +261,13 @@ array_in(PG_FUNCTION_ARGS) *q = '\0'; lBound[ndim] = atoi(p); p = q + 1; - for (q = p; isdigit((unsigned char) *q) || (*q == '-') || (*q == '+'); q++); + for (q = p; isdigit((unsigned char) *q) || (*q == '-') || (*q == '+'); q++) + /* skip */ ; if (q == p) /* no digits? */ ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("missing dimension value"))); + errmsg("malformed array literal: \"%s\"", string), + errdetail("Missing array dimension value."))); } else { @@ -273,7 +277,9 @@ array_in(PG_FUNCTION_ARGS) if (*q != ']') ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("missing \"]\" in array dimensions"))); + errmsg("malformed array literal: \"%s\"", string), + errdetail("Missing \"%s\" after array dimensions.", + "]"))); *q = '\0'; ub = atoi(p); @@ -293,7 +299,8 @@ array_in(PG_FUNCTION_ARGS) if (*p != '{') ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("array value must start with \"{\" or dimension information"))); + errmsg("malformed array literal: \"%s\"", string), + errdetail("Array value must start with \"{\" or dimension information."))); ndim = ArrayCount(p, dim, typdelim); for (i = 0; i < ndim; i++) lBound[i] = 1; @@ -307,7 +314,9 @@ array_in(PG_FUNCTION_ARGS) if (strncmp(p, ASSGN, strlen(ASSGN)) != 0) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("missing assignment operator"))); + errmsg("malformed array literal: \"%s\"", string), + errdetail("Missing \"%s\" after array dimensions.", + ASSGN))); p += strlen(ASSGN); while (array_isspace(*p)) p++; @@ -319,18 +328,21 @@ array_in(PG_FUNCTION_ARGS) if (*p != '{') ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("array value must start with \"{\" or dimension information"))); + errmsg("malformed array literal: \"%s\"", string), + errdetail("Array contents must start with \"{\"."))); ndim_braces = ArrayCount(p, dim_braces, typdelim); if (ndim_braces != ndim) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("array dimensions incompatible with array literal"))); + 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, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("array dimensions incompatible with array literal"))); + errmsg("malformed array literal: \"%s\"", string), + errdetail("Specified array dimensions do not match array contents."))); } } @@ -460,7 +472,8 @@ ArrayCount(const char *str, int *dim, char typdelim) /* Signal a premature end of the string */ ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("malformed array literal: \"%s\"", str))); + errmsg("malformed array literal: \"%s\"", str), + errdetail("Unexpected end of input."))); break; case '\\': @@ -475,7 +488,9 @@ ArrayCount(const char *str, int *dim, char typdelim) parse_state != ARRAY_ELEM_DELIMITED) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("malformed array literal: \"%s\"", str))); + errmsg("malformed array literal: \"%s\"", str), + errdetail("Unexpected \"%c\" character.", + '\\'))); if (parse_state != ARRAY_QUOTED_ELEM_STARTED) parse_state = ARRAY_ELEM_STARTED; /* skip the escaped character */ @@ -484,7 +499,8 @@ ArrayCount(const char *str, int *dim, char typdelim) else ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("malformed array literal: \"%s\"", str))); + errmsg("malformed array literal: \"%s\"", str), + errdetail("Unexpected end of input."))); break; case '\"': @@ -498,7 +514,8 @@ ArrayCount(const char *str, int *dim, char typdelim) parse_state != ARRAY_ELEM_DELIMITED) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("malformed array literal: \"%s\"", str))); + errmsg("malformed array literal: \"%s\"", str), + errdetail("Unexpected array element."))); in_quotes = !in_quotes; if (in_quotes) parse_state = ARRAY_QUOTED_ELEM_STARTED; @@ -518,7 +535,9 @@ ArrayCount(const char *str, int *dim, char typdelim) parse_state != ARRAY_LEVEL_DELIMITED) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("malformed array literal: \"%s\"", str))); + errmsg("malformed array literal: \"%s\"", str), + errdetail("Unexpected \"%c\" character.", + '{'))); parse_state = ARRAY_LEVEL_STARTED; if (nest_level >= MAXDIM) ereport(ERROR, @@ -546,21 +565,25 @@ ArrayCount(const char *str, int *dim, char typdelim) !(nest_level == 1 && parse_state == ARRAY_LEVEL_STARTED)) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("malformed array literal: \"%s\"", str))); + errmsg("malformed array literal: \"%s\"", str), + errdetail("Unexpected \"%c\" character.", + '}'))); parse_state = ARRAY_LEVEL_COMPLETED; if (nest_level == 0) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("malformed array literal: \"%s\"", str))); + errmsg("malformed array literal: \"%s\"", str), + errdetail("Unmatched \"%c\" character.", '}'))); nest_level--; if (nelems_last[nest_level] != 0 && nelems[nest_level] != nelems_last[nest_level]) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("multidimensional arrays must have " - "array expressions with matching " - "dimensions"))); + errmsg("malformed array literal: \"%s\"", str), + errdetail("Multidimensional arrays must have " + "sub-arrays with matching " + "dimensions."))); nelems_last[nest_level] = nelems[nest_level]; nelems[nest_level] = 1; if (nest_level == 0) @@ -591,7 +614,9 @@ ArrayCount(const char *str, int *dim, char typdelim) parse_state != ARRAY_LEVEL_COMPLETED) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("malformed array literal: \"%s\"", str))); + errmsg("malformed array literal: \"%s\"", str), + errdetail("Unexpected \"%c\" character.", + typdelim))); if (parse_state == ARRAY_LEVEL_COMPLETED) parse_state = ARRAY_LEVEL_DELIMITED; else @@ -612,7 +637,8 @@ ArrayCount(const char *str, int *dim, char typdelim) parse_state != ARRAY_ELEM_DELIMITED) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("malformed array literal: \"%s\"", str))); + errmsg("malformed array literal: \"%s\"", str), + errdetail("Unexpected array element."))); parse_state = ARRAY_ELEM_STARTED; } } @@ -631,7 +657,8 @@ ArrayCount(const char *str, int *dim, char typdelim) if (!array_isspace(*ptr++)) ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("malformed array literal: \"%s\"", str))); + errmsg("malformed array literal: \"%s\"", str), + errdetail("Junk after closing right brace."))); } /* special case for an empty array */ @@ -718,7 +745,8 @@ ReadArrayStr(char *arrayStr, * character. * * The error checking in this routine is mostly pro-forma, since we expect - * that ArrayCount() already validated the string. + * that ArrayCount() already validated the string. So we don't bother + * with errdetail messages. */ srcptr = arrayStr; while (!eoArray) |