mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
Disable support for partitionwise joins in problematic cases.
Commit f49842d
, which added support for partitionwise joins, built the
child's tlist by applying adjust_appendrel_attrs() to the parent's. So in
the case where the parent's included a whole-row Var for the parent, the
child's contained a ConvertRowtypeExpr. To cope with that, that commit
added code to the planner, such as setrefs.c, but some code paths still
assumed that the tlist for a scan (or join) rel would only include Vars
and PlaceHolderVars, which was true before that commit, causing errors:
* When creating an explicit sort node for an input path for a mergejoin
path for a child join, prepare_sort_from_pathkeys() threw the 'could not
find pathkey item to sort' error.
* When deparsing a relation participating in a pushed down child join as a
subquery in contrib/postgres_fdw, get_relation_column_alias_ids() threw
the 'unexpected expression in subquery output' error.
* When performing set_plan_references() on a local join plan generated by
contrib/postgres_fdw for EvalPlanQual support for a pushed down child
join, fix_join_expr() threw the 'variable not found in subplan target
lists' error.
To fix these, two approaches have been proposed: one by Ashutosh Bapat and
one by me. While the former keeps building the child's tlist with a
ConvertRowtypeExpr, the latter builds it with a whole-row Var for the
child not to violate the planner assumption, and tries to fix it up later,
But both approaches need more work, so refuse to generate partitionwise
join paths when whole-row Vars are involved, instead. We don't need to
handle ConvertRowtypeExprs in the child's tlists for now, so this commit
also removes the changes to the planner.
Previously, partitionwise join computed attr_needed data for each child
separately, and built the child join's tlist using that data, which also
required an extra step for adding PlaceHolderVars to that tlist, but it
would be more efficient to build it from the parent join's tlist through
the adjust_appendrel_attrs() transformation. So this commit builds that
list that way, and simplifies build_joinrel_tlist() and placeholder.c as
well as part of set_append_rel_size() to basically what they were before
partitionwise join went in.
Back-patch to PG11 where partitionwise join was introduced.
Report by Rajkumar Raghuwanshi. Analysis by Ashutosh Bapat, who also
provided some of regression tests. Patch by me, reviewed by Robert Haas.
Discussion: https://postgr.es/m/CAKcux6ktu-8tefLWtQuuZBYFaZA83vUzuRd7c1YHC-yEWyYFpg@mail.gmail.com
This commit is contained in:
@ -8337,8 +8337,9 @@ ALTER TABLE fprt2_p1 SET (autovacuum_enabled = 'false');
|
||||
ALTER TABLE fprt2_p2 SET (autovacuum_enabled = 'false');
|
||||
INSERT INTO fprt2_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 3) i;
|
||||
INSERT INTO fprt2_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 3) i;
|
||||
CREATE FOREIGN TABLE ftprt2_p1 PARTITION OF fprt2 FOR VALUES FROM (0) TO (250)
|
||||
CREATE FOREIGN TABLE ftprt2_p1 (b int, c varchar, a int)
|
||||
SERVER loopback OPTIONS (table_name 'fprt2_p1', use_remote_estimate 'true');
|
||||
ALTER TABLE fprt2 ATTACH PARTITION ftprt2_p1 FOR VALUES FROM (0) TO (250);
|
||||
CREATE FOREIGN TABLE ftprt2_p2 PARTITION OF fprt2 FOR VALUES FROM (250) TO (500)
|
||||
SERVER loopback OPTIONS (table_name 'fprt2_p2', use_remote_estimate 'true');
|
||||
ANALYZE fprt2;
|
||||
@ -8389,28 +8390,42 @@ SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10)
|
||||
8 | |
|
||||
(5 rows)
|
||||
|
||||
-- with whole-row reference
|
||||
-- with whole-row reference; partitionwise join does not apply
|
||||
EXPLAIN (COSTS OFF)
|
||||
SELECT t1,t2 FROM fprt1 t1 JOIN fprt2 t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a % 25 =0 ORDER BY 1,2;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------------
|
||||
SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2;
|
||||
QUERY PLAN
|
||||
--------------------------------------------------------
|
||||
Sort
|
||||
Sort Key: ((t1.*)::fprt1), ((t2.*)::fprt2)
|
||||
-> Append
|
||||
-> Foreign Scan
|
||||
Relations: (public.ftprt1_p1 t1) INNER JOIN (public.ftprt2_p1 t2)
|
||||
-> Foreign Scan
|
||||
Relations: (public.ftprt1_p2 t1) INNER JOIN (public.ftprt2_p2 t2)
|
||||
(7 rows)
|
||||
-> Hash Full Join
|
||||
Hash Cond: (t1.a = t2.b)
|
||||
-> Append
|
||||
-> Foreign Scan on ftprt1_p1 t1
|
||||
-> Foreign Scan on ftprt1_p2 t1_1
|
||||
-> Hash
|
||||
-> Append
|
||||
-> Foreign Scan on ftprt2_p1 t2
|
||||
-> Foreign Scan on ftprt2_p2 t2_1
|
||||
(11 rows)
|
||||
|
||||
SELECT t1,t2 FROM fprt1 t1 JOIN fprt2 t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a % 25 =0 ORDER BY 1,2;
|
||||
t1 | t2
|
||||
SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2;
|
||||
wr | wr
|
||||
----------------+----------------
|
||||
(0,0,0000) | (0,0,0000)
|
||||
(50,50,0001) |
|
||||
(100,100,0002) |
|
||||
(150,150,0003) | (150,150,0003)
|
||||
(200,200,0004) |
|
||||
(250,250,0005) | (250,250,0005)
|
||||
(300,300,0006) |
|
||||
(350,350,0007) |
|
||||
(400,400,0008) | (400,400,0008)
|
||||
(4 rows)
|
||||
(450,450,0009) |
|
||||
| (75,75,0001)
|
||||
| (225,225,0004)
|
||||
| (325,325,0006)
|
||||
| (475,475,0009)
|
||||
(14 rows)
|
||||
|
||||
-- join with lateral reference
|
||||
EXPLAIN (COSTS OFF)
|
||||
@ -8474,6 +8489,34 @@ SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE
|
||||
| | 475 | t2_phv
|
||||
(14 rows)
|
||||
|
||||
-- test FOR UPDATE; partitionwise join does not apply
|
||||
EXPLAIN (COSTS OFF)
|
||||
SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1;
|
||||
QUERY PLAN
|
||||
--------------------------------------------------------------
|
||||
LockRows
|
||||
-> Sort
|
||||
Sort Key: t1.a
|
||||
-> Hash Join
|
||||
Hash Cond: (t2.b = t1.a)
|
||||
-> Append
|
||||
-> Foreign Scan on ftprt2_p1 t2
|
||||
-> Foreign Scan on ftprt2_p2 t2_1
|
||||
-> Hash
|
||||
-> Append
|
||||
-> Foreign Scan on ftprt1_p1 t1
|
||||
-> Foreign Scan on ftprt1_p2 t1_1
|
||||
(12 rows)
|
||||
|
||||
SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1;
|
||||
a | b
|
||||
-----+-----
|
||||
0 | 0
|
||||
150 | 150
|
||||
250 | 250
|
||||
400 | 400
|
||||
(4 rows)
|
||||
|
||||
RESET enable_partitionwise_join;
|
||||
-- ===================================================================
|
||||
-- test partitionwise aggregates
|
||||
|
Reference in New Issue
Block a user