Re: jsonb_set() strictness considered harmful to data
От | Adrian Klaver |
---|---|
Тема | Re: jsonb_set() strictness considered harmful to data |
Дата | |
Msg-id | 3a866bdd-8a04-c428-9f77-9768c04ceae6@aklaver.com обсуждение исходный текст |
Ответ на | Re: jsonb_set() strictness considered harmful to data (Tomas Vondra <tomas.vondra@2ndquadrant.com>) |
Список | pgsql-general |
On 10/21/19 12:50 PM, Tomas Vondra wrote: > On Mon, Oct 21, 2019 at 08:06:46AM -0700, Adrian Klaver wrote: >> On 10/20/19 11:07 PM, Tomas Vondra wrote: >>> On Sun, Oct 20, 2019 at 06:51:05PM -0400, Andrew Dunstan wrote: >> >>> >>> True. And AFAIK catching exceptions is not really possible in some code, >>> e.g. in stored procedures (because we can't do subtransactions, so no >>> exception blocks). >>> >> >> Can you explain the above to me as I thought there are exception >> blocks in stored functions and now sub-transactions in stored procedures. >> > > Sorry for the confusion - I've not been particularly careful when > writing that response. > > Let me illustrate the issue with this example: > > CREATE TABLE t (a int); > > CREATE OR REPLACE PROCEDURE test() LANGUAGE plpgsql AS $$ > DECLARE > msg TEXT; > BEGIN > -- SAVEPOINT s1; > INSERT INTO t VALUES (1); > -- COMMIT; > EXCEPTION > WHEN others THEN > msg := SUBSTR(SQLERRM, 1, 100); > RAISE NOTICE 'error: %', msg; > END; $$; > > CALL test(); > > If you uncomment the SAVEPOINT, you get > > NOTICE: error: unsupported transaction command in PL/pgSQL > > because savepoints are not allowed in stored procedures. Fine. > > If you uncomment the COMMIT, you get > > NOTICE: error: cannot commit while a subtransaction is active > > which happens because the EXCEPTION block creates a subtransaction, and > we can't commit when it's active. > > But we can commit outside the exception block: > > CREATE OR REPLACE PROCEDURE test() LANGUAGE plpgsql AS $$ > DECLARE > msg TEXT; > BEGIN > BEGIN > INSERT INTO t VALUES (1); > EXCEPTION > WHEN others THEN > msg := SUBSTR(SQLERRM, 1, 100); > RAISE NOTICE 'error: %', msg; > END; > COMMIT; > END; $$; You can do something like the below though: CREATE TABLE t (a int PRIMARY KEY); CREATE OR REPLACE PROCEDURE public.test() LANGUAGE plpgsql AS $procedure$ DECLARE msg TEXT; BEGIN BEGIN INSERT INTO t VALUES (1); EXCEPTION WHEN others THEN msg := SUBSTR(SQLERRM, 1, 100); RAISE NOTICE 'error: %', msg; UPDATE t set a = 2; END; COMMIT; END; $procedure$ test_(postgres)# CALL test(); CALL test_(postgres)# select * from t; a --- 1 (1 row) test_(postgres)# CALL test(); NOTICE: error: duplicate key value violates unique constraint "t_pkey" CALL test_(postgres)# select * from t; a --- 2 (1 row) > > > regards > -- Adrian Klaver adrian.klaver@aklaver.com
В списке pgsql-general по дате отправления: