Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9e9931d

Browse files
author
Etsuro Fujita
committed
Re-allow FDWs and custom scan providers to replace joins with pseudoconstant quals.
This was disabled in commit6f80a8d due to the lack of support forhandling of pseudoconstant quals assigned to replaced joins increateplan.c. To re-allow it, this patch adds the support by 1)modifying the ForeignPath and CustomPath structs so that if theyrepresent foreign and custom scans replacing a join with a scan, theystore the list of RestrictInfo nodes to apply to the join, as inJoinPaths, and by 2) modifying create_scan_plan() in createplan.c sothat it uses that list in that case, instead of the baserestrictinfolist, to get pseudoconstant quals assigned to the join, as mentioned inthe commit message for that commit.Important item for the release notes: this is non-backwards-compatiblesince it modifies the ForeignPath and CustomPath structs, as mentionedabove, and changes the argument lists for FDW helper functionscreate_foreignscan_path(), create_foreign_join_path(), andcreate_foreign_upper_path().Richard Guo, with some additional changes by me, reviewed by NishantSharma, Suraj Kharage, and Richard Guo.Discussion:https://postgr.es/m/CADrsxdbcN1vejBaf8a%2BQhrZY5PXL-04mCd4GDu6qm6FigDZd6Q%40mail.gmail.com
1 parent5ffb7c7 commit9e9931d

File tree

13 files changed

+99
-76
lines changed

13 files changed

+99
-76
lines changed

‎contrib/file_fdw/file_fdw.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@ fileGetForeignPaths(PlannerInfo *root,
581581
NIL,/* no pathkeys */
582582
baserel->lateral_relids,
583583
NULL,/* no extra plan */
584+
NIL,/* no fdw_restrictinfo list */
584585
coptions));
585586

586587
/*

‎contrib/postgres_fdw/expected/postgres_fdw.out

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2316,31 +2316,21 @@ SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM
23162316
1
23172317
(10 rows)
23182318

2319-
-- join with pseudoconstant quals, not pushed down.
2319+
-- join with pseudoconstant quals
23202320
EXPLAIN (VERBOSE, COSTS OFF)
23212321
SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1 AND CURRENT_USER = SESSION_USER) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
2322-
QUERY PLAN
2323-
-------------------------------------------------------------------------------
2322+
QUERY PLAN
2323+
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
23242324
Limit
23252325
Output: t1.c1, t2.c1, t1.c3
2326-
->Sort
2326+
->Result
23272327
Output: t1.c1, t2.c1, t1.c3
2328-
Sort Key: t1.c3, t1.c1
2329-
-> Result
2330-
Output: t1.c1, t2.c1, t1.c3
2331-
One-Time Filter: (CURRENT_USER = SESSION_USER)
2332-
-> Hash Join
2333-
Output: t1.c1, t1.c3, t2.c1
2334-
Hash Cond: (t2.c1 = t1.c1)
2335-
-> Foreign Scan on public.ft2 t2
2336-
Output: t2.c1
2337-
Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
2338-
-> Hash
2339-
Output: t1.c1, t1.c3
2340-
-> Foreign Scan on public.ft1 t1
2341-
Output: t1.c1, t1.c3
2342-
Remote SQL: SELECT "C 1", c3 FROM "S 1"."T 1"
2343-
(19 rows)
2328+
One-Time Filter: (CURRENT_USER = SESSION_USER)
2329+
-> Foreign Scan
2330+
Output: t1.c1, t1.c3, t2.c1
2331+
Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2332+
Remote SQL: SELECT r1."C 1", r2."C 1", r1.c3 FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST
2333+
(9 rows)
23442334

23452335
-- non-Var items in targetlist of the nullable rel of a join preventing
23462336
-- push-down in some cases

‎contrib/postgres_fdw/postgres_fdw.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ static List *get_useful_pathkeys_for_relation(PlannerInfo *root,
524524
RelOptInfo*rel);
525525
staticList*get_useful_ecs_for_relation(PlannerInfo*root,RelOptInfo*rel);
526526
staticvoidadd_paths_with_pathkeys_for_rel(PlannerInfo*root,RelOptInfo*rel,
527-
Path*epq_path);
527+
Path*epq_path,List*restrictlist);
528528
staticvoidadd_foreign_grouping_paths(PlannerInfo*root,
529529
RelOptInfo*input_rel,
530530
RelOptInfo*grouped_rel,
@@ -1034,11 +1034,12 @@ postgresGetForeignPaths(PlannerInfo *root,
10341034
NIL,/* no pathkeys */
10351035
baserel->lateral_relids,
10361036
NULL,/* no extra plan */
1037+
NIL,/* no fdw_restrictinfo list */
10371038
NIL);/* no fdw_private list */
10381039
add_path(baserel, (Path*)path);
10391040

