Skip to content

Commit 2910fc8

Browse files
committed
Update extensions with GIN/GIST support for parallel query.
Commit 749a787 bumped the extension version on all of these extensions already, and we haven't had a release since then, so we can make further changes without bumping the extension version again. Take this opportunity to mark all of the functions exported by these modules PARALLEL SAFE -- except for pg_trgm's set_limit(). Mark that one PARALLEL RESTRICTED, because it makes a persistent change to a GUC value. Note that some of the markings added by this commit don't have any effect; for example, gseg_picksplit() isn't likely to be mentioned explicitly in a query and therefore it's parallel-safety marking will never be consulted. But this commit just marks everything for consistency: if it were somehow used in a query, that would be fine as far as parallel query is concerned, since it does not consult any backend-private state, attempt to write data, etc. Andreas Karlsson, with a few revisions by me.
1 parent 131c7e7 commit 2910fc8

12 files changed

+553
-274
lines changed

contrib/cube/cube--1.1--1.2.sql

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,44 @@ FROM (VALUES
1717
('g_cube_distance(internal,cube,smallint,oid)', '{internal,cube,smallint,oid,internal}')
1818
) AS update_data (oldproc, newtypes)
1919
WHERE oid = pg_catalog.to_regprocedure(oldproc);
20+
21+
ALTER FUNCTION cube_in(cstring) PARALLEL SAFE;
22+
ALTER FUNCTION cube(float8[], float8[]) PARALLEL SAFE;
23+
ALTER FUNCTION cube(float8[]) PARALLEL SAFE;
24+
ALTER FUNCTION cube_out(cube) PARALLEL SAFE;
25+
ALTER FUNCTION cube_eq(cube, cube) PARALLEL SAFE;
26+
ALTER FUNCTION cube_ne(cube, cube) PARALLEL SAFE;
27+
ALTER FUNCTION cube_lt(cube, cube) PARALLEL SAFE;
28+
ALTER FUNCTION cube_gt(cube, cube) PARALLEL SAFE;
29+
ALTER FUNCTION cube_le(cube, cube) PARALLEL SAFE;
30+
ALTER FUNCTION cube_ge(cube, cube) PARALLEL SAFE;
31+
ALTER FUNCTION cube_cmp(cube, cube) PARALLEL SAFE;
32+
ALTER FUNCTION cube_contains(cube, cube) PARALLEL SAFE;
33+
ALTER FUNCTION cube_contained(cube, cube) PARALLEL SAFE;
34+
ALTER FUNCTION cube_overlap(cube, cube) PARALLEL SAFE;
35+
ALTER FUNCTION cube_union(cube, cube) PARALLEL SAFE;
36+
ALTER FUNCTION cube_inter(cube, cube) PARALLEL SAFE;
37+
ALTER FUNCTION cube_size(cube) PARALLEL SAFE;
38+
ALTER FUNCTION cube_subset(cube, int4[]) PARALLEL SAFE;
39+
ALTER FUNCTION cube_distance(cube, cube) PARALLEL SAFE;
40+
ALTER FUNCTION distance_chebyshev(cube, cube) PARALLEL SAFE;
41+
ALTER FUNCTION distance_taxicab(cube, cube) PARALLEL SAFE;
42+
ALTER FUNCTION cube_dim(cube) PARALLEL SAFE;
43+
ALTER FUNCTION cube_ll_coord(cube, int4) PARALLEL SAFE;
44+
ALTER FUNCTION cube_ur_coord(cube, int4) PARALLEL SAFE;
45+
ALTER FUNCTION cube_coord(cube, int4) PARALLEL SAFE;
46+
ALTER FUNCTION cube_coord_llur(cube, int4) PARALLEL SAFE;
47+
ALTER FUNCTION cube(float8) PARALLEL SAFE;
48+
ALTER FUNCTION cube(float8, float8) PARALLEL SAFE;
49+
ALTER FUNCTION cube(cube, float8) PARALLEL SAFE;
50+
ALTER FUNCTION cube(cube, float8, float8) PARALLEL SAFE;
51+
ALTER FUNCTION cube_is_point(cube) PARALLEL SAFE;
52+
ALTER FUNCTION cube_enlarge(cube, float8, int4) PARALLEL SAFE;
53+
ALTER FUNCTION g_cube_consistent(internal, cube, smallint, oid, internal) PARALLEL SAFE;
54+
ALTER FUNCTION g_cube_compress(internal) PARALLEL SAFE;
55+
ALTER FUNCTION g_cube_decompress(internal) PARALLEL SAFE;
56+
ALTER FUNCTION g_cube_penalty(internal, internal, internal) PARALLEL SAFE;
57+
ALTER FUNCTION g_cube_picksplit(internal, internal) PARALLEL SAFE;
58+
ALTER FUNCTION g_cube_union(internal, internal) PARALLEL SAFE;
59+
ALTER FUNCTION g_cube_same(cube, cube, internal) PARALLEL SAFE;
60+
ALTER FUNCTION g_cube_distance(internal, cube, smallint, oid, internal) PARALLEL SAFE;

