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
 --