10401041
/* Add paths with pathkeys */
1041-
add_paths_with_pathkeys_for_rel(root,baserel,NULL);
1042+
add_paths_with_pathkeys_for_rel(root,baserel,NULL,NIL);
10421043

10431044
/*
10441045
* If we're not using remote estimates, stop here. We have no way to
@@ -1206,6 +1207,7 @@ postgresGetForeignPaths(PlannerInfo *root,
12061207
NIL,/* no pathkeys */
12071208
param_info->ppi_req_outer,
12081209
NULL,
1210+
NIL,/* no fdw_restrictinfo list */
12091211
NIL);/* no fdw_private list */
12101212
add_path(baserel, (Path*)path);
12111213
}
@@ -5991,7 +5993,7 @@ foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype,
59915993

59925994
staticvoid
59935995
add_paths_with_pathkeys_for_rel(PlannerInfo*root,RelOptInfo*rel,
5994-
Path*epq_path)
5996+
Path*epq_path,List*restrictlist)
59955997
{
59965998
List*useful_pathkeys_list=NIL;/* List of all pathkeys */
59975999
ListCell*lc;
@@ -6085,6 +6087,7 @@ add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel,
60856087
useful_pathkeys,
60866088
rel->lateral_relids,
60876089
sorted_epq_path,
6090+
NIL,/* no fdw_restrictinfo list */
60886091
NIL));
60896092
else
60906093
add_path(rel, (Path*)
@@ -6096,6 +6099,7 @@ add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel,
60966099
useful_pathkeys,
60976100
rel->lateral_relids,
60986101
sorted_epq_path,
6102+
restrictlist,
60996103
NIL));
61006104
}
61016105
}
@@ -6348,13 +6352,15 @@ postgresGetForeignJoinPaths(PlannerInfo *root,
63486352
NIL,/* no pathkeys */
63496353
joinrel->lateral_relids,
63506354
epq_path,
6355+
extra->restrictlist,
63516356
NIL);/* no fdw_private */
63526357

63536358
/* Add generated path into joinrel by add_path(). */
63546359
add_path(joinrel, (Path*)joinpath);
63556360

63566361
/* Consider pathkeys for the join relation */
6357-
add_paths_with_pathkeys_for_rel(root,joinrel,epq_path);
6362+
add_paths_with_pathkeys_for_rel(root,joinrel,epq_path,
6363+
extra->restrictlist);
63586364

63596365
/* XXX Consider parameterized paths for the join relation */
63606366
}
@@ -6735,6 +6741,7 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel,
67356741
total_cost,
67366742
NIL,/* no pathkeys */
67376743
NULL,
6744+
NIL,/* no fdw_restrictinfo list */
67386745
NIL);/* no fdw_private */
67396746

67406747
/* Add generated path into grouped_rel by add_path(). */
@@ -6868,6 +6875,7 @@ add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel,
68686875
total_cost,
68696876
root->sort_pathkeys,
68706877
NULL,/* no extra plan */
6878+
NIL,/* no fdw_restrictinfo list */
68716879
fdw_private);
68726880

