|
491 | 491 | $node_publisher->stop('fast');
|
492 | 492 | $node_subscriber->stop('fast');
|
493 | 493 |
|
| 494 | +# The bug was that when an ERROR was caught and handled by a (PL/pgSQL) |
| 495 | +# function, the apply worker reset the replication origin but continued |
| 496 | +# processing subsequent changes. So, we fail to update the replication origin |
| 497 | +# during further apply operations. This can lead to the apply worker requesting |
| 498 | +# the changes that have been applied again after restarting. |
| 499 | + |
| 500 | +$node_publisher->rotate_logfile(); |
| 501 | +$node_publisher->start(); |
| 502 | + |
| 503 | +$node_subscriber->rotate_logfile(); |
| 504 | +$node_subscriber->start(); |
| 505 | + |
| 506 | +# Set up a publication with a table |
| 507 | +$node_publisher->safe_psql( |
| 508 | + 'postgres', qq( |
| 509 | + CREATE TABLE t1 (a int); |
| 510 | + CREATE PUBLICATION regress_pub FOR TABLE t1; |
| 511 | +)); |
| 512 | + |
| 513 | +# Set up a subscription which subscribes the publication |
| 514 | +$node_subscriber->safe_psql( |
| 515 | + 'postgres', qq( |
| 516 | + CREATE TABLE t1 (a int); |
| 517 | + CREATE SUBSCRIPTION regress_sub CONNECTION '$publisher_connstr' PUBLICATION regress_pub; |
| 518 | +)); |
| 519 | + |
| 520 | +$node_subscriber->wait_for_subscription_sync($node_publisher, 'regress_sub'); |
| 521 | + |
| 522 | +# Create an AFTER INSERT trigger on the table that raises and subsequently |
| 523 | +# handles an exception. Subsequent insertions will trigger this exception, |
| 524 | +# causing the apply worker to invoke its error callback with an ERROR. However, |
| 525 | +# since the error is caught within the trigger, the apply worker will continue |
| 526 | +# processing changes. |
| 527 | +$node_subscriber->safe_psql( |
| 528 | + 'postgres', q{ |
| 529 | +CREATE FUNCTION handle_exception_trigger() |
| 530 | +RETURNS TRIGGER AS $$ |
| 531 | +BEGIN |
| 532 | + BEGIN |
| 533 | + -- Raise an exception |
| 534 | + RAISE EXCEPTION 'This is a test exception'; |
| 535 | + EXCEPTION |
| 536 | + WHEN OTHERS THEN |
| 537 | + RETURN NEW; |
| 538 | + END; |
| 539 | +
|
| 540 | + RETURN NEW; |
| 541 | +END; |
| 542 | +$$ LANGUAGE plpgsql; |
| 543 | +
|
| 544 | +CREATE TRIGGER silent_exception_trigger |
| 545 | +AFTER INSERT OR UPDATE ON t1 |
| 546 | +FOR EACH ROW |
| 547 | +EXECUTE FUNCTION handle_exception_trigger(); |
| 548 | +
|
| 549 | +ALTER TABLE t1 ENABLE ALWAYS TRIGGER silent_exception_trigger; |
| 550 | +}); |
| 551 | + |
| 552 | +# Obtain current remote_lsn value to check its advancement later |
| 553 | +my $remote_lsn = $node_subscriber->safe_psql('postgres', |
| 554 | + "SELECT remote_lsn FROM pg_replication_origin_status os, pg_subscription s WHERE os.external_id = 'pg_' || s.oid AND s.subname = 'regress_sub'" |
| 555 | +); |
| 556 | + |
| 557 | +# Insert a tuple to replicate changes |
| 558 | +$node_publisher->safe_psql('postgres', "INSERT INTO t1 VALUES (1);"); |
| 559 | +$node_publisher->wait_for_catchup('regress_sub'); |
| 560 | + |
| 561 | +# Confirms the origin can be advanced |
| 562 | +$result = $node_subscriber->safe_psql('postgres', |
| 563 | + "SELECT remote_lsn > '$remote_lsn' FROM pg_replication_origin_status os, pg_subscription s WHERE os.external_id = 'pg_' || s.oid AND s.subname = 'regress_sub'" |
| 564 | +); |
| 565 | +is($result, 't', |
| 566 | + 'remote_lsn has advanced for apply worker raising an exception'); |
| 567 | + |
| 568 | +$node_publisher->stop('fast'); |
| 569 | +$node_subscriber->stop('fast'); |
| 570 | + |
494 | 571 | done_testing();
|
0 commit comments