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.
This commit is contained in:
parent
0fd38e1370
commit
475aedd1ef
@ -247,11 +247,13 @@ array_in(PG_FUNCTION_ARGS)
|
|||||||
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
|
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
|
||||||
ndim + 1, MAXDIM)));
|
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? */
|
if (q == p) /* no digits? */
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("missing dimension value")));
|
errmsg("malformed array literal: \"%s\"", string),
|
||||||
|
errdetail("\"[\" must introduce explicitly-specified array dimensions.")));
|
||||||
|
|
||||||
if (*q == ':')
|
if (*q == ':')
|
||||||
{
|
{
|
||||||
@ -259,11 +261,13 @@ array_in(PG_FUNCTION_ARGS)
|
|||||||
*q = '\0';
|
*q = '\0';
|
||||||
lBound[ndim] = atoi(p);
|
lBound[ndim] = atoi(p);
|
||||||
p = q + 1;
|
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? */
|
if (q == p) /* no digits? */
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("missing dimension value")));
|
errmsg("malformed array literal: \"%s\"", string),
|
||||||
|
errdetail("Missing array dimension value.")));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -273,7 +277,9 @@ array_in(PG_FUNCTION_ARGS)
|
|||||||
if (*q != ']')
|
if (*q != ']')
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("missing \"]\" in array dimensions")));
|
errmsg("malformed array literal: \"%s\"", string),
|
||||||
|
errdetail("Missing \"%s\" after array dimensions.",
|
||||||
|
"]")));
|
||||||
|
|
||||||
*q = '\0';
|
*q = '\0';
|
||||||
ub = atoi(p);
|
ub = atoi(p);
|
||||||
@ -293,7 +299,8 @@ array_in(PG_FUNCTION_ARGS)
|
|||||||
if (*p != '{')
|
if (*p != '{')
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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);
|
ndim = ArrayCount(p, dim, typdelim);
|
||||||
for (i = 0; i < ndim; i++)
|
for (i = 0; i < ndim; i++)
|
||||||
lBound[i] = 1;
|
lBound[i] = 1;
|
||||||
@ -307,7 +314,9 @@ array_in(PG_FUNCTION_ARGS)
|
|||||||
if (strncmp(p, ASSGN, strlen(ASSGN)) != 0)
|
if (strncmp(p, ASSGN, strlen(ASSGN)) != 0)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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);
|
p += strlen(ASSGN);
|
||||||
while (array_isspace(*p))
|
while (array_isspace(*p))
|
||||||
p++;
|
p++;
|
||||||
@ -319,18 +328,21 @@ array_in(PG_FUNCTION_ARGS)
|
|||||||
if (*p != '{')
|
if (*p != '{')
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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);
|
ndim_braces = ArrayCount(p, dim_braces, typdelim);
|
||||||
if (ndim_braces != ndim)
|
if (ndim_braces != ndim)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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)
|
for (i = 0; i < ndim; ++i)
|
||||||
{
|
{
|
||||||
if (dim[i] != dim_braces[i])
|
if (dim[i] != dim_braces[i])
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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 */
|
/* Signal a premature end of the string */
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("malformed array literal: \"%s\"", str)));
|
errmsg("malformed array literal: \"%s\"", str),
|
||||||
|
errdetail("Unexpected end of input.")));
|
||||||
break;
|
break;
|
||||||
case '\\':
|
case '\\':
|
||||||
|
|
||||||
@ -475,7 +488,9 @@ ArrayCount(const char *str, int *dim, char typdelim)
|
|||||||
parse_state != ARRAY_ELEM_DELIMITED)
|
parse_state != ARRAY_ELEM_DELIMITED)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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)
|
if (parse_state != ARRAY_QUOTED_ELEM_STARTED)
|
||||||
parse_state = ARRAY_ELEM_STARTED;
|
parse_state = ARRAY_ELEM_STARTED;
|
||||||
/* skip the escaped character */
|
/* skip the escaped character */
|
||||||
@ -484,7 +499,8 @@ ArrayCount(const char *str, int *dim, char typdelim)
|
|||||||
else
|
else
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("malformed array literal: \"%s\"", str)));
|
errmsg("malformed array literal: \"%s\"", str),
|
||||||
|
errdetail("Unexpected end of input.")));
|
||||||
break;
|
break;
|
||||||
case '\"':
|
case '\"':
|
||||||
|
|
||||||
@ -498,7 +514,8 @@ ArrayCount(const char *str, int *dim, char typdelim)
|
|||||||
parse_state != ARRAY_ELEM_DELIMITED)
|
parse_state != ARRAY_ELEM_DELIMITED)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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;
|
in_quotes = !in_quotes;
|
||||||
if (in_quotes)
|
if (in_quotes)
|
||||||
parse_state = ARRAY_QUOTED_ELEM_STARTED;
|
parse_state = ARRAY_QUOTED_ELEM_STARTED;
|
||||||
@ -518,7 +535,9 @@ ArrayCount(const char *str, int *dim, char typdelim)
|
|||||||
parse_state != ARRAY_LEVEL_DELIMITED)
|
parse_state != ARRAY_LEVEL_DELIMITED)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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;
|
parse_state = ARRAY_LEVEL_STARTED;
|
||||||
if (nest_level >= MAXDIM)
|
if (nest_level >= MAXDIM)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -546,21 +565,25 @@ ArrayCount(const char *str, int *dim, char typdelim)
|
|||||||
!(nest_level == 1 && parse_state == ARRAY_LEVEL_STARTED))
|
!(nest_level == 1 && parse_state == ARRAY_LEVEL_STARTED))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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;
|
parse_state = ARRAY_LEVEL_COMPLETED;
|
||||||
if (nest_level == 0)
|
if (nest_level == 0)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("malformed array literal: \"%s\"", str)));
|
errmsg("malformed array literal: \"%s\"", str),
|
||||||
|
errdetail("Unmatched \"%c\" character.", '}')));
|
||||||
nest_level--;
|
nest_level--;
|
||||||
|
|
||||||
if (nelems_last[nest_level] != 0 &&
|
if (nelems_last[nest_level] != 0 &&
|
||||||
nelems[nest_level] != nelems_last[nest_level])
|
nelems[nest_level] != nelems_last[nest_level])
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("multidimensional arrays must have "
|
errmsg("malformed array literal: \"%s\"", str),
|
||||||
"array expressions with matching "
|
errdetail("Multidimensional arrays must have "
|
||||||
"dimensions")));
|
"sub-arrays with matching "
|
||||||
|
"dimensions.")));
|
||||||
nelems_last[nest_level] = nelems[nest_level];
|
nelems_last[nest_level] = nelems[nest_level];
|
||||||
nelems[nest_level] = 1;
|
nelems[nest_level] = 1;
|
||||||
if (nest_level == 0)
|
if (nest_level == 0)
|
||||||
@ -591,7 +614,9 @@ ArrayCount(const char *str, int *dim, char typdelim)
|
|||||||
parse_state != ARRAY_LEVEL_COMPLETED)
|
parse_state != ARRAY_LEVEL_COMPLETED)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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)
|
if (parse_state == ARRAY_LEVEL_COMPLETED)
|
||||||
parse_state = ARRAY_LEVEL_DELIMITED;
|
parse_state = ARRAY_LEVEL_DELIMITED;
|
||||||
else
|
else
|
||||||
@ -612,7 +637,8 @@ ArrayCount(const char *str, int *dim, char typdelim)
|
|||||||
parse_state != ARRAY_ELEM_DELIMITED)
|
parse_state != ARRAY_ELEM_DELIMITED)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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;
|
parse_state = ARRAY_ELEM_STARTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -631,7 +657,8 @@ ArrayCount(const char *str, int *dim, char typdelim)
|
|||||||
if (!array_isspace(*ptr++))
|
if (!array_isspace(*ptr++))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(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 */
|
/* special case for an empty array */
|
||||||
@ -718,7 +745,8 @@ ReadArrayStr(char *arrayStr,
|
|||||||
* character.
|
* character.
|
||||||
*
|
*
|
||||||
* The error checking in this routine is mostly pro-forma, since we expect
|
* 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;
|
srcptr = arrayStr;
|
||||||
while (!eoArray)
|
while (!eoArray)
|
||||||
|
@ -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}}},{...
|
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}}}');
|
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...
|
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 $$
|
CREATE OR REPLACE FUNCTION plperl_concat(TEXT[]) RETURNS TEXT AS $$
|
||||||
my $array_arg = shift;
|
my $array_arg = shift;
|
||||||
my $result = "";
|
my $result = "";
|
||||||
|
@ -1065,26 +1065,32 @@ select '{{1,{2}},{2,3}}'::text[];
|
|||||||
ERROR: malformed array literal: "{{1,{2}},{2,3}}"
|
ERROR: malformed array literal: "{{1,{2}},{2,3}}"
|
||||||
LINE 1: select '{{1,{2}},{2,3}}'::text[];
|
LINE 1: select '{{1,{2}},{2,3}}'::text[];
|
||||||
^
|
^
|
||||||
|
DETAIL: Unexpected "{" character.
|
||||||
select '{{},{}}'::text[];
|
select '{{},{}}'::text[];
|
||||||
ERROR: malformed array literal: "{{},{}}"
|
ERROR: malformed array literal: "{{},{}}"
|
||||||
LINE 1: select '{{},{}}'::text[];
|
LINE 1: select '{{},{}}'::text[];
|
||||||
^
|
^
|
||||||
|
DETAIL: Unexpected "}" character.
|
||||||
select E'{{1,2},\\{2,3}}'::text[];
|
select E'{{1,2},\\{2,3}}'::text[];
|
||||||
ERROR: malformed array literal: "{{1,2},\{2,3}}"
|
ERROR: malformed array literal: "{{1,2},\{2,3}}"
|
||||||
LINE 1: select E'{{1,2},\\{2,3}}'::text[];
|
LINE 1: select E'{{1,2},\\{2,3}}'::text[];
|
||||||
^
|
^
|
||||||
|
DETAIL: Unexpected "\" character.
|
||||||
select '{{"1 2" x},{3}}'::text[];
|
select '{{"1 2" x},{3}}'::text[];
|
||||||
ERROR: malformed array literal: "{{"1 2" x},{3}}"
|
ERROR: malformed array literal: "{{"1 2" x},{3}}"
|
||||||
LINE 1: select '{{"1 2" x},{3}}'::text[];
|
LINE 1: select '{{"1 2" x},{3}}'::text[];
|
||||||
^
|
^
|
||||||
|
DETAIL: Unexpected array element.
|
||||||
select '{}}'::text[];
|
select '{}}'::text[];
|
||||||
ERROR: malformed array literal: "{}}"
|
ERROR: malformed array literal: "{}}"
|
||||||
LINE 1: select '{}}'::text[];
|
LINE 1: select '{}}'::text[];
|
||||||
^
|
^
|
||||||
|
DETAIL: Junk after closing right brace.
|
||||||
select '{ }}'::text[];
|
select '{ }}'::text[];
|
||||||
ERROR: malformed array literal: "{ }}"
|
ERROR: malformed array literal: "{ }}"
|
||||||
LINE 1: select '{ }}'::text[];
|
LINE 1: select '{ }}'::text[];
|
||||||
^
|
^
|
||||||
|
DETAIL: Junk after closing right brace.
|
||||||
select array[];
|
select array[];
|
||||||
ERROR: cannot determine type of empty array
|
ERROR: cannot determine type of empty array
|
||||||
LINE 1: select array[];
|
LINE 1: select array[];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user