contrib/cube/cube--1.2.sql

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,20 @@
88
CREATE FUNCTION cube_in(cstring)
99
RETURNS cube
1010
AS 'MODULE_PATHNAME'
11-
LANGUAGE C IMMUTABLE STRICT;
11+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
1212

1313
CREATE FUNCTION cube(float8[], float8[]) RETURNS cube
1414
AS 'MODULE_PATHNAME', 'cube_a_f8_f8'
15-
LANGUAGE C IMMUTABLE STRICT;
15+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
1616

1717
CREATE FUNCTION cube(float8[]) RETURNS cube
1818
AS 'MODULE_PATHNAME', 'cube_a_f8'
19-
LANGUAGE C IMMUTABLE STRICT;
19+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
2020

2121
CREATE FUNCTION cube_out(cube)
2222
RETURNS cstring
2323
AS 'MODULE_PATHNAME'
24-
LANGUAGE C IMMUTABLE STRICT;
24+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
2525

2626
CREATE TYPE cube (
2727
INTERNALLENGTH = variable,
@@ -41,70 +41,70 @@ COMMENT ON TYPE cube IS 'multi-dimensional cube ''(FLOAT-1, FLOAT-2, ..., FLOAT-
4141
CREATE FUNCTION cube_eq(cube, cube)
4242
RETURNS bool
4343
AS 'MODULE_PATHNAME'
44-
LANGUAGE C IMMUTABLE STRICT;
44+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
4545

4646
COMMENT ON FUNCTION cube_eq(cube, cube) IS 'same as';
4747

4848
CREATE FUNCTION cube_ne(cube, cube)
4949
RETURNS bool
5050
AS 'MODULE_PATHNAME'
51-
LANGUAGE C IMMUTABLE STRICT;
51+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
5252

5353
COMMENT ON FUNCTION cube_ne(cube, cube) IS 'different';
5454

5555
CREATE FUNCTION cube_lt(cube, cube)
5656
RETURNS bool
5757
AS 'MODULE_PATHNAME'
58-
LANGUAGE C IMMUTABLE STRICT;
58+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
5959

6060
COMMENT ON FUNCTION cube_lt(cube, cube) IS 'lower than';
6161

6262
CREATE FUNCTION cube_gt(cube, cube)
6363
RETURNS bool
6464
AS 'MODULE_PATHNAME'
65-
LANGUAGE C IMMUTABLE STRICT;
65+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
6666

6767
COMMENT ON FUNCTION cube_gt(cube, cube) IS 'greater than';
6868

6969
CREATE FUNCTION cube_le(cube, cube)
7070
RETURNS bool
7171
AS 'MODULE_PATHNAME'
72-
LANGUAGE C IMMUTABLE STRICT;
72+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
7373

7474
COMMENT ON FUNCTION cube_le(cube, cube) IS 'lower than or equal to';
7575

7676
CREATE FUNCTION cube_ge(cube, cube)
7777
RETURNS bool
7878
AS 'MODULE_PATHNAME'
79-
LANGUAGE C IMMUTABLE STRICT;
79+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
8080

8181
COMMENT ON FUNCTION cube_ge(cube, cube) IS 'greater than or equal to';
8282

8383
CREATE FUNCTION cube_cmp(cube, cube)
8484
RETURNS int4
8585
AS 'MODULE_PATHNAME'
86-
LANGUAGE C IMMUTABLE STRICT;
86+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
8787

8888
COMMENT ON FUNCTION cube_cmp(cube, cube) IS 'btree comparison function';
8989

9090
CREATE FUNCTION cube_contains(cube, cube)
9191
RETURNS bool
9292
AS 'MODULE_PATHNAME'
93-
LANGUAGE C IMMUTABLE STRICT;
93+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
9494

9595
COMMENT ON FUNCTION cube_contains(cube, cube) IS 'contains';
9696

9797
CREATE FUNCTION cube_contained(cube, cube)
9898
RETURNS bool
9999
AS 'MODULE_PATHNAME'
100-
LANGUAGE C IMMUTABLE STRICT;
100+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
101101

102102
COMMENT ON FUNCTION cube_contained(cube, cube) IS 'contained in';
103103

104104
CREATE FUNCTION cube_overlap(cube, cube)
105105
RETURNS bool
106106
AS 'MODULE_PATHNAME'
107-
LANGUAGE C IMMUTABLE STRICT;
107+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
108108

109109
COMMENT ON FUNCTION cube_overlap(cube, cube) IS 'overlaps';
110110

@@ -113,99 +113,99 @@ COMMENT ON FUNCTION cube_overlap(cube, cube) IS 'overlaps';
113113
CREATE FUNCTION cube_union(cube, cube)
114114
RETURNS cube
115115
AS 'MODULE_PATHNAME'
116-
LANGUAGE C IMMUTABLE STRICT;
116+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
117117

118118
CREATE FUNCTION cube_inter(cube, cube)
119119
RETURNS cube
120120
AS 'MODULE_PATHNAME'
121-
LANGUAGE C IMMUTABLE STRICT;
121+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
122122

123123
CREATE FUNCTION cube_size(cube)
124124
RETURNS float8
125125
AS 'MODULE_PATHNAME'
126-
LANGUAGE C IMMUTABLE STRICT;
126+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
127127

128128

129129
-- Misc N-dimensional functions
130130

131131
CREATE FUNCTION cube_subset(cube, int4[])
132132
RETURNS cube
133133
AS 'MODULE_PATHNAME'
134-
LANGUAGE C IMMUTABLE STRICT;
134+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
135135

136136
-- proximity routines
137137

138138
CREATE FUNCTION cube_distance(cube, cube)
139139
RETURNS float8
140140
AS 'MODULE_PATHNAME'
141-
LANGUAGE C IMMUTABLE STRICT;
141+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
142142

143143
CREATE FUNCTION distance_chebyshev(cube, cube)
144144
RETURNS float8
145145
AS 'MODULE_PATHNAME'
146-
LANGUAGE C IMMUTABLE STRICT;
146+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
147147

148148
CREATE FUNCTION distance_taxicab(cube, cube)
149149
RETURNS float8
150150
AS 'MODULE_PATHNAME'
151-
LANGUAGE C IMMUTABLE STRICT;
151+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
152152

153153
-- Extracting elements functions
154154

155155
CREATE FUNCTION cube_dim(cube)
156156
RETURNS int4
157157
AS 'MODULE_PATHNAME'
158-
LANGUAGE C IMMUTABLE STRICT;
158+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
159159

160160
CREATE FUNCTION cube_ll_coord(cube, int4)
161161
RETURNS float8
162162
AS 'MODULE_PATHNAME'
163-
LANGUAGE C IMMUTABLE STRICT;
163+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
164164

165165
CREATE FUNCTION cube_ur_coord(cube, int4)
166166
RETURNS float8
167167
AS 'MODULE_PATHNAME'
168-
LANGUAGE C IMMUTABLE STRICT;
168+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
169169

170170
CREATE FUNCTION cube_coord(cube, int4)
171171
RETURNS float8
172172
AS 'MODULE_PATHNAME'
173-
LANGUAGE C IMMUTABLE STRICT;
173+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
174174

175175
CREATE FUNCTION cube_coord_llur(cube, int4)
176176
RETURNS float8
177177
AS 'MODULE_PATHNAME'
178-
LANGUAGE C IMMUTABLE STRICT;
178+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
179179

180180
CREATE FUNCTION cube(float8) RETURNS cube
181181
AS 'MODULE_PATHNAME', 'cube_f8'
182-
LANGUAGE C IMMUTABLE STRICT;
182+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
183183

184184
CREATE FUNCTION cube(float8, float8) RETURNS cube
185185
AS 'MODULE_PATHNAME', 'cube_f8_f8'
186-
LANGUAGE C IMMUTABLE STRICT;
186+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
187187

188188
CREATE FUNCTION cube(cube, float8) RETURNS cube
189189
AS 'MODULE_PATHNAME', 'cube_c_f8'
190-
LANGUAGE C IMMUTABLE STRICT;
190+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
191191

192192
CREATE FUNCTION cube(cube, float8, float8) RETURNS cube
193193
AS 'MODULE_PATHNAME', 'cube_c_f8_f8'
194-
LANGUAGE C IMMUTABLE STRICT;
194+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
195195

196196
-- Test if cube is also a point
197197

198198
CREATE FUNCTION cube_is_point(cube)
199199
RETURNS bool
200200
AS 'MODULE_PATHNAME'
201-
LANGUAGE C IMMUTABLE STRICT;
201+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
202202

203203
-- Increasing the size of a cube by a radius in at least n dimensions
204204

205205
CREATE FUNCTION cube_enlarge(cube, float8, int4)
206206
RETURNS cube
207207
AS 'MODULE_PATHNAME'
208-
LANGUAGE C IMMUTABLE STRICT;
208+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
209209

210210
--
211211
-- OPERATORS
@@ -307,42 +307,42 @@ CREATE OPERATOR ~ (
307307
CREATE FUNCTION g_cube_consistent(internal,cube,smallint,oid,internal)
308308
RETURNS bool
309309
AS 'MODULE_PATHNAME'
310-
LANGUAGE C IMMUTABLE STRICT;
310+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
311311

312312
CREATE FUNCTION g_cube_compress(internal)
313313
RETURNS internal
314314
AS 'MODULE_PATHNAME'
315-
LANGUAGE C IMMUTABLE STRICT;
315+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
316316

317317
CREATE FUNCTION g_cube_decompress(internal)
318318
RETURNS internal
319319
AS 'MODULE_PATHNAME'
320-
LANGUAGE C IMMUTABLE STRICT;
320+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
321321

322322
CREATE FUNCTION g_cube_penalty(internal,internal,internal)
323323
RETURNS internal
324324
AS 'MODULE_PATHNAME'
325-
LANGUAGE C IMMUTABLE STRICT;
325+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
326326

327327
CREATE FUNCTION g_cube_picksplit(internal, internal)
328328
RETURNS internal
329329
AS 'MODULE_PATHNAME'
330-
LANGUAGE C IMMUTABLE STRICT;
330+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
331331

332332
CREATE FUNCTION g_cube_union(internal, internal)
333333
RETURNS cube
334334
AS 'MODULE_PATHNAME'
335-
LANGUAGE C IMMUTABLE STRICT;
335+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
336336

337337
CREATE FUNCTION g_cube_same(cube, cube, internal)
338338
RETURNS internal
339339
AS 'MODULE_PATHNAME'
340-
LANGUAGE C IMMUTABLE STRICT;
340+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
341341

342342
CREATE FUNCTION g_cube_distance (internal, cube, smallint, oid, internal)
343343
RETURNS float8
344344
AS 'MODULE_PATHNAME'
345-
LANGUAGE C IMMUTABLE STRICT;
345+
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
346346

347347
-- Create the operator classes for indexing
348348

contrib/hstore/hstore--1.3--1.4.sql

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,61 @@ WHERE oid = pg_catalog.to_regprocedure(oldproc);
2424
UPDATE pg_catalog.pg_proc SET
2525
prorettype = 'ghstore'::pg_catalog.regtype
2626
WHERE oid = pg_catalog.to_regprocedure('ghstore_union(internal,internal)');
27+
28+
ALTER FUNCTION hstore_in(cstring) PARALLEL SAFE;
29+
ALTER FUNCTION hstore_out(hstore) PARALLEL SAFE;
30+
ALTER FUNCTION hstore_recv(internal) PARALLEL SAFE;
31+
ALTER FUNCTION hstore_send(hstore) PARALLEL SAFE;
32+
ALTER FUNCTION hstore_version_diag(hstore) PARALLEL SAFE;
33+
ALTER FUNCTION fetchval(hstore, text) PARALLEL SAFE;
34+
ALTER FUNCTION slice_array(hstore, text[]) PARALLEL SAFE;
35+
ALTER FUNCTION slice(hstore, text[]) PARALLEL SAFE;
36+
ALTER FUNCTION isexists(hstore, text) PARALLEL SAFE;
37+
ALTER FUNCTION exist(hstore, text) PARALLEL SAFE;
38+
ALTER FUNCTION exists_any(hstore, text[]) PARALLEL SAFE;
39+
ALTER FUNCTION exists_all(hstore, text[]) PARALLEL SAFE;
40+
ALTER FUNCTION isdefined(hstore, text) PARALLEL SAFE;
41+
ALTER FUNCTION defined(hstore, text) PARALLEL SAFE;
42+
ALTER FUNCTION delete(hstore, text) PARALLEL SAFE;
43+
ALTER FUNCTION delete(hstore, text[]) PARALLEL SAFE;
44+
ALTER FUNCTION delete(hstore, hstore) PARALLEL SAFE;
45+
ALTER FUNCTION hs_concat(hstore, hstore) PARALLEL SAFE;
46+
ALTER FUNCTION hs_contains(hstore, hstore) PARALLEL SAFE;
47+
ALTER FUNCTION hs_contained(hstore, hstore) PARALLEL SAFE;
48+
ALTER FUNCTION tconvert(text, text) PARALLEL SAFE;
49+
ALTER FUNCTION hstore(text, text) PARALLEL SAFE;
50+
ALTER FUNCTION hstore(text[], text[]) PARALLEL SAFE;
51+
ALTER FUNCTION hstore(text[]) PARALLEL SAFE;
52+
ALTER FUNCTION hstore_to_json(hstore) PARALLEL SAFE;
53+
ALTER FUNCTION hstore_to_json_loose(hstore) PARALLEL SAFE;
54+
ALTER FUNCTION hstore_to_jsonb(hstore) PARALLEL SAFE;
55+
ALTER FUNCTION hstore_to_jsonb_loose(hstore) PARALLEL SAFE;
56+
ALTER FUNCTION hstore(record) PARALLEL SAFE;
57+
ALTER FUNCTION hstore_to_array(hstore) PARALLEL SAFE;
58+
ALTER FUNCTION hstore_to_matrix(hstore) PARALLEL SAFE;
59+
ALTER FUNCTION akeys(hstore) PARALLEL SAFE;
60+
ALTER FUNCTION avals(hstore) PARALLEL SAFE;
61+
ALTER FUNCTION skeys(hstore) PARALLEL SAFE;
62+
ALTER FUNCTION svals(hstore) PARALLEL SAFE;
63+
ALTER FUNCTION each(hstore) PARALLEL SAFE;
64+
ALTER FUNCTION populate_record(anyelement, hstore) PARALLEL SAFE;
65+
ALTER FUNCTION hstore_eq(hstore, hstore) PARALLEL SAFE;
66+
ALTER FUNCTION hstore_ne(hstore, hstore) PARALLEL SAFE;
67+
ALTER FUNCTION hstore_gt(hstore, hstore) PARALLEL SAFE;
68+
ALTER FUNCTION hstore_ge(hstore, hstore) PARALLEL SAFE;
69+
ALTER FUNCTION hstore_lt(hstore, hstore) PARALLEL SAFE;
70+
ALTER FUNCTION hstore_le(hstore, hstore) PARALLEL SAFE;
71+
ALTER FUNCTION hstore_cmp(hstore, hstore) PARALLEL SAFE;
72+
ALTER FUNCTION hstore_hash(hstore) PARALLEL SAFE;
73+
ALTER FUNCTION ghstore_in(cstring) PARALLEL SAFE;
74+
ALTER FUNCTION ghstore_out(ghstore) PARALLEL SAFE;
75+
ALTER FUNCTION ghstore_compress(internal) PARALLEL SAFE;
76+
ALTER FUNCTION ghstore_decompress(internal) PARALLEL SAFE;
77+
ALTER FUNCTION ghstore_penalty(internal, internal, internal) PARALLEL SAFE;
78+
ALTER FUNCTION ghstore_picksplit(internal, internal) PARALLEL SAFE;
79+
ALTER FUNCTION ghstore_union(internal, internal) PARALLEL SAFE;
80+
ALTER FUNCTION ghstore_same(ghstore, ghstore, internal) PARALLEL SAFE;
81+
ALTER FUNCTION ghstore_consistent(internal, hstore, smallint, oid, internal) PARALLEL SAFE;
82+
ALTER FUNCTION gin_extract_hstore(hstore, internal) PARALLEL SAFE;
83+
ALTER FUNCTION gin_extract_hstore_query(hstore, internal, int2, internal, internal) PARALLEL SAFE;
84+
ALTER FUNCTION gin_consistent_hstore(internal, int2, hstore, int4, internal, internal) PARALLEL SAFE;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy