mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-03 09:16:53 +02:00
618c16707a
Since commitffa2e4670
, libpq accumulates text in conn->errorMessage across a whole query cycle. In some situations, we may report more than one error event within a cycle: the easiest case to reach is where we report a FATAL error message from the server, and then a bit later we detect loss of connection. Since, historically, each error PGresult bears the entire content of conn->errorMessage, this results in duplication of the FATAL message in any output that concatenates the contents of the PGresults. Accumulation in errorMessage still seems like a good idea, especially in view of the number of places that did ad-hoc error concatenation beforeffa2e4670
. So to fix this, let's track how much of conn->errorMessage has been read out into error PGresults, and only include new text in later PGresults. The tricky part of that is to be sure that we never discard an error PGresult once made (else we'd risk dropping some text, a problem much worse than duplication). While libpq formerly did that in some code paths, a little bit of rearrangement lets us postpone making an error PGresult at all until we are about to return it. A side benefit of that postponement is that it now becomes practical to return a dummy static PGresult in cases where we hit out-of-memory while trying to manufacture an error PGresult. This eliminates the admittedly-very-rare case where we'd return NULL from PQgetResult, indicating successful query completion, even though what actually happened was an OOM failure. Discussion: https://postgr.es/m/ab4288f8-be5c-57fb-2400-e3e857f53e46@enterprisedb.com
113 lines
2.8 KiB
Plaintext
113 lines
2.8 KiB
Plaintext
Parsed test spec with 2 sessions
|
|
|
|
starting permutation: s1_b s1_xid s2_init s1_view_slot s1_cancel_s2 s1_view_slot s1_c
|
|
step s1_b: BEGIN;
|
|
step s1_xid: SELECT 'xid' FROM txid_current();
|
|
?column?
|
|
--------
|
|
xid
|
|
(1 row)
|
|
|
|
step s2_init:
|
|
SELECT 'init' FROM pg_create_logical_replication_slot('slot_creation_error', 'test_decoding');
|
|
<waiting ...>
|
|
step s1_view_slot:
|
|
SELECT slot_name, slot_type, active FROM pg_replication_slots WHERE slot_name = 'slot_creation_error'
|
|
|
|
slot_name |slot_type|active
|
|
-------------------+---------+------
|
|
slot_creation_error|logical |t
|
|
(1 row)
|
|
|
|
step s1_cancel_s2:
|
|
SELECT pg_cancel_backend(pid)
|
|
FROM pg_stat_activity
|
|
WHERE application_name = 'isolation/slot_creation_error/s2';
|
|
|
|
pg_cancel_backend
|
|
-----------------
|
|
t
|
|
(1 row)
|
|
|
|
step s2_init: <... completed>
|
|
ERROR: canceling statement due to user request
|
|
step s1_view_slot:
|
|
SELECT slot_name, slot_type, active FROM pg_replication_slots WHERE slot_name = 'slot_creation_error'
|
|
|
|
slot_name|slot_type|active
|
|
---------+---------+------
|
|
(0 rows)
|
|
|
|
step s1_c: COMMIT;
|
|
|
|
starting permutation: s1_b s1_xid s2_init s1_c s1_view_slot s1_drop_slot
|
|
step s1_b: BEGIN;
|
|
step s1_xid: SELECT 'xid' FROM txid_current();
|
|
?column?
|
|
--------
|
|
xid
|
|
(1 row)
|
|
|
|
step s2_init:
|
|
SELECT 'init' FROM pg_create_logical_replication_slot('slot_creation_error', 'test_decoding');
|
|
<waiting ...>
|
|
step s1_c: COMMIT;
|
|
step s2_init: <... completed>
|
|
?column?
|
|
--------
|
|
init
|
|
(1 row)
|
|
|
|
step s1_view_slot:
|
|
SELECT slot_name, slot_type, active FROM pg_replication_slots WHERE slot_name = 'slot_creation_error'
|
|
|
|
slot_name |slot_type|active
|
|
-------------------+---------+------
|
|
slot_creation_error|logical |f
|
|
(1 row)
|
|
|
|
step s1_drop_slot:
|
|
SELECT pg_drop_replication_slot('slot_creation_error');
|
|
|
|
pg_drop_replication_slot
|
|
------------------------
|
|
|
|
(1 row)
|
|
|
|
|
|
starting permutation: s1_b s1_xid s2_init s1_terminate_s2 s1_c s1_view_slot
|
|
step s1_b: BEGIN;
|
|
step s1_xid: SELECT 'xid' FROM txid_current();
|
|
?column?
|
|
--------
|
|
xid
|
|
(1 row)
|
|
|
|
step s2_init:
|
|
SELECT 'init' FROM pg_create_logical_replication_slot('slot_creation_error', 'test_decoding');
|
|
<waiting ...>
|
|
step s1_terminate_s2:
|
|
SELECT pg_terminate_backend(pid)
|
|
FROM pg_stat_activity
|
|
WHERE application_name = 'isolation/slot_creation_error/s2';
|
|
|
|
pg_terminate_backend
|
|
--------------------
|
|
t
|
|
(1 row)
|
|
|
|
step s2_init: <... completed>
|
|
FATAL: terminating connection due to administrator command
|
|
server closed the connection unexpectedly
|
|
This probably means the server terminated abnormally
|
|
before or while processing the request.
|
|
|
|
step s1_c: COMMIT;
|
|
step s1_view_slot:
|
|
SELECT slot_name, slot_type, active FROM pg_replication_slots WHERE slot_name = 'slot_creation_error'
|
|
|
|
slot_name|slot_type|active
|
|
---------+---------+------
|
|
(0 rows)
|
|
|