68736881
/* and add it to the ordered_rel */
@@ -6983,7 +6991,8 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel,
69836991
path->total_cost,
69846992
path->pathkeys,
69856993
NULL,/* no extra plan */
6986-
NULL);/* no fdw_private */
6994+
NIL,/* no fdw_restrictinfo list */
6995+
NIL);/* no fdw_private */
69876996

69886997
/* and add it to the final_rel */
69896998
add_path(final_rel, (Path*)final_path);
@@ -7103,6 +7112,7 @@ add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel,
71037112
total_cost,
71047113
pathkeys,
71057114
NULL,/* no extra plan */
7115+
NIL,/* no fdw_restrictinfo list */
71067116
fdw_private);
71077117

71087118
/* and add it to the final_rel */

‎contrib/postgres_fdw/sql/postgres_fdw.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2
640640
EXPLAIN (VERBOSE, COSTS OFF)
641641
SELECT t1."C 1"FROM"S 1"."T 1" t1, LATERAL (SELECT DISTINCTt2.c1,t3.c1FROM ft1 t2, ft2 t3WHEREt2.c1=t3.c1ANDt2.c2=t1.c2) qORDER BY t1."C 1" OFFSET10LIMIT10;
642642
SELECT t1."C 1"FROM"S 1"."T 1" t1, LATERAL (SELECT DISTINCTt2.c1,t3.c1FROM ft1 t2, ft2 t3WHEREt2.c1=t3.c1ANDt2.c2=t1.c2) qORDER BY t1."C 1" OFFSET10LIMIT10;
643-
-- join with pseudoconstant quals, not pushed down.
643+
-- join with pseudoconstant quals
644644
EXPLAIN (VERBOSE, COSTS OFF)
645645
SELECTt1.c1,t2.c1FROM ft1 t1JOIN ft2 t2ON (t1.c1=t2.c1ANDCURRENT_USER=SESSION_USER)ORDER BYt1.c3,t1.c1 OFFSET100LIMIT10;
646646

‎doc/src/sgml/custom-scan.sgml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ typedef struct CustomPath
6262
Path path;
6363
uint32 flags;
6464
List *custom_paths;
65+
List *custom_restrictinfo;
6566
List *custom_private;
6667
const CustomPathMethods *methods;
6768
} CustomPath;
@@ -85,6 +86,10 @@ typedef struct CustomPath
8586
An optional <structfield>custom_paths</structfield> is a list of <structname>Path</structname>
8687
nodes used by this custom-path node; these will be transformed into
8788
<structname>Plan</structname> nodes by planner.
89+
As described below, custom paths can be created for join relations as
90+
well. In such a case, <structfield>custom_restrictinfo</structfield>
91+
should be used to store the set of join clauses to apply to the join the
92+
custom path replaces. Otherwise it should be NIL.
8893
<structfield>custom_private</structfield> can be used to store the custom path's
8994
private data. Private data should be stored in a form that can be handled
9095
by <literal>nodeToString</literal>, so that debugging routines that attempt to
@@ -114,6 +119,17 @@ extern PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook;
114119
responsibility of the hook to minimize duplicated work.
115120
</para>
116121

122+
<para>
123+
Note also that the set of join clauses to apply to the join,
124+
which is passed as <literal>extra-&gt;restrictlist</literal>, varies
125+
depending on the combination of inner and outer relations. A
126+
<structname>CustomPath</structname> path generated for the
127+
<literal>joinrel</literal> must contain the set of join clauses it uses,
128+
which will be used by the planner to convert the
129+
<structname>CustomPath</structname> path into a plan, if it is selected
130+
by the planner as the best path for the <literal>joinrel</literal>.
131+
</para>
132+
117133
<sect2 id="custom-scan-path-callbacks">
118134
<title>Custom Scan Path Callbacks</title>
119135

