diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 743351b95e0abc2a570be15982ef34e3f1730a35..933c6b035c60beb17a754e2edfcab25ffc2b7c9f 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) diff --git a/src/pl/plperl/expected/plperl_array.out b/src/pl/plperl/expected/plperl_array.out index d21c84bd98a3d4ddea10d3ae2e8173ebbd33a2cc..6347b5211d27f8cedbec5b8cfc59be6c30eedcca 100644 --- a/src/pl/plperl/expected/plperl_array.out +++ b/src/pl/plperl/expected/plperl_array.out @@ -65,9 +65,10 @@ ERROR: number of array dimensions (7) exceeds the maximum allowed (6) LINE 1: select plperl_sum_array('{{{{{{{1,2},{3,4}},{{5,6},{7,8}}},{... ^ select plperl_sum_array('{{{1,2,3}, {4,5,6,7}}, {{7,8,9}, {10, 11, 12}}}'); -ERROR: multidimensional arrays must have array expressions with matching dimensions +ERROR: malformed array literal: "{{{1,2,3}, {4,5,6,7}}, {{7,8,9}, {10, 11, 12}}}" LINE 1: select plperl_sum_array('{{{1,2,3}, {4,5,6,7}}, {{7,8,9}, {1... ^ +DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions. CREATE OR REPLACE FUNCTION plperl_concat(TEXT[]) RETURNS TEXT AS $$ my $array_arg = shift; my $result = ""; diff --git a/src/test/regress/expected/arrays.out b/src/test/regress/expected/arrays.out index cb606afd9cfe47b14dba1ae5011d1f806686252e..d33c9b90fffb22d1703a4e263b15f2d3aebdf4bb 100644 --- a/src/test/regress/expected/arrays.out +++ b/src/test/regress/expected/arrays.out @@ -1065,26 +1065,32 @@ select '{{1,{2}},{2,3}}'::text[]; ERROR: malformed array literal: "{{1,{2}},{2,3}}" LINE 1: select '{{1,{2}},{2,3}}'::text[]; ^ +DETAIL: Unexpected "{" character. select '{{},{}}'::text[]; ERROR: malformed array literal: "{{},{}}" LINE 1: select '{{},{}}'::text[]; ^ +DETAIL: Unexpected "}" character. select E'{{1,2},\\{2,3}}'::text[]; ERROR: malformed array literal: "{{1,2},\{2,3}}" LINE 1: select E'{{1,2},\\{2,3}}'::text[]; ^ +DETAIL: Unexpected "\" character. select '{{"1 2" x},{3}}'::text[]; ERROR: malformed array literal: "{{"1 2" x},{3}}" LINE 1: select '{{"1 2" x},{3}}'::text[]; ^ +DETAIL: Unexpected array element. select '{}}'::text[]; ERROR: malformed array literal: "{}}" LINE 1: select '{}}'::text[]; ^ +DETAIL: Junk after closing right brace. select '{ }}'::text[]; ERROR: malformed array literal: "{ }}" LINE 1: select '{ }}'::text[]; ^ +DETAIL: Junk after closing right brace. select array[]; ERROR: cannot determine type of empty array LINE 1: select array[];