Dynamic use of RAISE with USING to generate and catch non-hardcoded custom exceptions

From: mike davis <mike(dot)davis65(at)hotmail(dot)com>
To: "pgsql-general(at)postgresql(dot)org" <pgsql-general(at)postgresql(dot)org>
Subject: Dynamic use of RAISE with USING to generate and catch non-hardcoded custom exceptions
Date: 2017-09-21 23:40:48
Message-ID: HE1P190MB03950E8FB8BEC927B177533581660@HE1P190MB0395.EURP190.PROD.OUTLOOK.COM
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

I’m trying to get dynamic version of the RAISE command working so that I can use a table of custom application error messages and codes for use by all developed plpgsql functions. In this way the customer error codes and message are not hard coded into code and are defined consistently in one place in the db.

However, I cannot get a dynamic/parameterised version of the RAISE command working with the USING syntax - I want to do this so that i can catch the raised error in an EXCEPTION block.

The following example shows a example of (working) hardcoded version:

DO

$$

DECLARE

BEGIN

RAISE EXCEPTION 'Something is wrong' USING errcode = 'E0001';

EXCEPTION

WHEN SQLSTATE 'E0001' THEN

RAISE NOTICE '%','Error E0001 raised - going to do something about it';

WHEN OTHERS THEN

RAISE NOTICE 'OTHER ERRORS: %', sqlstate;

END

$$

Which raises and catches the custom error E0001 and returns (as expected)

NOTICE: Error E0001 raised - going to do something about it.

Now what I am trying to achieve is as above but for the msg text and errcode to be retrieved from a table before issuing the RAISE EXCEPTION statement.

ie. Assume v_msg and v_sqlstate have been retrieved and contain:

v_msg = 'Something is wrong’

v_sqlstate = ‘E0001’

The what I want to raise dynamically is:

RAISE EXCEPTION v_msg USING errcode = v_sqlstate;

and be able to use the same exception block as above in the hard coded example.

I searched and found a couple of similar examples where

RAISE EXCEPTION ’%’, i_msg

is used and works but this does not allow a custom SQLSTATE to be raised and trapped.

ie. The following runs ok:

DO

$$

DECLARE

v1 TEXT ;

BEGIN

v1 := 'SOMETHING IS WRONG';

RAISE NOTICE '%', v1;

RAISE EXCEPTION '%', v1;

EXCEPTION

WHEN SQLSTATE 'E0001' THEN

RAISE NOTICE '%','Error E0001 raised - going to do something about it';

WHEN OTHERS THEN

RAISE NOTICE 'OTHER ERRORS: %', sqlstate;

END

$$

and returns:

NOTICE: SOMETHING IS WRONG

NOTICE: OTHER ERRORS: P0001

but obviously the WHEN OTHERS has caught the exception and the SQLSTATE is the default P0001.

So, then what i really want is similar to the above but with the USING keyword of RAISE being dynamic/parameterised.

So i tried the following:

DO

$$

DECLARE

v_msg TEXT := '''SOMETHING IS WRONG''';

v_sqlstate TEXT := '''E0001''';

v1 TEXT ;

BEGIN

v1 := v_msg || ' USING errcode = ' || v_sqlstate;

RAISE NOTICE '%', v1;

RAISE EXCEPTION '%', v1;

EXCEPTION

WHEN SQLSTATE 'E0001' THEN

RAISE NOTICE '%','Error E0001 raised - going to do something about it';

WHEN OTHERS THEN

RAISE NOTICE 'OTHER ERRORS: %,%', sqlstate,sqlerrm;

END

$$

which returns:

NOTICE: 'SOMETHING IS WRONG' USING errcode = 'E0001'

NOTICE: OTHER ERRORS: P0001,'SOMETHING IS WRONG' USING errcode = 'E0001'

So clearly the whole of v1 (whilst syntatically correct) is treated as the message and the default sqlstate of P0001 is still raised and caught by WHEN OTHERS.

Have tried a few other things but cannot find way to get a custom errcode/sqlstate to be raised except by hardcoding it ! I’m sure there must be a way to do this!

Any help or advice on how to achieve this very much appreciated !

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Michael Paquier 2017-09-22 02:04:24 Re: Logical decoding client has the power to crash the server
Previous Message Thomas Kellerer 2017-09-21 21:29:18 Re: Performance appending to an array column