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