Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4103a2f

Browse files
committed
Invalidate cached plans on FDW option changes.
This fixes problems where a plan must change but fails to do so, as seen in a bug report from Rajkumar Raghuwanshi. For ALTER FOREIGN TABLE OPTIONS, do this through the standard method of forcing a relcache flush on the table. For ALTER FOREIGN DATA WRAPPER and ALTER SERVER, just flush the whole plan cache on any change in pg_foreign_data_wrapper or pg_foreign_server. That matches the way we handle some other low-probability cases such as opclass changes, and it's unclear that the case arises often enough to be worth working harder. Besides, that gives a patch that is simple enough to back-patch with confidence. Back-patch to 9.3. In principle we could apply the code change to 9.2 as well, but (a) we lack postgres_fdw to test it with, (b) it's doubtful that anyone is doing anything exciting enough with FDWs that far back to need this desperately, and (c) the patch doesn't apply cleanly. Patch originally by Amit Langote, reviewed by Etsuro Fujita and Ashutosh Bapat, who each contributed substantial changes as well. Discussion: https://postgr.es/m/CAKcux6m5cA6rRPTKkqVdJ-R=KKDfe35Q_ZuUqxDSV_4hwga=og@mail.gmail.com
1 parent 6032991 commit 4103a2f

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed

contrib/postgres_fdw/expected/postgres_fdw.out

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2479,12 +2479,100 @@ EXECUTE st5('foo', 1);
24792479
1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
24802480
(1 row)
24812481

2482+
-- altering FDW options requires replanning
2483+
PREPARE st6 AS SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2;
2484+
EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6;
2485+
QUERY PLAN
2486+
----------------------------------------------------------------------------------------------
2487+
Foreign Scan on public.ft1 t1
2488+
Output: c1, c2, c3, c4, c5, c6, c7, c8
2489+
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = c2))
2490+
(3 rows)
2491+
2492+
PREPARE st7 AS INSERT INTO ft1 (c1,c2,c3) VALUES (1001,101,'foo');
2493+
EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7;
2494+
QUERY PLAN
2495+
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2496+
Insert on public.ft1
2497+
Remote SQL: INSERT INTO "S 1"."T 1"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
2498+
-> Result
2499+
Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft1 '::character(10), NULL::user_enum
2500+
(4 rows)
2501+
2502+
ALTER TABLE "S 1"."T 1" RENAME TO "T 0";
2503+
ALTER FOREIGN TABLE ft1 OPTIONS (SET table_name 'T 0');
2504+
EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6;
2505+
QUERY PLAN
2506+
----------------------------------------------------------------------------------------------
2507+
Foreign Scan on public.ft1 t1
2508+
Output: c1, c2, c3, c4, c5, c6, c7, c8
2509+
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 0" WHERE (("C 1" = c2))
2510+
(3 rows)
2511+
2512+
EXECUTE st6;
2513+
c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
2514+
----+----+-------+------------------------------+--------------------------+----+------------+-----
2515+
1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
2516+
2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo
2517+
3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
2518+
4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo
2519+
5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo
2520+
6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo
2521+
7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
2522+
8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
2523+
9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo
2524+
(9 rows)
2525+
2526+
EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7;
2527+
QUERY PLAN
2528+
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2529+
Insert on public.ft1
2530+
Remote SQL: INSERT INTO "S 1"."T 0"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
2531+
-> Result
2532+
Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft1 '::character(10), NULL::user_enum
2533+
(4 rows)
2534+
2535+
ALTER TABLE "S 1"."T 0" RENAME TO "T 1";
2536+
ALTER FOREIGN TABLE ft1 OPTIONS (SET table_name 'T 1');
2537+
PREPARE st8 AS SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
2538+
EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8;
2539+
QUERY PLAN
2540+
----------------------------------------------------------------------------------------
2541+
Aggregate
2542+
Output: count(c3)
2543+
-> Foreign Scan on public.ft1 t1
2544+
Output: c3
2545+
Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" OPERATOR(public.===) c2))
2546+
(5 rows)
2547+
2548+
ALTER SERVER loopback OPTIONS (DROP extensions);
2549+
EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8;
2550+
QUERY PLAN
2551+
-----------------------------------------------------------
2552+
Aggregate
2553+
Output: count(c3)
2554+
-> Foreign Scan on public.ft1 t1
2555+
Output: c3
2556+
Filter: (t1.c1 === t1.c2)
2557+
Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
2558+
(6 rows)
2559+
2560+
EXECUTE st8;
2561+
count
2562+
-------
2563+
9
2564+
(1 row)
2565+
2566+
ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
24822567
-- cleanup
24832568
DEALLOCATE st1;
24842569
DEALLOCATE st2;
24852570
DEALLOCATE st3;
24862571
DEALLOCATE st4;
24872572
DEALLOCATE st5;
2573+
DEALLOCATE st6;
2574+
DEALLOCATE st7;
2575+
DEALLOCATE st8;
24882576
-- System columns, except ctid, should not be sent to remote
24892577
EXPLAIN (VERBOSE, COSTS OFF)
24902578
SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1;

