Convert contrib/isn's input functions to report errors softly

This commit is contained in:
Andrew Dunstan 2022-12-24 15:28:13 -05:00
parent e37fe1db6e
commit 720e0327bc
3 changed files with 63 additions and 44 deletions

View File

@ -260,6 +260,21 @@ SELECT '12345679'::ISSN = '9771234567003'::EAN13 AS "ok",
t | t | t t | t | t
(1 row) (1 row)
-- test non-error-throwing input API
SELECT str as isn, typ as "type",
pg_input_is_valid(str,typ) as ok,
pg_input_error_message(str,typ) as errmsg
FROM (VALUES ('9780123456786', 'UPC'),
('postgresql...','EAN13'),
('9771234567003','ISSN'))
AS a(str,typ);
isn | type | ok | errmsg
---------------+-------+----+--------------------------------------------------------
9780123456786 | UPC | f | cannot cast ISBN to UPC for number: "9780123456786"
postgresql... | EAN13 | f | invalid input syntax for EAN13 number: "postgresql..."
9771234567003 | ISSN | t |
(3 rows)
-- --
-- cleanup -- cleanup
-- --

View File

@ -675,14 +675,14 @@ eantoobig:
/* /*
* string2ean --- try to parse a string into an ean13. * string2ean --- try to parse a string into an ean13.
* *
* If errorOK is false, ereport a useful error message if the string is bad. * ereturn false with a useful error message if the string is bad.
* If errorOK is true, just return "false" for bad input. * Otherwise return true.
* *
* if the input string ends with '!' it will always be treated as invalid * if the input string ends with '!' it will always be treated as invalid
* (even if the check digit is valid) * (even if the check digit is valid)
*/ */
static bool static bool
string2ean(const char *str, bool errorOK, ean13 *result, string2ean(const char *str, struct Node *escontext, ean13 *result,
enum isn_type accept) enum isn_type accept)
{ {
bool digit, bool digit,
@ -876,48 +876,38 @@ eanbadcheck:
return true; return true;
} }
if (!errorOK)
{
if (rcheck == (unsigned) -1) if (rcheck == (unsigned) -1)
{ {
ereport(ERROR, ereturn(escontext, false,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid %s number: \"%s\"", errmsg("invalid %s number: \"%s\"",
isn_names[accept], str))); isn_names[accept], str)));
} }
else else
{ {
ereport(ERROR, ereturn(escontext, false,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid check digit for %s number: \"%s\", should be %c", errmsg("invalid check digit for %s number: \"%s\", should be %c",
isn_names[accept], str, (rcheck == 10) ? ('X') : (rcheck + '0')))); isn_names[accept], str, (rcheck == 10) ? ('X') : (rcheck + '0'))));
} }
}
return false;
eaninvalid: eaninvalid:
if (!errorOK) ereturn(escontext, false,
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for %s number: \"%s\"", errmsg("invalid input syntax for %s number: \"%s\"",
isn_names[accept], str))); isn_names[accept], str)));
return false;
eanwrongtype: eanwrongtype:
if (!errorOK) ereturn(escontext, false,
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("cannot cast %s to %s for number: \"%s\"", errmsg("cannot cast %s to %s for number: \"%s\"",
isn_names[type], isn_names[accept], str))); isn_names[type], isn_names[accept], str)));
return false;
eantoobig: eantoobig:
if (!errorOK) ereturn(escontext, false,
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("value \"%s\" is out of range for %s type", errmsg("value \"%s\" is out of range for %s type",
str, isn_names[accept]))); str, isn_names[accept])));
return false;
} }
/*---------------------------------------------------------- /*----------------------------------------------------------
@ -952,7 +942,7 @@ isn_out(PG_FUNCTION_ARGS)
char *result; char *result;
char buf[MAXEAN13LEN + 1]; char buf[MAXEAN13LEN + 1];
(void) ean2string(val, false, buf, true); (void) ean2string(val, fcinfo->context, buf, true);
result = pstrdup(buf); result = pstrdup(buf);
PG_RETURN_CSTRING(result); PG_RETURN_CSTRING(result);
@ -968,7 +958,7 @@ ean13_out(PG_FUNCTION_ARGS)
char *result; char *result;
char buf[MAXEAN13LEN + 1]; char buf[MAXEAN13LEN + 1];
(void) ean2string(val, false, buf, false); (void) ean2string(val, fcinfo->context, buf, false);
result = pstrdup(buf); result = pstrdup(buf);
PG_RETURN_CSTRING(result); PG_RETURN_CSTRING(result);
@ -983,7 +973,8 @@ ean13_in(PG_FUNCTION_ARGS)
const char *str = PG_GETARG_CSTRING(0); const char *str = PG_GETARG_CSTRING(0);
ean13 result; ean13 result;
(void) string2ean(str, false, &result, EAN13); if (!string2ean(str, fcinfo->context, &result, EAN13))
PG_RETURN_NULL();
PG_RETURN_EAN13(result); PG_RETURN_EAN13(result);
} }
@ -996,7 +987,8 @@ isbn_in(PG_FUNCTION_ARGS)
const char *str = PG_GETARG_CSTRING(0); const char *str = PG_GETARG_CSTRING(0);
ean13 result; ean13 result;
(void) string2ean(str, false, &result, ISBN); if (!string2ean(str, fcinfo->context, &result, ISBN))
PG_RETURN_NULL();
PG_RETURN_EAN13(result); PG_RETURN_EAN13(result);
} }
@ -1009,7 +1001,8 @@ ismn_in(PG_FUNCTION_ARGS)
const char *str = PG_GETARG_CSTRING(0); const char *str = PG_GETARG_CSTRING(0);
ean13 result; ean13 result;
(void) string2ean(str, false, &result, ISMN); if (!string2ean(str, fcinfo->context, &result, ISMN))
PG_RETURN_NULL();
PG_RETURN_EAN13(result); PG_RETURN_EAN13(result);
} }
@ -1022,7 +1015,8 @@ issn_in(PG_FUNCTION_ARGS)
const char *str = PG_GETARG_CSTRING(0); const char *str = PG_GETARG_CSTRING(0);
ean13 result; ean13 result;
(void) string2ean(str, false, &result, ISSN); if (!string2ean(str, fcinfo->context, &result, ISSN))
PG_RETURN_NULL();
PG_RETURN_EAN13(result); PG_RETURN_EAN13(result);
} }
@ -1035,7 +1029,8 @@ upc_in(PG_FUNCTION_ARGS)
const char *str = PG_GETARG_CSTRING(0); const char *str = PG_GETARG_CSTRING(0);
ean13 result; ean13 result;
(void) string2ean(str, false, &result, UPC); if (!string2ean(str, fcinfo->context, &result, UPC))
PG_RETURN_NULL();
PG_RETURN_EAN13(result); PG_RETURN_EAN13(result);
} }

View File

@ -107,6 +107,15 @@ SELECT '12345679'::ISSN = '9771234567003'::EAN13 AS "ok",
'M-1234-5678-5'::ISMN = '9790123456785'::EAN13 AS "ok", 'M-1234-5678-5'::ISMN = '9790123456785'::EAN13 AS "ok",
'9791234567896'::EAN13 != '123456789X'::ISBN AS "nope"; '9791234567896'::EAN13 != '123456789X'::ISBN AS "nope";
-- test non-error-throwing input API
SELECT str as isn, typ as "type",
pg_input_is_valid(str,typ) as ok,
pg_input_error_message(str,typ) as errmsg
FROM (VALUES ('9780123456786', 'UPC'),
('postgresql...','EAN13'),
('9771234567003','ISSN'))
AS a(str,typ);
-- --
-- cleanup -- cleanup
-- --