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

Commit 8895923

Browse files
committed
Fix planner's row-mark code for inheritance from a foreign table.
Commit 428b260 broke planning of cases where row marks are needed (SELECT FOR UPDATE, etc) and one of the query's tables is a foreign table that has regular table(s) as inheritance children. We got the reverse case right, but apparently were thinking that foreign tables couldn't be inheritance parents. Not so; so we need to be able to add a CTID junk column while adding a new child, not only a wholerow junk column. Back-patch to v12 where the faulty code came in. Amit Langote Discussion: https://postgr.es/m/CA+HiwqEmo3FV1LAQ4TVyS2h1WM=kMkZUmbNuZSCnfHvMcUcPeA@mail.gmail.com
1 parent 79c50ca commit 8895923

File tree

3 files changed

+126
-2
lines changed

3 files changed

+126
-2
lines changed

contrib/postgres_fdw/expected/postgres_fdw.out

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7255,6 +7255,92 @@ select * from bar where f1 in (select f1 from foo) for share;
72557255
4 | 44
72567256
(4 rows)
72577257

7258+
-- Now check SELECT FOR UPDATE/SHARE with an inherited source table,
7259+
-- where the parent is itself a foreign table
7260+
create table loct4 (f1 int, f2 int, f3 int);
7261+
create foreign table foo2child (f3 int) inherits (foo2)
7262+
server loopback options (table_name 'loct4');
7263+
NOTICE: moving and merging column "f3" with inherited definition
7264+
DETAIL: User-specified column moved to the position of the inherited column.
7265+
explain (verbose, costs off)
7266+
select * from bar where f1 in (select f1 from foo2) for share;
7267+
QUERY PLAN
7268+
--------------------------------------------------------------------------------------
7269+
LockRows
7270+
Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.tableoid
7271+
-> Hash Join
7272+
Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.tableoid
7273+
Inner Unique: true
7274+
Hash Cond: (bar.f1 = foo2.f1)
7275+
-> Append
7276+
-> Seq Scan on public.bar bar_1
7277+
Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid
7278+
-> Foreign Scan on public.bar2 bar_2
7279+
Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid
7280+
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR SHARE
7281+
-> Hash
7282+
Output: foo2.*, foo2.f1, foo2.tableoid
7283+
-> HashAggregate
7284+
Output: foo2.*, foo2.f1, foo2.tableoid
7285+
Group Key: foo2.f1
7286+
-> Append
7287+
-> Foreign Scan on public.foo2 foo2_1
7288+
Output: foo2_1.*, foo2_1.f1, foo2_1.tableoid
7289+
Remote SQL: SELECT f1, f2, f3 FROM public.loct1
7290+
-> Foreign Scan on public.foo2child foo2_2
7291+
Output: foo2_2.*, foo2_2.f1, foo2_2.tableoid
7292+
Remote SQL: SELECT f1, f2, f3 FROM public.loct4
7293+
(24 rows)
7294+
7295+
select * from bar where f1 in (select f1 from foo2) for share;
7296+
f1 | f2
7297+
----+----
7298+
2 | 22
7299+
4 | 44
7300+
(2 rows)
7301+
7302+
drop foreign table foo2child;
7303+
-- And with a local child relation of the foreign table parent
7304+
create table foo2child (f3 int) inherits (foo2);
7305+
NOTICE: moving and merging column "f3" with inherited definition
7306+
DETAIL: User-specified column moved to the position of the inherited column.
7307+
explain (verbose, costs off)
7308+
select * from bar where f1 in (select f1 from foo2) for share;
7309+
QUERY PLAN
7310+
-------------------------------------------------------------------------------------------------
7311+
LockRows
7312+
Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.ctid, foo2.tableoid
7313+
-> Hash Join
7314+
Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.ctid, foo2.tableoid
7315+
Inner Unique: true
7316+
Hash Cond: (bar.f1 = foo2.f1)
7317+
-> Append
7318+
-> Seq Scan on public.bar bar_1
7319+
Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid
7320+
-> Foreign Scan on public.bar2 bar_2
7321+
Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid
7322+
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR SHARE
7323+
-> Hash
7324+
Output: foo2.*, foo2.f1, foo2.ctid, foo2.tableoid
7325+
-> HashAggregate
7326+
Output: foo2.*, foo2.f1, foo2.ctid, foo2.tableoid
7327+
Group Key: foo2.f1
7328+
-> Append
7329+
-> Foreign Scan on public.foo2 foo2_1
7330+
Output: foo2_1.*, foo2_1.f1, foo2_1.ctid, foo2_1.tableoid
7331+
Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
7332+
-> Seq Scan on public.foo2child foo2_2
7333+
Output: foo2_2.*, foo2_2.f1, foo2_2.ctid, foo2_2.tableoid
7334+
(23 rows)
7335+
7336+
select * from bar where f1 in (select f1 from foo2) for share;
7337+
f1 | f2
7338+
----+----
7339+
2 | 22
7340+
4 | 44
7341+
(2 rows)
7342+
7343+
drop table foo2child;
72587344
-- Check UPDATE with inherited target and an inherited source table
72597345
explain (verbose, costs off)
72607346
update bar set f2 = f2 + 100 where f1 in (select f1 from foo);

