1# Tests for various bugs found over time 2use strict; 3use warnings; 4use PostgresNode; 5use TestLib; 6use Test::More tests => 3; 7 8# Bug #15114 9 10# The bug was that determining which columns are part of the replica 11# identity index using RelationGetIndexAttrBitmap() would run 12# eval_const_expressions() on index expressions and predicates across 13# all indexes of the table, which in turn might require a snapshot, 14# but there wasn't one set, so it crashes. There were actually two 15# separate bugs, one on the publisher and one on the subscriber. The 16# fix was to avoid the constant expressions simplification in 17# RelationGetIndexAttrBitmap(), so it's safe to call in more contexts. 18 19my $node_publisher = get_new_node('publisher'); 20$node_publisher->init(allows_streaming => 'logical'); 21$node_publisher->start; 22 23my $node_subscriber = get_new_node('subscriber'); 24$node_subscriber->init(allows_streaming => 'logical'); 25$node_subscriber->start; 26 27my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres'; 28 29$node_publisher->safe_psql('postgres', 30 "CREATE TABLE tab1 (a int PRIMARY KEY, b int)"); 31 32$node_publisher->safe_psql('postgres', 33 "CREATE FUNCTION double(x int) RETURNS int IMMUTABLE LANGUAGE SQL AS 'select x * 2'"); 34 35# an index with a predicate that lends itself to constant expressions 36# evaluation 37$node_publisher->safe_psql('postgres', 38 "CREATE INDEX ON tab1 (b) WHERE a > double(1)"); 39 40# and the same setup on the subscriber 41$node_subscriber->safe_psql('postgres', 42 "CREATE TABLE tab1 (a int PRIMARY KEY, b int)"); 43 44$node_subscriber->safe_psql('postgres', 45 "CREATE FUNCTION double(x int) RETURNS int IMMUTABLE LANGUAGE SQL AS 'select x * 2'"); 46 47$node_subscriber->safe_psql('postgres', 48 "CREATE INDEX ON tab1 (b) WHERE a > double(1)"); 49 50$node_publisher->safe_psql('postgres', 51 "CREATE PUBLICATION pub1 FOR ALL TABLES"); 52 53$node_subscriber->safe_psql('postgres', 54 "CREATE SUBSCRIPTION sub1 CONNECTION '$publisher_connstr application_name=sub1' PUBLICATION pub1"); 55 56$node_publisher->wait_for_catchup('sub1'); 57 58# This would crash, first on the publisher, and then (if the publisher 59# is fixed) on the subscriber. 60$node_publisher->safe_psql('postgres', 61 "INSERT INTO tab1 VALUES (1, 2)"); 62 63$node_publisher->wait_for_catchup('sub1'); 64 65pass('index predicates do not cause crash'); 66 67$node_publisher->stop('fast'); 68$node_subscriber->stop('fast'); 69 70 71# Handling of temporary and unlogged tables with FOR ALL TABLES publications 72 73# If a FOR ALL TABLES publication exists, temporary and unlogged 74# tables are ignored for publishing changes. The bug was that we 75# would still check in that case that such a table has a replica 76# identity set before accepting updates. If it did not it would cause 77# an error when an update was attempted. 78 79$node_publisher = get_new_node('publisher2'); 80$node_publisher->init(allows_streaming => 'logical'); 81$node_publisher->start; 82 83$node_publisher->safe_psql('postgres', 84 "CREATE PUBLICATION pub FOR ALL TABLES"); 85 86is( $node_publisher->psql( 87 'postgres', 88 "CREATE TEMPORARY TABLE tt1 AS SELECT 1 AS a; UPDATE tt1 SET a = 2;"), 89 0, 90 'update to temporary table without replica identity with FOR ALL TABLES publication' 91); 92 93is( $node_publisher->psql( 94 'postgres', 95 "CREATE UNLOGGED TABLE tu1 AS SELECT 1 AS a; UPDATE tu1 SET a = 2;"), 96 0, 97 'update to unlogged table without replica identity with FOR ALL TABLES publication' 98); 99 100$node_publisher->stop('fast'); 101