Skip to content

Commit bbfdf71

Browse files
committed
Fix bug in translate_col_privs_multilevel
Fix incorrect code which was trying to convert a Bitmapset of columns at the attnums according to a parent table and transform them into the equivalent Bitmapset with same attnums according to the given child table. This code is new as of a61b1f7 and was failing to do the correct translation when there was an intermediate parent table between 'rel' and 'top_parent_rel'. Reported-by: Ranier Vilela Author: Richard Guo, Amit Langote Discussion: https://postgr.es/m/CAEudQArohfB_Gy%2BhcH2-bANUkxgjJiP%3DABq01_LgTNTbcNijag%40mail.gmail.com
1 parent b5d0f8e commit bbfdf71

File tree

3 files changed

+68
-13
lines changed

3 files changed

+68
-13
lines changed

contrib/postgres_fdw/expected/postgres_fdw.out

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6768,6 +6768,42 @@ DROP TRIGGER row_before_insupd_trigger ON child_tbl;
67686768
DROP TABLE parent_tbl CASCADE;
67696769
NOTICE: drop cascades to view rw_view
67706770
DROP FUNCTION row_before_insupd_trigfunc;
6771+
-- Try a more complex permutation of WCO where there are multiple levels of
6772+
-- partitioned tables with columns not all in the same order
6773+
CREATE TABLE parent_tbl (a int, b text, c numeric) PARTITION BY RANGE(a);
6774+
CREATE TABLE sub_parent (c numeric, a int, b text) PARTITION BY RANGE(a);
6775+
ALTER TABLE parent_tbl ATTACH PARTITION sub_parent FOR VALUES FROM (1) TO (10);
6776+
CREATE TABLE child_local (b text, c numeric, a int);
6777+
CREATE FOREIGN TABLE child_foreign (b text, c numeric, a int)
6778+
SERVER loopback OPTIONS (table_name 'child_local');
6779+
ALTER TABLE sub_parent ATTACH PARTITION child_foreign FOR VALUES FROM (1) TO (10);
6780+
CREATE VIEW rw_view AS SELECT * FROM parent_tbl WHERE a < 5 WITH CHECK OPTION;
6781+
INSERT INTO parent_tbl (a) VALUES(1),(5);
6782+
EXPLAIN (VERBOSE, COSTS OFF)
6783+
UPDATE rw_view SET b = 'text', c = 123.456;
6784+
QUERY PLAN
6785+
-------------------------------------------------------------------------------------------------
6786+
Update on public.parent_tbl
6787+
Foreign Update on public.child_foreign parent_tbl_1
6788+
Remote SQL: UPDATE public.child_local SET b = $2, c = $3 WHERE ctid = $1 RETURNING a
6789+
-> Foreign Scan on public.child_foreign parent_tbl_1
6790+
Output: 'text'::text, 123.456, parent_tbl_1.tableoid, parent_tbl_1.ctid, parent_tbl_1.*
6791+
Remote SQL: SELECT b, c, a, ctid FROM public.child_local WHERE ((a < 5)) FOR UPDATE
6792+
(6 rows)
6793+
6794+
UPDATE rw_view SET b = 'text', c = 123.456;
6795+
SELECT * FROM parent_tbl ORDER BY a;
6796+
a | b | c
6797+
---+------+---------
6798+
1 | text | 123.456
6799+
5 | |
6800+
(2 rows)
6801+
6802+
DROP VIEW rw_view;
6803+
DROP TABLE child_local;
6804+
DROP FOREIGN TABLE child_foreign;
6805+
DROP TABLE sub_parent;
6806+
DROP TABLE parent_tbl;
67716807
-- ===================================================================
67726808
-- test serial columns (ie, sequence-based defaults)
67736809
-- ===================================================================

contrib/postgres_fdw/sql/postgres_fdw.sql

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,6 +1580,29 @@ DROP TABLE parent_tbl CASCADE;
15801580

15811581
DROP FUNCTION row_before_insupd_trigfunc;
15821582

