@@ -93,8 +93,8 @@ CREATE TABLE partitions (
93
93
-- it.
94
94
CREATE FUNCTION new_primary () RETURNS TRIGGER AS $$
95
95
BEGIN
96
- RAISE DEBUG ' [SHARDMAN] new_primary trigger called for part %, owner %' ,
97
- NEW .part_name , NEW .owner ;
96
+ RAISE DEBUG ' [SHARDMAN] new_primary trigger called on node % for part %, owner %' ,
97
+ shardman . get_node_id (), NEW .part_name , NEW .owner ;
98
98
IF NEW .owner != shardman .get_node_id () THEN
99
99
PERFORM shardman .replace_usual_part_with_foreign (NEW);
100
100
END IF;
@@ -150,7 +150,7 @@ BEGIN
150
150
PERFORM shardman .eliminate_sub (prev_lname);
151
151
EXECUTE format(
152
152
' CREATE SUBSCRIPTION %I connection %L
153
- PUBLICATION %I with (create_slot = false, slot_name = %L, copy_data = false);' ,
153
+ PUBLICATION %I with (create_slot = false, slot_name = %L, copy_data = false, synchronous_commit = on );' ,
154
154
prev_lname, prev_connstr, prev_lname, prev_lname);
155
155
END IF;
156
156
END $$ LANGUAGE plpgsql STRICT;
@@ -168,7 +168,7 @@ BEGIN
168
168
PERFORM shardman .eliminate_sub (lname);
169
169
EXECUTE format(
170
170
' CREATE SUBSCRIPTION %I connection %L
171
- PUBLICATION %I with (create_slot = false, slot_name = %L, copy_data = false);' ,
171
+ PUBLICATION %I with (create_slot = false, slot_name = %L, copy_data = false, synchronous_commit = on );' ,
172
172
lname, dst_connstr, lname, lname);
173
173
END $$ LANGUAGE plpgsql STRICT;
174
174
@@ -204,7 +204,7 @@ BEGIN
204
204
ELSE
205
205
-- On the other hand, if prev replica existed, drop sub for old
206
206
-- channel prev -> src
207
- PERFORM shardman .eliminate_sub (src_next_lname );
207
+ PERFORM shardman .eliminate_sub (prev_src_lname );
208
208
END IF;
209
209
IF NEW .nxt IS NOT NULL THEN
210
210
-- If next replica existed, drop pub for old channel src -> next
@@ -218,7 +218,7 @@ BEGIN
218
218
-- Drop subscription used for copy
219
219
PERFORM shardman .eliminate_sub (cp_logname);
220
220
-- If primary part was moved, replace moved table with foreign one
221
- IF NEW .prev IS NULL THEN
221
+ IF NEW .prv IS NULL THEN
222
222
PERFORM shardman .replace_foreign_part_with_usual (NEW);
223
223
END IF;
224
224
ELSEIF me = NEW .prv THEN -- node with prev replica
@@ -236,8 +236,7 @@ BEGIN
236
236
END
237
237
$$ LANGUAGE plpgsql;
238
238
CREATE TRIGGER part_moved AFTER UPDATE ON shardman .partitions
239
- FOR EACH ROW WHEN (OLD .prv is NULL AND NEW .prv IS NULL -- it is primary
240
- AND OLD .owner != NEW .owner -- and it is really moved
239
+ FOR EACH ROW WHEN (OLD .owner != NEW .owner -- part is really moved
241
240
AND OLD .part_name = NEW .part_name ) -- sanity check
242
241
EXECUTE PROCEDURE part_moved();
243
242
-- fire trigger only on worker nodes
@@ -287,7 +286,7 @@ BEGIN
287
286
PERFORM shardman .eliminate_sub (lname);
288
287
EXECUTE format(
289
288
' CREATE SUBSCRIPTION %I connection %L
290
- PUBLICATION %I with (create_slot = false, slot_name = %L, copy_data = false);' ,
289
+ PUBLICATION %I with (create_slot = false, slot_name = %L, copy_data = false, synchronous_commit = on );' ,
291
290
lname, oldtail_connstr, lname, lname);
292
291
END $$ LANGUAGE plpgsql;
293
292
@@ -324,18 +323,19 @@ BEGIN
324
323
END $$ LANGUAGE plpgsql STRICT;
325
324
326
325
-- Drop all foreign server's options. Yes, I don't know simpler ways.
327
- CREATE FUNCTION reset_foreign_server_opts (srvname name) RETURNS void AS $$
326
+ CREATE FUNCTION reset_foreign_server_opts (sname name) RETURNS void AS $$
328
327
DECLARE
329
328
opts text [];
330
329
opt text ;
331
330
opt_key text ;
332
331
BEGIN
333
- EXECUTE format($q$select coalesce(srvoptions, ' {}' ::text []) FROM
332
+ ASSERT EXISTS (SELECT 1 FROM pg_foreign_server WHERE srvname = sname);
333
+ EXECUTE format($q$SELECT coalesce(srvoptions, ' {}' ::text []) FROM
334
334
pg_foreign_server WHERE srvname = %L$q$,
335
- srvname ) INTO opts;
335
+ sname ) INTO opts;
336
336
FOREACH opt IN ARRAY opts LOOP
337
337
opt_key := regexp_replace(substring (opt from ' ^.*?=' ), ' =$' , ' ' );
338
- EXECUTE format(' ALTER SERVER %I OPTIONS (DROP %s);' , srvname , opt_key);
338
+ EXECUTE format(' ALTER SERVER %I OPTIONS (DROP %s);' , sname , opt_key);
339
339
END LOOP;
340
340
END $$ LANGUAGE plpgsql STRICT;
341
341
-- Same for resetting user mapping opts
@@ -359,29 +359,49 @@ BEGIN
359
359
END LOOP;
360
360
END $$ LANGUAGE plpgsql STRICT;
361
361
362
- -- Update foreign server and user mapping params according to partition part, so
363
- -- this is expected to be called on server/um params change. We use dedicated
364
- -- server for each partition because we plan to use multiple hosts/ports in
365
- -- connstrings for transient fallback to replica if server with main partition
366
- -- fails. FDW server, user mapping, foreign table and (obviously) parent partition
367
- -- must exist when called.
362
+ -- Update foreign server and user mapping params on current node according to
363
+ -- partition part, so this is expected to be called on server/um params
364
+ -- change. We use dedicated server for each partition because we plan to use
365
+ -- multiple hosts/ports in connstrings for transient fallback to replica if
366
+ -- server with main partition fails. FDW server, user mapping, foreign table and
367
+ -- (obviously) parent partition must exist when called if they need to be
368
+ -- updated; however, it is ok to call this func on nodes which don't need fdw
369
+ -- setup for this part because they hold primary partition.
368
370
CREATE FUNCTION update_fdw_server (part partitions) RETURNS void AS $$
369
371
DECLARE
370
372
connstring text ;
371
373
server_opts text ;
372
374
um_opts text ;
375
+ me int := shardman .get_node_id ();
376
+ my_part shardman .partitions ;
373
377
BEGIN
374
- -- ALTER FOREIGN TABLE doesn't support changing server, ALTER SERVER doesn't
375
- -- support dropping all params, and I don't want to recreate foreign table
376
- -- each time server params change, so resorting to these hacks.
377
- PERFORM shardman .reset_foreign_server_opts (part .part_name );
378
- PERFORM shardman .reset_um_opts (part .part_name , current_user ::regrole);
378
+ RAISE DEBUG ' [SHARDMAN %] update_fdw_server called for part %, owner %' ,
379
+ shardman .get_node_id (), part .part_name , part .owner ;
380
+
381
+ SELECT * FROM shardman .partitions WHERE part_name = part .part_name AND
382
+ owner = me INTO my_part;
383
+ IF my_part .part_name IS NOT NULL THEN -- we are holding the part
384
+ IF my_part .prv IS NULL THEN
385
+ RAISE DEBUG ' [SHARDMAN %] we are holding primary for part %s, not updating fdw server for it' ,
386
+ me, part .part_name ;
387
+ RETURN;
388
+ ELSE
389
+ RAISE DEBUG ' [SHARDMAN %] we are holding replica for part %s, updating fdw server for it' ,
390
+ me, part .part_name ;
391
+ END IF;
392
+ END IF;
379
393
380
394
SELECT nodes .connstring FROM shardman .nodes WHERE id = part .owner
381
395
INTO connstring;
382
396
SELECT * FROM shardman .conninfo_to_postgres_fdw_opts (connstring, ' ADD ' )
383
397
INTO server_opts, um_opts;
384
398
399
+ -- ALTER FOREIGN TABLE doesn't support changing server, ALTER SERVER doesn't
400
+ -- support dropping all params, and I don't want to recreate foreign table
401
+ -- each time server params change, so resorting to these hacks.
402
+ PERFORM shardman .reset_foreign_server_opts (part .part_name );
403
+ PERFORM shardman .reset_um_opts (part .part_name , current_user ::regrole);
404
+
385
405
IF server_opts != ' ' THEN
386
406
EXECUTE format(' ALTER SERVER %I %s' , part .part_name , server_opts);
387
407
END IF;
0 commit comments