summaryrefslogtreecommitdiff
path: root/src/test/isolation/specs/intra-grant-inplace.spec
blob: 9936d389359e5f051c94621a5ff3dad35b049485 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# GRANT's lock is the catalog tuple xmax.  GRANT doesn't acquire a heavyweight
# lock on the object undergoing an ACL change.  Inplace updates, such as
# relhasindex=true, need special code to cope.

setup
{
	CREATE TABLE intra_grant_inplace (c int);
}

teardown
{
	DROP TABLE IF EXISTS intra_grant_inplace;
}

# heap_update()
session s1
setup	{ SET deadlock_timeout = '100s'; }
step b1	{ BEGIN; }
step grant1	{
	GRANT SELECT ON intra_grant_inplace TO PUBLIC;
}
step drop1	{
	DROP TABLE intra_grant_inplace;
}
step c1	{ COMMIT; }

# inplace update
session s2
setup	{ SET deadlock_timeout = '10ms'; }
step read2	{
	SELECT relhasindex FROM pg_class
	WHERE oid = 'intra_grant_inplace'::regclass;
}
step b2		{ BEGIN; }
step addk2	{ ALTER TABLE intra_grant_inplace ADD PRIMARY KEY (c); }
step sfnku2	{
	SELECT relhasindex FROM pg_class
	WHERE oid = 'intra_grant_inplace'::regclass FOR NO KEY UPDATE;
}
step c2		{ COMMIT; }

# rowmarks
session s3
step b3		{ BEGIN ISOLATION LEVEL READ COMMITTED; }
step sfnku3	{
	SELECT relhasindex FROM pg_class
	WHERE oid = 'intra_grant_inplace'::regclass FOR NO KEY UPDATE;
}
step sfu3	{
	SELECT relhasindex FROM pg_class
	WHERE oid = 'intra_grant_inplace'::regclass FOR UPDATE;
}
step r3	{ ROLLBACK; }

# Additional heap_update()
session s4
# swallow error message to keep any OID value out of expected output
step revoke4	{
	DO $$
	BEGIN
		REVOKE SELECT ON intra_grant_inplace FROM PUBLIC;
	EXCEPTION WHEN others THEN
		RAISE WARNING 'got: %', regexp_replace(sqlerrm, '[0-9]+', 'REDACTED');
	END
	$$;
}

# Additional rowmarks
session s5
setup	{ BEGIN; }
step keyshr5	{
	SELECT relhasindex FROM pg_class
	WHERE oid = 'intra_grant_inplace'::regclass FOR KEY SHARE;
}
teardown	{ ROLLBACK; }


permutation
	b1
	grant1
	read2
	addk2(c1)	# inplace waits
	c1
	read2

# inplace thru KEY SHARE
permutation
	keyshr5
	addk2

# inplace wait NO KEY UPDATE w/ KEY SHARE
permutation
	keyshr5
	b3
	sfnku3
	addk2(r3)
	r3

# reproduce bug in DoesMultiXactIdConflict() call
permutation
	b3
	sfnku3
	keyshr5
	addk2(r3)
	r3

# same-xact rowmark
permutation
	b2
	sfnku2
	addk2
	c2

# same-xact rowmark in multixact
permutation
	keyshr5
	b2
	sfnku2
	addk2
	c2

permutation
	b3
	sfu3
	b1
	grant1(r3)	# acquire LockTuple(), await sfu3 xmax
	read2
	addk2(c1)	# block in LockTuple() behind grant1
	r3			# unblock grant1; addk2 now awaits grant1 xmax
	c1
	read2

permutation
	b2
	sfnku2
	b1
	grant1(addk2)	# acquire LockTuple(), await sfnku2 xmax
	addk2(*)		# block in LockTuple() behind grant1 = deadlock
	c2
	c1
	read2

# SearchSysCacheLocked1() calling LockRelease()
permutation
	b1
	grant1
	b3
	sfu3(c1)	# acquire LockTuple(), await grant1 xmax
	revoke4(r3)	# block in LockTuple() behind sfu3
	c1
	r3			# revoke4 unlocks old tuple and finds new

# SearchSysCacheLocked1() finding a tuple, then no tuple
permutation
	b1
	drop1
	b3
	sfu3(c1)		# acquire LockTuple(), await drop1 xmax
	revoke4(sfu3)	# block in LockTuple() behind sfu3
	c1				# sfu3 locks none; revoke4 unlocks old and finds none
	r3