1583+
-- Try a more complex permutation of WCO where there are multiple levels of
1584+
-- partitioned tables with columns not all in the same order
1585+
CREATE TABLE parent_tbl (a int, b text, c numeric) PARTITION BY RANGE(a);
1586+
CREATE TABLE sub_parent (c numeric, a int, b text) PARTITION BY RANGE(a);
1587+
ALTER TABLE parent_tbl ATTACH PARTITION sub_parent FOR VALUES FROM (1) TO (10);
1588+
CREATE TABLE child_local (b text, c numeric, a int);
1589+
CREATE FOREIGN TABLE child_foreign (b text, c numeric, a int)
1590+
SERVER loopback OPTIONS (table_name 'child_local');
1591+
ALTER TABLE sub_parent ATTACH PARTITION child_foreign FOR VALUES FROM (1) TO (10);
1592+
CREATE VIEW rw_view AS SELECT * FROM parent_tbl WHERE a < 5 WITH CHECK OPTION;
1593+
1594+
INSERT INTO parent_tbl (a) VALUES(1),(5);
1595+
EXPLAIN (VERBOSE, COSTS OFF)
1596+
UPDATE rw_view SET b = 'text', c = 123.456;
1597+
UPDATE rw_view SET b = 'text', c = 123.456;
1598+
SELECT * FROM parent_tbl ORDER BY a;
1599+
1600+
DROP VIEW rw_view;
1601+
DROP TABLE child_local;
1602+
DROP FOREIGN TABLE child_foreign;
1603+
DROP TABLE sub_parent;
1604+
DROP TABLE parent_tbl;
1605+
15831606
-- ===================================================================
15841607
-- test serial columns (ie, sequence-based defaults)
15851608
-- ===================================================================

src/backend/optimizer/util/inherit.c

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static Bitmapset *translate_col_privs(const Bitmapset *parent_privs,
5252
static Bitmapset *translate_col_privs_multilevel(PlannerInfo *root,
5353
RelOptInfo *rel,
5454
RelOptInfo *top_parent_rel,
55-
Bitmapset *top_parent_cols);
55+
Bitmapset *parent_cols);
5656
static void expand_appendrel_subquery(PlannerInfo *root, RelOptInfo *rel,
5757
RangeTblEntry *rte, Index rti);
5858

@@ -923,28 +923,26 @@ apply_child_basequals(PlannerInfo *root, RelOptInfo *parentrel,
923923

924924
/*
925925
* translate_col_privs_multilevel
926-
* Recursively translates the column numbers contained in
927-
* 'top_parent_cols' to the columns numbers of a descendent relation
928-
* given by 'relid'
926+
* Recursively translates the column numbers contained in 'parent_cols'
927+
* to the columns numbers of a descendent relation given by 'rel'
929928
*/
930929
static Bitmapset *
931930
translate_col_privs_multilevel(PlannerInfo *root, RelOptInfo *rel,
932931
RelOptInfo *top_parent_rel,
933-
Bitmapset *top_parent_cols)
932+
Bitmapset *parent_cols)
934933
{
935-
Bitmapset *result;
936934
AppendRelInfo *appinfo;
937935

938-
if (top_parent_cols == NULL)
936+
if (parent_cols == NULL)
939937
return NULL;
940938

941939
/* Recurse if immediate parent is not the top parent. */
942940
if (rel->parent != top_parent_rel)
943941
{
944942
if (rel->parent)
945-
result = translate_col_privs_multilevel(root, rel->parent,
946-
top_parent_rel,
947-
top_parent_cols);
943+
parent_cols = translate_col_privs_multilevel(root, rel->parent,
944+
top_parent_rel,
945+
parent_cols);
948946
else
949947
elog(ERROR, "rel with relid %u is not a child rel", rel->relid);
950948
}
@@ -953,7 +951,5 @@ translate_col_privs_multilevel(PlannerInfo *root, RelOptInfo *rel,
953951
appinfo = root->append_rel_array[rel->relid];
954952
Assert(appinfo != NULL);
955953

956-
result = translate_col_privs(top_parent_cols, appinfo->translated_vars);
957-
958-
return result;
954+
return translate_col_privs(parent_cols, appinfo->translated_vars);
959955
}

0 commit comments

Comments
 (0)