blob: d9b8d27fd1ffc6ed22b38832f5f99f4029e99ea3 (
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
|
# This test verifies INSERT ON CONFLICT DO UPDATE behavior concurrent with
# CREATE INDEX CONCURRENTLY a partial index.
#
# - s1: UPSERT a tuple
# - s2: UPSERT the same tuple
# - s3: CREATE UNIQUE INDEX CONCURRENTLY (with a predicate)
#
# - s4 and s5: control concurrency via injection points
setup
{
CREATE EXTENSION injection_points;
CREATE SCHEMA test;
CREATE UNLOGGED TABLE test.tbl(i int, updated_at timestamp);
CREATE UNIQUE INDEX tbl_pkey_special ON test.tbl(abs(i)) WHERE i < 1000;
ALTER TABLE test.tbl SET (parallel_workers=0);
}
teardown
{
DROP SCHEMA test CASCADE;
DROP EXTENSION injection_points;
}
session s1
setup
{
SELECT injection_points_set_local();
SELECT injection_points_attach('check-exclusion-or-unique-constraint-no-conflict', 'wait');
}
step s1_attach_invalidate_catalog_snapshot
{
SELECT injection_points_attach('invalidate-catalog-snapshot-end', 'wait');
}
step s1_start_upsert
{
INSERT INTO test.tbl VALUES(13,now()) ON CONFLICT (abs(i)) WHERE i < 100 DO UPDATE SET updated_at = now();
}
session s2
setup
{
SELECT injection_points_set_local();
SELECT injection_points_attach('exec-insert-before-insert-speculative', 'wait');
}
step s2_start_upsert
{
INSERT INTO test.tbl VALUES(13,now()) ON CONFLICT (abs(i)) WHERE i < 100 DO UPDATE SET updated_at = now();
}
session s3
setup
{
SELECT injection_points_set_local();
SELECT injection_points_attach('define-index-before-set-valid', 'wait');
}
step s3_start_create_index
{
CREATE UNIQUE INDEX CONCURRENTLY tbl_pkey_special_duplicate ON test.tbl(abs(i)) WHERE i < 10000;
}
session s4
# Step s1_attach_invalidate_catalog_snapshot sleeps or not depending on
# build conditions (CATCACHE_FORCE_RELEASE). Here we send a wakeup signal if
# it's sleeping or do nothing otherwise, and print a null value in either
# case.
step s4_wakeup_s1_setup
{
SELECT CASE WHEN
(SELECT pid FROM pg_stat_activity
WHERE wait_event_type = 'InjectionPoint' AND
wait_event = 'invalidate-catalog-snapshot-end') IS NOT NULL
THEN injection_points_wakeup('invalidate-catalog-snapshot-end')
END;
}
step s4_wakeup_s1
{
SELECT injection_points_detach('check-exclusion-or-unique-constraint-no-conflict');
SELECT injection_points_wakeup('check-exclusion-or-unique-constraint-no-conflict');
}
step s4_wakeup_s2
{
SELECT injection_points_detach('exec-insert-before-insert-speculative');
SELECT injection_points_wakeup('exec-insert-before-insert-speculative');
}
step s4_wakeup_define_index_before_set_valid
{
SELECT injection_points_detach('define-index-before-set-valid');
SELECT injection_points_wakeup('define-index-before-set-valid');
}
session s5
step s5_wakeup_s1_from_invalidate_catalog_snapshot
{
DO $$
DECLARE
v_waiting_pid INTEGER;
BEGIN
LOOP
SELECT pid INTO v_waiting_pid
FROM pg_stat_activity
WHERE wait_event_type = 'InjectionPoint'
AND wait_event = 'invalidate-catalog-snapshot-end'
LIMIT 1;
EXIT WHEN v_waiting_pid IS NOT NULL;
PERFORM pg_sleep(100);
END LOOP;
END
$$;
SELECT injection_points_detach('invalidate-catalog-snapshot-end');
SELECT injection_points_wakeup('invalidate-catalog-snapshot-end');
}
permutation
s1_attach_invalidate_catalog_snapshot
s4_wakeup_s1_setup
s3_start_create_index(s1_start_upsert, s2_start_upsert)
s1_start_upsert
s4_wakeup_define_index_before_set_valid
s2_start_upsert(s1_start_upsert)
s5_wakeup_s1_from_invalidate_catalog_snapshot
s4_wakeup_s2
s4_wakeup_s1
|