Skip to content

Commit 35746bc

Browse files
committed
Add new FDW API to test for parallel-safety.
This is basically a bug fix; the old code assumes that a ForeignScan is always parallel-safe, but for postgres_fdw, for example, this is definitely false. It should be true for file_fdw, though, since a worker can read a file from the filesystem just as well as any other backend process. Original patch by Thomas Munro. Documentation, and changes to the comments, by me.
1 parent 9117985 commit 35746bc

File tree

4 files changed

+60
-0
lines changed

4 files changed

+60
-0
lines changed

contrib/file_fdw/file_fdw.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ static void fileEndForeignScan(ForeignScanState *node);
131131
static bool fileAnalyzeForeignTable(Relation relation,
132132
AcquireSampleRowsFunc *func,
133133
BlockNumber *totalpages);
134+
static bool fileIsForeignScanParallelSafe(PlannerInfo *root, RelOptInfo *rel,
135+
RangeTblEntry *rte);
134136

135137
/*
136138
* Helper functions
@@ -170,6 +172,7 @@ file_fdw_handler(PG_FUNCTION_ARGS)
170172
fdwroutine->ReScanForeignScan = fileReScanForeignScan;
171173
fdwroutine->EndForeignScan = fileEndForeignScan;
172174
fdwroutine->AnalyzeForeignTable = fileAnalyzeForeignTable;
175+
fdwroutine->IsForeignScanParallelSafe = fileIsForeignScanParallelSafe;
173176

174177
PG_RETURN_POINTER(fdwroutine);
175178
}
@@ -761,6 +764,18 @@ fileAnalyzeForeignTable(Relation relation,
761764
return true;
762765
}
763766

767+
/*
768+
* fileIsForeignScanParallelSafe
769+
* Reading a file in a parallel worker should work just the same as
770+
* reading it in the leader, so mark scans safe.
771+
*/
772+
static bool
773+
fileIsForeignScanParallelSafe(PlannerInfo *root, RelOptInfo *rel,
774+
RangeTblEntry *rte)
775+
{
776+
return true;
777+
}
778+
764779
/*
765780
* check_selective_binary_conversion
766781
*

doc/src/sgml/fdwhandler.sgml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,29 @@ ImportForeignSchema (ImportForeignSchemaStmt *stmt, Oid serverOid);
988988
<para>
989989
<programlisting>
990990
Size
991+
IsForeignScanParallelSafe(PlannerInfo *root, RelOptInfo *rel,
992+
RangeTblEntry *rte);
993+
</programlisting>
994+
Test whether a scan can be performed within a parallel worker. This
995+
function will only be called when the planner believes that a parallel
996+
plan might be possible, and should return true if it is safe for that scan
997+
to run within a parallel worker. This will generally not be the case if
998+
the remote data source has transaction semantics, unless the worker's
999+
connection to the data can somehow be made to share the same transaction
1000+
context as the leader.
1001+
</para>
1002+
1003+
<para>
1004+
If this callback is not defined, it is assumed that the scan must take
1005+
place within the parallel leader. Note that returning true does not mean
1006+
that the scan itself can be done in parallel, only that the scan can be
1007+
performed within a parallel worker. Therefore, it can be useful to define
1008+
this method even when parallel execution is not supported.
1009+
</para>
1010+
1011+
<para>
1012+
<programlisting>
1013+
Size
9911014
EstimateDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt);
9921015
</programlisting>
9931016
Estimate the amount of dynamic shared memory that will be required

src/backend/optimizer/path/allpaths.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,23 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
527527
return;
528528
return;
529529
}
530+
531+
/*
532+
* Ask FDWs whether they can support performing a ForeignScan
533+
* within a worker. Most often, the answer will be no. For
534+
* example, if the nature of the FDW is such that it opens a TCP
535+
* connection with a remote server, each parallel worker would end
536+
* up with a separate connection, and these connections might not
537+
* be appropriately coordinated between workers and the leader.
538+
*/
539+
if (rte->relkind == RELKIND_FOREIGN_TABLE)
540+
{
541+
Assert(rel->fdwroutine);
542+
if (!rel->fdwroutine->IsForeignScanParallelSafe)
543+
return;
544+
if (!rel->fdwroutine->IsForeignScanParallelSafe(root, rel, rte))
545+
return;
546+
}
530547
break;
531548

532549
case RTE_SUBQUERY:

src/include/foreign/fdwapi.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ typedef void (*InitializeDSMForeignScan_function) (ForeignScanState *node,
131131
typedef void (*InitializeWorkerForeignScan_function) (ForeignScanState *node,
132132
shm_toc *toc,
133133
void *coordinate);
134+
typedef bool (*IsForeignScanParallelSafe_function) (PlannerInfo *root,
135+
RelOptInfo *rel,
136+
RangeTblEntry *rte);
137+
134138
/*
135139
* FdwRoutine is the struct returned by a foreign-data wrapper's handler
136140
* function. It provides pointers to the callback functions needed by the
@@ -188,6 +192,7 @@ typedef struct FdwRoutine
188192
ImportForeignSchema_function ImportForeignSchema;
189193

190194
/* Support functions for parallelism under Gather node */
195+
IsForeignScanParallelSafe_function IsForeignScanParallelSafe;
191196
EstimateDSMForeignScan_function EstimateDSMForeignScan;
192197
InitializeDSMForeignScan_function InitializeDSMForeignScan;
193198
InitializeWorkerForeignScan_function InitializeWorkerForeignScan;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy