Convert contrib/isn's input functions to report errors softly
authorAndrew Dunstan <andrew@dunslane.net>
Sat, 24 Dec 2022 20:28:13 +0000 (15:28 -0500)
committerAndrew Dunstan <andrew@dunslane.net>
Sat, 24 Dec 2022 20:28:13 +0000 (15:28 -0500)
contrib/isn/expected/isn.out
contrib/isn/isn.c
contrib/isn/sql/isn.sql

index 18fe37a82c3bc496c51f0c60821d42cb39ef46db..72171b2790e6f060529c201479b71598d4ff2d72 100644 (file)
@@ -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
 --
index a53d99722ad4220c29287055d489e6e8e4585eb9..a86db045dec1e1652952cb8baae8b15a54d67253 100644 (file)
@@ -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);
 }
 
index 71577d5590f8703638e49f116e6d81acc3d9e28f..6426cb42a0f5d8d2eadf50391984271b344f2abe 100644 (file)
@@ -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
 --