diff --git a/contrib/isn/expected/isn.out b/contrib/isn/expected/isn.out index 18fe37a82c..72171b2790 100644 --- a/contrib/isn/expected/isn.out +++ b/contrib/isn/expected/isn.out @@ -260,6 +260,21 @@ SELECT '12345679'::ISSN = '9771234567003'::EAN13 AS "ok", t | t | t (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 -- diff --git a/contrib/isn/isn.c b/contrib/isn/isn.c index a53d99722a..a86db045de 100644 --- a/contrib/isn/isn.c +++ b/contrib/isn/isn.c @@ -675,14 +675,14 @@ eantoobig: /* * string2ean --- try to parse a string into an ean13. * - * If errorOK is false, ereport a useful error message if the string is bad. - * If errorOK is true, just return "false" for bad input. + * ereturn false with a useful error message if the string is bad. + * Otherwise return true. * * if the input string ends with '!' it will always be treated as invalid * (even if the check digit is valid) */ static bool -string2ean(const char *str, bool errorOK, ean13 *result, +string2ean(const char *str, struct Node *escontext, ean13 *result, enum isn_type accept) { bool digit, @@ -876,48 +876,38 @@ eanbadcheck: return true; } - if (!errorOK) + if (rcheck == (unsigned) -1) { - if (rcheck == (unsigned) -1) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid %s number: \"%s\"", - isn_names[accept], str))); - } - else - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid check digit for %s number: \"%s\", should be %c", - isn_names[accept], str, (rcheck == 10) ? ('X') : (rcheck + '0')))); - } + ereturn(escontext, false, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid %s number: \"%s\"", + isn_names[accept], str))); + } + else + { + ereturn(escontext, false, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid check digit for %s number: \"%s\", should be %c", + isn_names[accept], str, (rcheck == 10) ? ('X') : (rcheck + '0')))); } - return false; eaninvalid: - if (!errorOK) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("invalid input syntax for %s number: \"%s\"", - isn_names[accept], str))); - return false; + ereturn(escontext, false, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("invalid input syntax for %s number: \"%s\"", + isn_names[accept], str))); eanwrongtype: - if (!errorOK) - ereport(ERROR, - (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), - errmsg("cannot cast %s to %s for number: \"%s\"", - isn_names[type], isn_names[accept], str))); - return false; + ereturn(escontext, false, + (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), + errmsg("cannot cast %s to %s for number: \"%s\"", + isn_names[type], isn_names[accept], str))); eantoobig: - if (!errorOK) - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("value \"%s\" is out of range for %s type", - str, isn_names[accept]))); - return false; + ereturn(escontext, false, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("value \"%s\" is out of range for %s type", + str, isn_names[accept]))); } /*---------------------------------------------------------- @@ -952,7 +942,7 @@ isn_out(PG_FUNCTION_ARGS) char *result; char buf[MAXEAN13LEN + 1]; - (void) ean2string(val, false, buf, true); + (void) ean2string(val, fcinfo->context, buf, true); result = pstrdup(buf); PG_RETURN_CSTRING(result); @@ -968,7 +958,7 @@ ean13_out(PG_FUNCTION_ARGS) char *result; char buf[MAXEAN13LEN + 1]; - (void) ean2string(val, false, buf, false); + (void) ean2string(val, fcinfo->context, buf, false); result = pstrdup(buf); PG_RETURN_CSTRING(result); @@ -983,7 +973,8 @@ ean13_in(PG_FUNCTION_ARGS) const char *str = PG_GETARG_CSTRING(0); ean13 result; - (void) string2ean(str, false, &result, EAN13); + if (!string2ean(str, fcinfo->context, &result, EAN13)) + PG_RETURN_NULL(); PG_RETURN_EAN13(result); } @@ -996,7 +987,8 @@ isbn_in(PG_FUNCTION_ARGS) const char *str = PG_GETARG_CSTRING(0); ean13 result; - (void) string2ean(str, false, &result, ISBN); + if (!string2ean(str, fcinfo->context, &result, ISBN)) + PG_RETURN_NULL(); PG_RETURN_EAN13(result); } @@ -1009,7 +1001,8 @@ ismn_in(PG_FUNCTION_ARGS) const char *str = PG_GETARG_CSTRING(0); ean13 result; - (void) string2ean(str, false, &result, ISMN); + if (!string2ean(str, fcinfo->context, &result, ISMN)) + PG_RETURN_NULL(); PG_RETURN_EAN13(result); } @@ -1022,7 +1015,8 @@ issn_in(PG_FUNCTION_ARGS) const char *str = PG_GETARG_CSTRING(0); ean13 result; - (void) string2ean(str, false, &result, ISSN); + if (!string2ean(str, fcinfo->context, &result, ISSN)) + PG_RETURN_NULL(); PG_RETURN_EAN13(result); } @@ -1035,7 +1029,8 @@ upc_in(PG_FUNCTION_ARGS) const char *str = PG_GETARG_CSTRING(0); ean13 result; - (void) string2ean(str, false, &result, UPC); + if (!string2ean(str, fcinfo->context, &result, UPC)) + PG_RETURN_NULL(); PG_RETURN_EAN13(result); } diff --git a/contrib/isn/sql/isn.sql b/contrib/isn/sql/isn.sql index 71577d5590..6426cb42a0 100644 --- a/contrib/isn/sql/isn.sql +++ b/contrib/isn/sql/isn.sql @@ -107,6 +107,15 @@ SELECT '12345679'::ISSN = '9771234567003'::EAN13 AS "ok", 'M-1234-5678-5'::ISMN = '9790123456785'::EAN13 AS "ok", '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 --