contrib/postgres_fdw/sql/postgres_fdw.sql

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,12 +570,35 @@ EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
570570
EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
571571
EXECUTE st5('foo', 1);
572572

573+
-- altering FDW options requires replanning
574+
PREPARE st6 AS SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2;
575+
EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6;
576+
PREPARE st7 AS INSERT INTO ft1 (c1,c2,c3) VALUES (1001,101,'foo');
577+
EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7;
578+
ALTER TABLE "S 1"."T 1" RENAME TO "T 0";
579+
ALTER FOREIGN TABLE ft1 OPTIONS (SET table_name 'T 0');
580+
EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6;
581+
EXECUTE st6;
582+
EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7;
583+
ALTER TABLE "S 1"."T 0" RENAME TO "T 1";
584+
ALTER FOREIGN TABLE ft1 OPTIONS (SET table_name 'T 1');
585+
586+
PREPARE st8 AS SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
587+
EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8;
588+
ALTER SERVER loopback OPTIONS (DROP extensions);
589+
EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8;
590+
EXECUTE st8;
591+
ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
592+
573593
-- cleanup
574594
DEALLOCATE st1;
575595
DEALLOCATE st2;
576596
DEALLOCATE st3;
577597
DEALLOCATE st4;
578598
DEALLOCATE st5;
599+
DEALLOCATE st6;
600+
DEALLOCATE st7;
601+
DEALLOCATE st8;
579602

580603
-- System columns, except ctid, should not be sent to remote
581604
EXPLAIN (VERBOSE, COSTS OFF)

src/backend/commands/tablecmds.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11313,6 +11313,12 @@ ATExecGenericOptions(Relation rel, List *options)
1131311313
simple_heap_update(ftrel, &tuple->t_self, tuple);
1131411314
CatalogUpdateIndexes(ftrel, tuple);
1131511315

11316+
/*
11317+
* Invalidate relcache so that all sessions will refresh any cached plans
11318+
* that might depend on the old options.
11319+
*/
11320+
CacheInvalidateRelcache(rel);
11321+
1131611322
InvokeObjectPostAlterHook(ForeignTableRelationId,
1131711323
RelationGetRelid(rel), 0);
1131811324

src/backend/utils/cache/plancache.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ InitPlanCache(void)
119119
CacheRegisterSyscacheCallback(NAMESPACEOID, PlanCacheSysCallback, (Datum) 0);
120120
CacheRegisterSyscacheCallback(OPEROID, PlanCacheSysCallback, (Datum) 0);
121121
CacheRegisterSyscacheCallback(AMOPOPID, PlanCacheSysCallback, (Datum) 0);
122+
CacheRegisterSyscacheCallback(FOREIGNSERVEROID, PlanCacheSysCallback, (Datum) 0);
123+
CacheRegisterSyscacheCallback(FOREIGNDATAWRAPPEROID, PlanCacheSysCallback, (Datum) 0);
122124
}
123125

124126
/*

0 commit comments

Comments
 (0)