@@ -240,7 +240,7 @@ BEGIN
240
240
END IF;
241
241
242
242
-- And update fdw almost everywhere
243
- PERFORM shardman .update_fdw_server (NEW);
243
+ PERFORM shardman .update_fdw_table_srv (NEW);
244
244
RETURN NULL ;
245
245
END
246
246
$$ LANGUAGE plpgsql;
@@ -326,7 +326,7 @@ BEGIN
326
326
327
327
IF NOT replica_removed AND shardman .me_worker () THEN
328
328
-- update fdw almost everywhere
329
- PERFORM shardman .update_fdw_server (new_primary);
329
+ PERFORM shardman .update_fdw_table_srv (new_primary);
330
330
END IF;
331
331
332
332
IF shardman .me_lord () THEN
@@ -427,14 +427,14 @@ DECLARE
427
427
opt text ;
428
428
opt_key text ;
429
429
BEGIN
430
- ASSERT EXISTS (SELECT 1 from pg_foreign_server WHERE srvname= server_name);
430
+ ASSERT EXISTS (SELECT 1 FROM pg_foreign_server WHERE srvname = server_name);
431
431
EXECUTE format($q$SELECT coalesce(srvoptions, ' {}' ::text []) FROM
432
432
pg_foreign_server WHERE srvname = %L$q$,
433
- server_name) INTO opts;
434
- FOREACH opt IN ARRAY opts LOOP
435
- opt_key := regexp_replace(substring (opt from ' ^.*?=' ), ' =$' , ' ' );
436
- EXECUTE format(' ALTER SERVER %I OPTIONS (DROP %s);' , server_name, opt_key);
437
- END LOOP;
433
+ server_name) INTO opts;
434
+ FOREACH opt IN ARRAY opts LOOP
435
+ opt_key := regexp_replace(substring (opt from ' ^.*?=' ), ' =$' , ' ' );
436
+ EXECUTE format(' ALTER SERVER %I OPTIONS (DROP %s);' , server_name, opt_key);
437
+ END LOOP;
438
438
END $$ LANGUAGE plpgsql STRICT;
439
439
-- Same for resetting user mapping opts
440
440
CREATE or replace FUNCTION reset_um_opts (srvname name, umuser regrole)
@@ -450,36 +450,40 @@ BEGIN
450
450
ums .umuser = umuser$q$, srvname)
451
451
INTO opts;
452
452
IF opts IS NOT NULL THEN
453
- FOREACH opt IN ARRAY opts LOOP
454
- opt_key := regexp_replace(substring (opt from ' ^.*?=' ), ' =$' , ' ' );
453
+ FOREACH opt IN ARRAY opts LOOP
454
+ opt_key := regexp_replace(substring (opt from ' ^.*?=' ), ' =$' , ' ' );
455
455
EXECUTE format(' ALTER USER MAPPING FOR %I SERVER %I OPTIONS (DROP %s);' ,
456
456
umuser::name, srvname, opt_key);
457
- END LOOP;
457
+ END LOOP;
458
458
END IF;
459
459
END $$ LANGUAGE plpgsql STRICT;
460
460
461
- CREATE FUNCTION create_foreign_server (node_id integer ) RETURNS void AS $$
461
+ -- Create foreign server & um pointing to node 'node_id' named "node_'node_id'",
462
+ -- or alter existing one to match the connstring.
463
+ CREATE FUNCTION ensure_foreign_server (node_id integer ) RETURNS void AS $$
462
464
DECLARE
463
- connstring text ;
465
+ connstring text : = shardman . get_worker_node_connstr (node_id) ;
464
466
server_opts text ;
465
467
um_opts text ;
466
- server_name text ;
468
+ server_name text : = ' node_ ' || node_id ;
467
469
BEGIN
468
- SELECT nodes .connstring FROM shardman .nodes WHERE id = node_id
469
- INTO connstring;
470
470
SELECT * FROM shardman .conninfo_to_postgres_fdw_opts (connstring)
471
471
INTO server_opts, um_opts;
472
- server_name := ' node_' || node_id;
473
- IF NOT EXISTS (SELECT 1 from pg_foreign_server WHERE srvname= server_name)
472
+ IF NOT EXISTS (SELECT 1 from pg_foreign_server WHERE srvname = server_name)
474
473
THEN
475
- RAISE DEBUG ' Create foreign server % for with options %' , server_name, server_opts;
474
+ RAISE DEBUG ' [SHMN] Create foreign server % for with options %' ,
475
+ server_name, server_opts;
476
476
EXECUTE format(' CREATE SERVER %I FOREIGN DATA WRAPPER postgres_fdw %s;' ,
477
- server_name, server_opts);
478
- -- TODO: support not only CURRENT_USER
479
- EXECUTE format(' CREATE USER MAPPING FOR CURRENT_USER SERVER %I %s;' ,
477
+ server_name, server_opts);
478
+ -- TODO: support not only CURRENT_USER
479
+ EXECUTE format(' CREATE USER MAPPING FOR CURRENT_USER SERVER %I %s;' ,
480
480
server_name, um_opts);
481
481
ELSE
482
- RAISE DEBUG ' Use existed foreign server % with options %' , server_name, server_opts;
482
+ -- ALTER SERVER & UM doesn't support dropping all params. We could
483
+ -- recreate them, but since these hacks already exist for legacy code,
484
+ -- we can use them as well.
485
+ RAISE DEBUG ' Using existing foreign server % with options %' ,
486
+ server_name, server_opts;
483
487
PERFORM shardman .reset_foreign_server_opts (server_name);
484
488
PERFORM shardman .reset_um_opts (server_name, current_user ::regrole);
485
489
@@ -493,13 +497,12 @@ BEGIN
493
497
END IF;
494
498
END $$ LANGUAGE plpgsql STRICT;
495
499
496
- -- Update foreign server and user mapping params on current node according to
497
- -- partition part, so this is expected to be called on server/um params
498
- -- change. FDW server, user mapping, foreign table and
499
- -- (obviously) parent partition must exist when called if they need to be
500
- -- updated; however, it is ok to call this func on nodes which don't need fdw
501
- -- setup for this part because they hold primary partition.
502
- CREATE FUNCTION update_fdw_server (part partitions) RETURNS void AS $$
500
+ -- Make sure foreign table for given part is associated with proper foreign
501
+ -- server, so this is expected to be called on server/um params change,
502
+ -- e.g. shard move or connstring update. Foreign table must exist when called if
503
+ -- they need to be updated; however, it is ok to call this func on nodes which
504
+ -- don't need fdw setup for this part because they hold primary partition.
505
+ CREATE FUNCTION update_fdw_table_srv (part partitions) RETURNS void AS $$
503
506
DECLARE
504
507
connstring text ;
505
508
server_opts text ;
@@ -509,24 +512,31 @@ DECLARE
509
512
server_oid oid ;
510
513
foreign_table_oid oid ;
511
514
BEGIN
512
- RAISE DEBUG ' [SHMN] update_fdw_server called for part %, owner %' ,
515
+ RAISE DEBUG ' [SHMN] update_fdw_table_srv called for part %, owner %' ,
513
516
part .part_name , part .owner ;
514
517
515
518
SELECT * FROM shardman .partitions WHERE part_name = part .part_name AND
516
519
owner = me INTO my_part;
517
520
IF my_part .part_name IS NOT NULL THEN -- we are holding the part
518
521
IF my_part .prv IS NULL THEN
519
- RAISE DEBUG ' [SHMN] we are holding primary for part %, not updating fdw server for it' , part .part_name ;
522
+ RAISE DEBUG ' [SHMN] we are holding primary for part %, not updating fdw table for it' ,
523
+ part .part_name ;
520
524
RETURN;
521
525
ELSE
522
- RAISE DEBUG ' [SHMN] we are holding replica for part %, updating fdw server for it' , part .part_name ;
526
+ RAISE DEBUG ' [SHMN] we are holding replica for part %, updating fdw table for it' ,
527
+ part .part_name ;
523
528
END IF;
524
529
END IF;
525
530
526
- PERFORM shardman .create_foreign_server (part .owner );
531
+ PERFORM shardman .ensure_foreign_server (part .owner );
527
532
528
- SELECT oid FROM pg_foreign_server WHERE srvname= ' node_' || part .owner into server_oid;
529
- SELECT oid FROM pg_class WHERE relname= part .part_name || ' _fdw' into foreign_table_oid;
533
+ -- Well, ALTER FOREIGN TABLE doesn't support changing server, but this hack
534
+ -- seems to be working.
535
+ SELECT oid FROM pg_foreign_server WHERE srvname = ' node_' || part .owner
536
+ INTO server_oid;
537
+ SELECT oid FROM pg_class WHERE relname = shardman .get_fdw_part_name (part .part_name )
538
+ INTO foreign_table_oid;
539
+ ASSERT foreign_table_oid IS NOT NULL , ' update_fdw_table_srv: table not found' ;
530
540
UPDATE pg_foreign_table SET ftserver = server_oid WHERE ftrelid = foreign_table_oid;
531
541
END $$ LANGUAGE plpgsql STRICT;
532
542
@@ -536,13 +546,11 @@ CREATE FUNCTION replace_usual_part_with_foreign(part partitions)
536
546
RETURNS void AS $$
537
547
DECLARE
538
548
connstring text ;
539
- fdw_part_name text ;
540
- server_name text ;
549
+ fdw_part_name text : = shardman . get_fdw_part_name ( part . part_name ) ;
550
+ server_name text : = ' node_ ' || part . owner ;
541
551
BEGIN
542
- server_name := ' node_' || part .owner ;
543
- PERFORM shardman .create_foreign_server (part .owner );
552
+ PERFORM shardman .ensure_foreign_server (part .owner );
544
553
545
- SELECT shardman .get_fdw_part_name (part .part_name ) INTO fdw_part_name;
546
554
EXECUTE format(' DROP FOREIGN TABLE IF EXISTS %I;' , fdw_part_name);
547
555
548
556
-- Generate and execute CREATE FOREIGN TABLE sql statement which will
0 commit comments