Convert contrib/intarray's bqarr_in() to report errors softly
authorAndrew Dunstan <[email protected]>
Wed, 28 Dec 2022 14:53:00 +0000 (09:53 -0500)
committerAndrew Dunstan <[email protected]>
Wed, 28 Dec 2022 15:00:12 +0000 (10:00 -0500)
Reviewed by Tom Lane and Amul Sul

Discussion: https://postgr.es/m/49e598c2-cfe8-0928-b6fb-d0cc51aab626@dunslane.net

contrib/intarray/_int_bool.c
contrib/intarray/expected/_int.out
contrib/intarray/sql/_int.sql

index 3ed88af76d777e3be65a6a188e33e24006ff266a..8fc6ad87fc7544b11ab5b10238791e903b9c8781 100644 (file)
@@ -35,6 +35,7 @@ typedef struct
        char       *buf;
        int32           state;
        int32           count;
+       struct Node *escontext;
        /* reverse polish notation in list (for temporary usage) */
        NODE       *str;
        /* number in str */
@@ -179,7 +180,7 @@ makepol(WORKSTATE *state)
                                else
                                {
                                        if (lenstack == STACKDEPTH)
-                                               ereport(ERROR,
+                                               ereturn(state->escontext, ERR,
                                                                (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
                                                                 errmsg("statement too complex")));
                                        stack[lenstack] = val;
@@ -206,10 +207,9 @@ makepol(WORKSTATE *state)
                                break;
                        case ERR:
                        default:
-                               ereport(ERROR,
+                               ereturn(state->escontext, ERR,
                                                (errcode(ERRCODE_SYNTAX_ERROR),
                                                 errmsg("syntax error")));
-                               return ERR;
                }
        }
 
@@ -483,6 +483,7 @@ bqarr_in(PG_FUNCTION_ARGS)
        ITEM       *ptr;
        NODE       *tmp;
        int32           pos = 0;
+       struct Node *escontext = fcinfo->context;
 
 #ifdef BS_DEBUG
        StringInfoData pbuf;
@@ -493,16 +494,18 @@ bqarr_in(PG_FUNCTION_ARGS)
        state.count = 0;
        state.num = 0;
        state.str = NULL;
+       state.escontext = escontext;
 
        /* make polish notation (postfix, but in reverse order) */
-       makepol(&state);
+       if (makepol(&state) == ERR)
+               PG_RETURN_NULL();
        if (!state.num)
-               ereport(ERROR,
+               ereturn(escontext, (Datum) 0,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 errmsg("empty query")));
 
        if (state.num > QUERYTYPEMAXITEMS)
-               ereport(ERROR,
+               ereturn(escontext, (Datum) 0,
                                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
                                 errmsg("number of query items (%d) exceeds the maximum allowed (%d)",
                                                state.num, (int) QUERYTYPEMAXITEMS)));
index a09d40efa17a4b71a116e1f27c6bc7a2e364a8e5..c953065a5c0f00be96a7f80e74374cb7b8fcfa4d 100644 (file)
@@ -398,6 +398,21 @@ SELECT '1&(2&(4&(5|!6)))'::query_int;
  1 & 2 & 4 & ( 5 | !6 )
 (1 row)
 
+-- test non-error-throwing input
+SELECT str as "query_int",
+       pg_input_is_valid(str,'query_int') as ok,
+       pg_input_error_message(str,'query_int') as errmsg
+FROM (VALUES ('1&(2&(4&(5|6)))'),
+             ('1#(2&(4&(5&6)))'),
+             ('foo'))
+      AS a(str);
+    query_int    | ok |    errmsg    
+-----------------+----+--------------
+ 1&(2&(4&(5|6))) | t  | 
+ 1#(2&(4&(5&6))) | f  | syntax error
+ foo             | f  | syntax error
+(3 rows)
+
 CREATE TABLE test__int( a int[] );
 \copy test__int from 'data/test__int.data'
 ANALYZE test__int;
index b26fc57e4ddfb4e7850cc7dd2a6a690143984ea9..4c9ba4c1fb92f93339a826320f9227aedfc698ca 100644 (file)
@@ -75,6 +75,17 @@ SELECT '1&2&4&5&6'::query_int;
 SELECT '1&(2&(4&(5|6)))'::query_int;
 SELECT '1&(2&(4&(5|!6)))'::query_int;
 
+-- test non-error-throwing input
+
+SELECT str as "query_int",
+       pg_input_is_valid(str,'query_int') as ok,
+       pg_input_error_message(str,'query_int') as errmsg
+FROM (VALUES ('1&(2&(4&(5|6)))'),
+             ('1#(2&(4&(5&6)))'),
+             ('foo'))
+      AS a(str);
+
+
 
 CREATE TABLE test__int( a int[] );
 \copy test__int from 'data/test__int.data'