contrib/postgres_fdw/sql/postgres_fdw.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,6 +1891,27 @@ explain (verbose, costs off)
18911891
select * from bar where f1 in (select f1 from foo) for share;
18921892
select * from bar where f1 in (select f1 from foo) for share;
18931893

1894+
-- Now check SELECT FOR UPDATE/SHARE with an inherited source table,
1895+
-- where the parent is itself a foreign table
1896+
create table loct4 (f1 int, f2 int, f3 int);
1897+
create foreign table foo2child (f3 int) inherits (foo2)
1898+
server loopback options (table_name 'loct4');
1899+
1900+
explain (verbose, costs off)
1901+
select * from bar where f1 in (select f1 from foo2) for share;
1902+
select * from bar where f1 in (select f1 from foo2) for share;
1903+
1904+
drop foreign table foo2child;
1905+
1906+
-- And with a local child relation of the foreign table parent
1907+
create table foo2child (f3 int) inherits (foo2);
1908+
1909+
explain (verbose, costs off)
1910+
select * from bar where f1 in (select f1 from foo2) for share;
1911+
select * from bar where f1 in (select f1 from foo2) for share;
1912+
1913+
drop table foo2child;
1914+
18941915
-- Check UPDATE with inherited target and an inherited source table
18951916
explain (verbose, costs off)
18961917
update bar set f2 = f2 + 100 where f1 in (select f1 from foo);

src/backend/optimizer/util/inherit.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,25 @@ expand_inherited_rtentry(PlannerInfo *root, RelOptInfo *rel,
232232
char resname[32];
233233
List *newvars = NIL;
234234

235-
/* The old PlanRowMark should already have necessitated adding TID */
236-
Assert(old_allMarkTypes & ~(1 << ROW_MARK_COPY));
235+
/* Add TID junk Var if needed, unless we had it already */
236+
if (new_allMarkTypes & ~(1 << ROW_MARK_COPY) &&
237+
!(old_allMarkTypes & ~(1 << ROW_MARK_COPY)))
238+
{
239+
/* Need to fetch TID */
240+
var = makeVar(oldrc->rti,
241+
SelfItemPointerAttributeNumber,
242+
TIDOID,
243+
-1,
244+
InvalidOid,
245+
0);
246+
snprintf(resname, sizeof(resname), "ctid%u", oldrc->rowmarkId);
247+
tle = makeTargetEntry((Expr *) var,
248+
list_length(root->processed_tlist) + 1,
249+
pstrdup(resname),
250+
true);
251+
root->processed_tlist = lappend(root->processed_tlist, tle);
252+
newvars = lappend(newvars, var);
253+
}
237254

238255
/* Add whole-row junk Var if needed, unless we had it already */
239256
if ((new_allMarkTypes & (1 << ROW_MARK_COPY)) &&

0 commit comments

Comments
 (0)