‎doc/src/sgml/fdwhandler.sgml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,17 @@ GetForeignJoinPaths(PlannerInfo *root,
333333
the responsibility of the FDW to minimize duplicated work.
334334
</para>
335335

336+
<para>
337+
Note also that the set of join clauses to apply to the join,
338+
which is passed as <literal>extra-&gt;restrictlist</literal>, varies
339+
depending on the combination of inner and outer relations. A
340+
<structname>ForeignPath</structname> path generated for the
341+
<literal>joinrel</literal> must contain the set of join clauses it uses,
342+
which will be used by the planner to convert the
343+
<structname>ForeignPath</structname> path into a plan, if it is selected
344+
by the planner as the best path for the <literal>joinrel</literal>.
345+
</para>
346+
336347
<para>
337348
If a <structname>ForeignPath</structname> path is chosen for the join, it will
338349
represent the entire join process; paths generated for the component

‎src/backend/optimizer/path/joinpath.c

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#include"optimizer/pathnode.h"
2525
#include"optimizer/paths.h"
2626
#include"optimizer/planmain.h"
27-
#include"optimizer/restrictinfo.h"
2827
#include"utils/typcache.h"
2928

3029
/* Hook for plugins to get control in add_paths_to_joinrel() */
@@ -131,7 +130,6 @@ add_paths_to_joinrel(PlannerInfo *root,
131130
{
132131
JoinPathExtraDataextra;
133132
boolmergejoin_allowed= true;
134-
boolconsider_join_pushdown= false;
135133
ListCell*lc;
136134
Relidsjoinrelids;
137135

@@ -323,34 +321,21 @@ add_paths_to_joinrel(PlannerInfo *root,
323321
hash_inner_and_outer(root,joinrel,outerrel,innerrel,
324322
jointype,&extra);
325323

326-
/*
327-
* createplan.c does not currently support handling of pseudoconstant
328-
* clauses assigned to joins pushed down by extensions; check if the
329-
* restrictlist has such clauses, and if so, disallow pushing down joins.
330-
*/
331-
if ((joinrel->fdwroutine&&
332-
joinrel->fdwroutine->GetForeignJoinPaths)||
333-
set_join_pathlist_hook)
334-
consider_join_pushdown= !has_pseudoconstant_clauses(root,
335-
restrictlist);
336-
337324
/*
338325
* 5. If inner and outer relations are foreign tables (or joins) belonging
339326
* to the same server and assigned to the same user to check access
340327
* permissions as, give the FDW a chance to push down joins.
341328
*/
342329
if (joinrel->fdwroutine&&
343-
joinrel->fdwroutine->GetForeignJoinPaths&&
344-
consider_join_pushdown)
330+
joinrel->fdwroutine->GetForeignJoinPaths)
345331
joinrel->fdwroutine->GetForeignJoinPaths(root,joinrel,
346332
outerrel,innerrel,
347333
jointype,&extra);
348334

349335
/*
350336
* 6. Finally, give extensions a chance to manipulate the path list.
351337
*/
352-
if (set_join_pathlist_hook&&
353-
consider_join_pushdown)
338+
if (set_join_pathlist_hook)
354339
set_join_pathlist_hook(root,joinrel,outerrel,innerrel,
355340
jointype,&extra);
356341
}

‎src/backend/optimizer/plan/createplan.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,8 +599,27 @@ create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
599599
* Detect whether we have any pseudoconstant quals to deal with. Then, if
600600
* we'll need a gating Result node, it will be able to project, so there
601601
* are no requirements on the child's tlist.
602+
*
603+
* If this replaces a join, it must be a foreign scan or a custom scan,
604+
* and the FDW or the custom scan provider would have stored in the best
605+
* path the list of RestrictInfo nodes to apply to the join; check against
606+
* that list in that case.
602607
*/
603-
gating_clauses=get_gating_quals(root,scan_clauses);
608+
if (IS_JOIN_REL(rel))
609+
{
610+
List*join_clauses;
611+
612+
Assert(best_path->pathtype==T_ForeignScan||
613+
best_path->pathtype==T_CustomScan);
614+
if (best_path->pathtype==T_ForeignScan)
615+
join_clauses= ((ForeignPath*)best_path)->fdw_restrictinfo;
616+
else
617+
join_clauses= ((CustomPath*)best_path)->custom_restrictinfo;
618+
619+
gating_clauses=get_gating_quals(root,join_clauses);
620+
}
621+
else
622+
gating_clauses=get_gating_quals(root,scan_clauses);
604623
if (gating_clauses)
605624
flags=0;
606625

‎src/backend/optimizer/util/pathnode.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2229,6 +2229,7 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
22292229
List*pathkeys,
22302230
Relidsrequired_outer,
22312231
Path*fdw_outerpath,
2232+
List*fdw_restrictinfo,
22322233
List*fdw_private)
22332234
{
22342235
ForeignPath*pathnode=makeNode(ForeignPath);
@@ -2250,6 +2251,7 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
22502251
pathnode->path.pathkeys=pathkeys;
22512252

22522253
pathnode->fdw_outerpath=fdw_outerpath;
2254+
pathnode->fdw_restrictinfo=fdw_restrictinfo;
22532255
pathnode->fdw_private=fdw_private;
22542256

22552257
returnpathnode;
@@ -2273,6 +2275,7 @@ create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel,
22732275
List*pathkeys,
22742276
Relidsrequired_outer,
22752277
Path*fdw_outerpath,
2278+
List*fdw_restrictinfo,
22762279
List*fdw_private)
22772280
{
22782281
ForeignPath*pathnode=makeNode(ForeignPath);
@@ -2300,6 +2303,7 @@ create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel,
23002303
pathnode->path.pathkeys=pathkeys;
23012304

23022305
pathnode->fdw_outerpath=fdw_outerpath;
2306+
pathnode->fdw_restrictinfo=fdw_restrictinfo;
23032307
pathnode->fdw_private=fdw_private;
23042308

23052309
returnpathnode;
@@ -2322,6 +2326,7 @@ create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel,
23222326
doublerows,Coststartup_cost,Costtotal_cost,
23232327
List*pathkeys,
23242328
Path*fdw_outerpath,
2329+
List*fdw_restrictinfo,
23252330
List*fdw_private)
23262331
{
23272332
ForeignPath*pathnode=makeNode(ForeignPath);
@@ -2345,6 +2350,7 @@ create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel,
23452350
pathnode->path.pathkeys=pathkeys;
23462351

23472352
pathnode->fdw_outerpath=fdw_outerpath;
2353+
pathnode->fdw_restrictinfo=fdw_restrictinfo;
23482354
pathnode->fdw_private=fdw_private;
23492355

23502356
returnpathnode;
@@ -4149,6 +4155,8 @@ do { \
41494155
FLAT_COPY_PATH(fpath,path,ForeignPath);
41504156
if (fpath->fdw_outerpath)
41514157
REPARAMETERIZE_CHILD_PATH(fpath->fdw_outerpath);
4158+
if (fpath->fdw_restrictinfo)
4159+
ADJUST_CHILD_ATTRS(fpath->fdw_restrictinfo);
41524160

41534161
/* Hand over to FDW if needed. */
41544162
rfpc_func=
@@ -4166,6 +4174,8 @@ do { \
41664174

41674175
FLAT_COPY_PATH(cpath,path,CustomPath);
41684176
REPARAMETERIZE_CHILD_PATH_LIST(cpath->custom_paths);
4177+
if (cpath->custom_restrictinfo)
4178+
ADJUST_CHILD_ATTRS(cpath->custom_restrictinfo);
41694179
if (cpath->methods&&
41704180
cpath->methods->ReparameterizeCustomPathByChild)
41714181
cpath->custom_private=

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp