Yes we can support --include-foreign-data without parallel option and
later add support for parallel option as a different patch.

Hi,

    I've attached a new version of the patch in which an error is emitted if 
the parallel backup is used with the --include-foreign-data option.


Cheers


Luis M. Carril


diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml
index 4bcd4bdaef..319851b936 100644
--- a/doc/src/sgml/ref/pg_dump.sgml
+++ b/doc/src/sgml/ref/pg_dump.sgml
@@ -767,6 +767,34 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>--include-foreign-data=<replaceable class="parameter">foreignserver</replaceable></option></term>
+      <listitem>
+       <para>
+        Dump the data for any foreign table with a foreign server
+        matching <replaceable class="parameter">foreignserver</replaceable>
+        pattern. Multiple foreign servers can be selected by writing multiple <option>--include-foreign-data</option>.
+        Also, the <replaceable class="parameter">foreignserver</replaceable> parameter is
+        interpreted as a pattern according to the same rules used by
+        <application>psql</application>'s <literal>\d</literal> commands (see <xref
+        linkend="app-psql-patterns" endterm="app-psql-patterns-title"/>),
+        so multiple foreign servers can also be selected by writing wildcard characters
+        in the pattern.  When using wildcards, be careful to quote the pattern
+        if needed to prevent the shell from expanding the wildcards;  see
+        <xref linkend="pg-dump-examples" endterm="pg-dump-examples-title"/>.
+        The only exception is that an empty pattern is disallowed.
+       </para>
+
+       <note>
+        <para>
+         When <option>--include-foreign-data</option> is specified, <application>pg_dump</application>
+         does not check if the foreign table is also writeable. Therefore, there is no guarantee that 
+         the results of a foreign table dump can be successfully restored by themselves into a clean database.
+        </para>
+       </note>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>--inserts</option></term>
       <listitem>
diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h
index 8c0cedcd98..d255162c7a 100644
--- a/src/bin/pg_dump/pg_backup.h
+++ b/src/bin/pg_dump/pg_backup.h
@@ -141,6 +141,7 @@ typedef struct _dumpOptions
 	bool		aclsSkip;
 	const char *lockWaitTimeout;
 	int			dump_inserts;	/* 0 = COPY, otherwise rows per INSERT */
+	bool		include_foreign_data;
 
 	/* flags for various command-line long options */
 	int			disable_dollar_quoting;
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 799b6988b7..13156357dd 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -120,6 +120,8 @@ static SimpleStringList table_exclude_patterns = {NULL, NULL};
 static SimpleOidList table_exclude_oids = {NULL, NULL};
 static SimpleStringList tabledata_exclude_patterns = {NULL, NULL};
 static SimpleOidList tabledata_exclude_oids = {NULL, NULL};
+static SimpleStringList foreign_servers_include_patterns = {NULL, NULL};
+static SimpleOidList foreign_servers_include_oids = {NULL, NULL};
 
 
 char		g_opaque_type[10];	/* name for the opaque type */
@@ -156,6 +158,9 @@ static void expand_schema_name_patterns(Archive *fout,
 										SimpleStringList *patterns,
 										SimpleOidList *oids,
 										bool strict_names);
+static void expand_foreign_server_name_patterns(Archive *fout,
+										SimpleStringList *patterns,
+										SimpleOidList *oids);
 static void expand_table_name_patterns(Archive *fout,
 									   SimpleStringList *patterns,
 									   SimpleOidList *oids,
@@ -388,6 +393,7 @@ main(int argc, char **argv)
 		{"no-sync", no_argument, NULL, 7},
 		{"on-conflict-do-nothing", no_argument, &dopt.do_nothing, 1},
 		{"rows-per-insert", required_argument, NULL, 10},
+		{"include-foreign-data", required_argument, NULL, 11},
 
 		{NULL, 0, NULL, 0}
 	};
@@ -604,6 +610,13 @@ main(int argc, char **argv)
 				dopt.dump_inserts = (int) rowsPerInsert;
 				break;
 
+			case 11:				/* include foreign data */
+				if (strcmp(optarg, "") == 0)
+					fatal("empty string is not a valid pattern in --include-foreign-data");
+				simple_string_list_append(&foreign_servers_include_patterns, optarg);
+				dopt.include_foreign_data = true;
+				break;
+
 			default:
 				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
 				exit_nicely(1);
@@ -645,6 +658,12 @@ main(int argc, char **argv)
 		exit_nicely(1);
 	}
 
+	if (dopt.schemaOnly && foreign_servers_include_patterns.head != NULL)
+		fatal("options -s/--schema-only and --include-foreign-data cannot be used together");
+
+	if (numWorkers > 1 && foreign_servers_include_patterns.head != NULL)
+		fatal("option --include-foreign-data is not supported with parallel backup");
+
 	if (dopt.dataOnly && dopt.outputClean)
 	{
 		pg_log_error("options -c/--clean and -a/--data-only cannot be used together");
@@ -812,6 +831,9 @@ main(int argc, char **argv)
 							   &tabledata_exclude_oids,
 							   false);
 
+	expand_foreign_server_name_patterns(fout, &foreign_servers_include_patterns,
+										&foreign_servers_include_oids);
+
 	/* non-matching exclusion patterns aren't an error */
 
 	/*
@@ -1035,6 +1057,9 @@ help(const char *progname)
 	printf(_("  --use-set-session-authorization\n"
 			 "                               use SET SESSION AUTHORIZATION commands instead of\n"
 			 "                               ALTER OWNER commands to set ownership\n"));
+	printf(_("  --include-foreign-data=PATTERN\n"
+			 "                               include data of foreign tables with the named\n"
+			 "                               foreign servers in dump\n"));
 
 	printf(_("\nConnection options:\n"));
 	printf(_("  -d, --dbname=DBNAME      database to dump\n"));
@@ -1333,6 +1358,53 @@ expand_schema_name_patterns(Archive *fout,
 	destroyPQExpBuffer(query);
 }
 
+/*
+ * Find the OIDs of all foreign servers matching the given list of patterns,
+ * and append them to the given OID list.
+ */
+static void
+expand_foreign_server_name_patterns(Archive *fout,
+							SimpleStringList *patterns,
+							SimpleOidList *oids)
+{
+	PQExpBuffer query;
+	PGresult   *res;
+	SimpleStringListCell *cell;
+	int			i;
+
+	if (patterns->head == NULL)
+		return;					/* nothing to do */
+
+	query = createPQExpBuffer();
+
+	/*
+	 * The loop below runs multiple SELECTs might sometimes result in
+	 * duplicate entries in the OID list, but we don't care.
+	 */
+
+	for (cell = patterns->head; cell; cell = cell->next)
+	{
+		appendPQExpBuffer(query,
+						  "SELECT oid FROM pg_catalog.pg_foreign_server s\n");
+		processSQLNamePattern(GetConnection(fout), query, cell->val, false,
+							  false, NULL, "s.srvname", NULL, NULL);
+
+		res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+		if (PQntuples(res) == 0)
+			fatal("no matching foreign servers were found for pattern \"%s\"", cell->val);
+
+		for (i = 0; i < PQntuples(res); i++)
+		{
+			simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
+		}
+
+		PQclear(res);
+		resetPQExpBuffer(query);
+	}
+
+	destroyPQExpBuffer(query);
+}
+
 /*
  * Find the OIDs of all tables matching the given list of patterns,
  * and append them to the given OID list. See also expand_dbname_patterns()
@@ -1809,7 +1881,11 @@ dumpTableData_copy(Archive *fout, void *dcontext)
 	 */
 	column_list = fmtCopyColumnList(tbinfo, clistBuf);
 
-	if (tdinfo->filtercond)
+	/*
+	 * COPY TO does not support foreign tables directly, instead we do a
+	 * COPY (SELECT ...) TO.
+	 */
+	if (tdinfo->filtercond || tbinfo->relkind == RELKIND_FOREIGN_TABLE)
 	{
 		/* Note: this syntax is only supported in 8.2 and up */
 		appendPQExpBufferStr(q, "COPY (SELECT ");
@@ -1821,9 +1897,11 @@ dumpTableData_copy(Archive *fout, void *dcontext)
 		}
 		else
 			appendPQExpBufferStr(q, "* ");
-		appendPQExpBuffer(q, "FROM %s %s) TO stdout;",
-						  fmtQualifiedDumpable(tbinfo),
-						  tdinfo->filtercond);
+
+		appendPQExpBuffer(q, "FROM %s", fmtQualifiedDumpable(tbinfo));
+		if (tdinfo->filtercond)
+			appendPQExpBuffer(q, " %s", tdinfo->filtercond);
+		appendPQExpBuffer(q, ") TO stdout;");
 	}
 	else
 	{
@@ -2339,8 +2417,11 @@ makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo)
 	/* Skip VIEWs (no data to dump) */
 	if (tbinfo->relkind == RELKIND_VIEW)
 		return;
-	/* Skip FOREIGN TABLEs (no data to dump) */
-	if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
+	/* Skip FOREIGN TABLEs (no data to dump) if not requested explicitly */
+	if (tbinfo->relkind == RELKIND_FOREIGN_TABLE &&
+		(foreign_servers_include_oids.head == NULL ||
+		!simple_oid_list_member(&foreign_servers_include_oids,
+								tbinfo->foreign_server_oid)))
 		return;
 	/* Skip partitioned tables (data in partitions) */
 	if (tbinfo->relkind == RELKIND_PARTITIONED_TABLE)
@@ -6648,6 +6729,25 @@ getTables(Archive *fout, int *numTables)
 		tblinfo[i].ispartition = (strcmp(PQgetvalue(res, i, i_ispartition), "t") == 0);
 		tblinfo[i].partbound = pg_strdup(PQgetvalue(res, i, i_partbound));
 
+		if (dopt->include_foreign_data &&
+			tblinfo[i].relkind == RELKIND_FOREIGN_TABLE)
+		{
+			PQExpBuffer query_server = createPQExpBuffer();
+			PGresult   *res_server;
+
+			/* retrieve the oid of the foreign server*/
+			appendPQExpBuffer(query_server,
+							  "SELECT ftserver "
+							  "FROM pg_catalog.pg_foreign_table "
+							  "WHERE ftrelid = '%u'",
+							  tblinfo[i].dobj.catId.oid);
+
+			res_server = ExecuteSqlQueryForSingleRow(fout, query_server->data);
+			tblinfo[i].foreign_server_oid = atooid(PQgetvalue(res_server, 0, 0));
+			PQclear(res_server);
+			destroyPQExpBuffer(query_server);
+		}
+
 		/*
 		 * Read-lock target tables to make sure they aren't DROPPED or altered
 		 * in schema before we get around to dumping them.
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 21004e5078..caf4fa7946 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -322,6 +322,7 @@ typedef struct _tableInfo
 	char	   *partbound;		/* partition bound definition */
 	bool		needs_override; /* has GENERATED ALWAYS AS IDENTITY */
 	char	   *amname;			/* relation access method */
+	Oid			foreign_server_oid; /* foreign server oid */
 
 	/*
 	 * Stuff computed only for dumpable tables.
diff --git a/src/bin/pg_dump/t/001_basic.pl b/src/bin/pg_dump/t/001_basic.pl
index 9ca8a8e608..af56ad6183 100644
--- a/src/bin/pg_dump/t/001_basic.pl
+++ b/src/bin/pg_dump/t/001_basic.pl
@@ -4,7 +4,7 @@ use warnings;
 use Config;
 use PostgresNode;
 use TestLib;
-use Test::More tests => 74;
+use Test::More tests => 80;
 
 my $tempdir       = TestLib::tempdir;
 my $tempdir_short = TestLib::tempdir_short;
@@ -49,6 +49,24 @@ command_fails_like(
 	'pg_dump: options -s/--schema-only and -a/--data-only cannot be used together'
 );
 
+command_fails_like(
+	[ 'pg_dump', '-s', '--include-foreign-data', 'xxx' ],
+	qr/\Qpg_dump: error: options -s\/--schema-only and --include-foreign-data cannot be used together\E/,
+	'pg_dump: options -s/--schema-only and --include-foreign-data cannot be used together'
+);
+
+command_fails_like(
+	[ 'pg_dump', '-j2', '--include-foreign-data', 'xxx' ],
+	qr/\Qpg_dump: error: option --include-foreign-data is not supported with parallel backup\E/,
+	'pg_dump: option --include-foreign-data is not supported with parallel backup'
+);
+
+command_fails_like(
+	[ 'pg_dump', '--include-foreign-data', '' ],
+	qr/\Qpg_dump: error: empty string is not a valid pattern in --include-foreign-data\E/,
+	'pg_dump: empty string is not a valid pattern in --include-foreign-data'
+);
+
 command_fails_like(
 	['pg_restore'],
 	qr{\Qpg_restore: error: one of -d/--dbname and -f/--file must be specified\E},
diff --git a/src/test/modules/test_pg_dump/Makefile b/src/test/modules/test_pg_dump/Makefile
index 6123b994f6..6f95a83b57 100644
--- a/src/test/modules/test_pg_dump/Makefile
+++ b/src/test/modules/test_pg_dump/Makefile
@@ -1,12 +1,12 @@
 # src/test/modules/test_pg_dump/Makefile
 
-MODULE = test_pg_dump
-PGFILEDESC = "test_pg_dump - Test pg_dump with an extension"
+MODULES = test_pg_dump_fdw
+PGFILEDESC = "test_pg_dump - Test pg_dump with extensions"
 
-EXTENSION = test_pg_dump
-DATA = test_pg_dump--1.0.sql
+EXTENSION = test_pg_dump_fdw test_pg_dump
+DATA = test_pg_dump_fdw--1.0.sql test_pg_dump--1.0.sql
 
-REGRESS = test_pg_dump
+REGRESS = test_pg_dump test_pg_dump_fdw
 TAP_TESTS = 1
 
 ifdef USE_PGXS
diff --git a/src/test/modules/test_pg_dump/expected/test_pg_dump_fdw.out b/src/test/modules/test_pg_dump/expected/test_pg_dump_fdw.out
new file mode 100644
index 0000000000..dc1b6267ee
--- /dev/null
+++ b/src/test/modules/test_pg_dump/expected/test_pg_dump_fdw.out
@@ -0,0 +1,19 @@
+CREATE EXTENSION test_pg_dump_fdw;
+CREATE SERVER pg_dump_fdw FOREIGN DATA WRAPPER test_pg_dump_fdw;
+CREATE FOREIGN TABLE test_pg_dump_fdw_t (a INTEGER, b INTEGER) SERVER pg_dump_fdw;
+SELECT * FROM test_pg_dump_fdw_t;
+ a  | b  
+----+----
+  0 |  0
+  1 |  1
+  2 |  2
+  3 |  3
+  4 |  4
+  5 |  5
+  6 |  6
+  7 |  7
+  8 |  8
+  9 |  9
+ 10 | 10
+(11 rows)
+
diff --git a/src/test/modules/test_pg_dump/sql/test_pg_dump_fdw.sql b/src/test/modules/test_pg_dump/sql/test_pg_dump_fdw.sql
new file mode 100644
index 0000000000..06ad1d51a0
--- /dev/null
+++ b/src/test/modules/test_pg_dump/sql/test_pg_dump_fdw.sql
@@ -0,0 +1,7 @@
+CREATE EXTENSION test_pg_dump_fdw;
+
+CREATE SERVER pg_dump_fdw FOREIGN DATA WRAPPER test_pg_dump_fdw;
+
+CREATE FOREIGN TABLE test_pg_dump_fdw_t (a INTEGER, b INTEGER) SERVER pg_dump_fdw;
+
+SELECT * FROM test_pg_dump_fdw_t;
diff --git a/src/test/modules/test_pg_dump/t/001_base.pl b/src/test/modules/test_pg_dump/t/001_base.pl
index fb4ecf8aca..6c57d39a56 100644
--- a/src/test/modules/test_pg_dump/t/001_base.pl
+++ b/src/test/modules/test_pg_dump/t/001_base.pl
@@ -135,6 +135,13 @@ my %pgdump_runs = (
 			"$tempdir/defaults_tar_format.tar",
 		],
 	},
+	include_foreign_data => {
+		dump_cmd => [
+			'pg_dump',
+			'--include-foreign-data=test_pg_dump_fdw_server',
+			"--file=$tempdir/include_foreign_data.sql",
+		],
+	},
 	pg_dumpall_globals => {
 		dump_cmd => [
 			'pg_dumpall',                             '--no-sync',
@@ -220,6 +227,7 @@ my %full_runs = (
 	createdb        => 1,
 	defaults        => 1,
 	no_privs        => 1,
+	include_foreign_data => 1,
 	no_owner        => 1,);
 
 my %tests = (
@@ -537,6 +545,55 @@ my %tests = (
 			schema_only      => 1,
 			section_pre_data => 1,
 		},
+	},
+
+	'CREATE EXTENSION test_pg_dump_fdw' => {
+		create_order => 2,
+		create_sql   => 'CREATE EXTENSION test_pg_dump_fdw;',
+		regexp => qr/^
+			\QCREATE EXTENSION IF NOT EXISTS test_pg_dump_fdw WITH SCHEMA public;\E
+			\n/xm,
+		like => {
+			%full_runs,
+			include_foreign_data => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => { binary_upgrade => 1, },
+	},
+
+	'CREATE SERVER test_pg_dump_fdw_server FOREIGN DATA WRAPPER test_pg_dump_fdw' => {
+		create_order => 3,
+		create_sql   => 'CREATE SERVER test_pg_dump_fdw_server FOREIGN DATA WRAPPER test_pg_dump_fdw;',
+		regexp => qr/^
+			\QCREATE SERVER test_pg_dump_fdw_server FOREIGN DATA WRAPPER test_pg_dump_fdw;\E
+			\n/xm,
+		like => {
+			%full_runs,
+			include_foreign_data => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+	},
+
+	'include foreign data' => {
+		create_order => 9,
+		create_sql => 'CREATE FOREIGN TABLE t (a INTEGER, b INTEGER) SERVER test_pg_dump_fdw_server;',
+		regexp => qr/^
+			\QCOPY public.t (a, b) FROM stdin;\E\n
+			\Q0	0\E\n
+			\Q1	1\E\n
+			\Q2	2\E\n
+			\Q3	3\E\n
+			\Q4	4\E\n
+			\Q5	5\E\n
+			\Q6	6\E\n
+			\Q7	7\E\n
+			\Q8	8\E\n
+			\Q9	9\E\n
+			\Q10	10\E\n
+			/xm,
+		like => { include_foreign_data => 1, },
 	},);
 
 #########################################
diff --git a/src/test/modules/test_pg_dump/test_pg_dump_fdw--1.0.sql b/src/test/modules/test_pg_dump/test_pg_dump_fdw--1.0.sql
new file mode 100644
index 0000000000..88931393d0
--- /dev/null
+++ b/src/test/modules/test_pg_dump/test_pg_dump_fdw--1.0.sql
@@ -0,0 +1,9 @@
+\echo Use "CREATE EXTENSION test_pg_dump_fdw" to load this file. \quit
+
+CREATE FUNCTION test_pg_dump_fdw_handler()
+RETURNS fdw_handler
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+
+CREATE FOREIGN DATA WRAPPER test_pg_dump_fdw
+HANDLER test_pg_dump_fdw_handler;
diff --git a/src/test/modules/test_pg_dump/test_pg_dump_fdw.c b/src/test/modules/test_pg_dump/test_pg_dump_fdw.c
new file mode 100644
index 0000000000..72e4c01ea8
--- /dev/null
+++ b/src/test/modules/test_pg_dump/test_pg_dump_fdw.c
@@ -0,0 +1,155 @@
+#include "postgres.h"
+
+#include "catalog/pg_type.h"
+#include "foreign/fdwapi.h"
+#include "foreign/foreign.h"
+#include "optimizer/pathnode.h"
+#include "optimizer/planmain.h"
+#include "optimizer/restrictinfo.h"
+
+static int curr_row = 0;
+
+PG_MODULE_MAGIC;
+
+PG_FUNCTION_INFO_V1(test_pg_dump_fdw_handler);
+
+static void dumptestGetForeignRelSize(PlannerInfo *root,
+									  RelOptInfo *baserel,
+									  Oid foreigntableid);
+static void dumptestGetForeignPaths(PlannerInfo *root,
+									RelOptInfo *baserel,
+									Oid foreigntableid);
+static ForeignScan * dumptestGetForeignPlan(PlannerInfo *root,
+								   RelOptInfo *baserel,
+								   Oid foreigntableid,
+								   ForeignPath *best_path,
+								   List *tlist,
+								   List *scan_clauses,
+								   Plan *outer_plan);
+static void dumptestBeginForeignScan(ForeignScanState *node,
+									 int eflags);
+static TupleTableSlot * dumptestIterateForeignScan(ForeignScanState *node);
+static void dumptestReScanForeignScan(ForeignScanState *node);
+static void dumptestEndForeignScan(ForeignScanState *node);
+
+/*
+ * Handler function
+ */
+Datum
+test_pg_dump_fdw_handler(PG_FUNCTION_ARGS)
+{
+	FdwRoutine *fdwroutine = makeNode(FdwRoutine);
+
+	fdwroutine->GetForeignRelSize = dumptestGetForeignRelSize;
+	fdwroutine->GetForeignPaths = dumptestGetForeignPaths;
+	fdwroutine->GetForeignPlan = dumptestGetForeignPlan;
+	fdwroutine->BeginForeignScan = dumptestBeginForeignScan;
+	fdwroutine->IterateForeignScan = dumptestIterateForeignScan;
+	fdwroutine->ReScanForeignScan = dumptestReScanForeignScan;
+	fdwroutine->EndForeignScan = dumptestEndForeignScan;
+
+	PG_RETURN_POINTER(fdwroutine);
+}
+
+static void
+dumptestGetForeignRelSize(PlannerInfo *root,
+						  RelOptInfo *baserel,
+						  Oid foreigntableid)
+{
+	baserel->rows = 1;
+}
+
+static void
+dumptestGetForeignPaths(PlannerInfo *root,
+						RelOptInfo *baserel,
+						Oid foreigntableid)
+{
+	add_path(baserel, (Path *)
+			 create_foreignscan_path(root, baserel,
+			 						 NULL /* default pathtarget */,
+									 baserel->rows,
+									 1,
+									 1,
+									 NIL,
+									 baserel->lateral_relids,
+									 NULL,
+									 NIL));
+}
+
+static ForeignScan *
+dumptestGetForeignPlan(PlannerInfo *root,
+					   RelOptInfo *baserel,
+					   Oid foreigntableid,
+					   ForeignPath *best_path,
+					   List *tlist,
+					   List *scan_clauses,
+					   Plan *outer_plan)
+{
+	scan_clauses = extract_actual_clauses(scan_clauses, false);
+	
+	return make_foreignscan(tlist,
+							scan_clauses,
+							baserel->relid,
+							NIL,
+							best_path->fdw_private,
+							NIL,
+							NIL,
+							outer_plan);
+}
+
+static void
+dumptestBeginForeignScan(ForeignScanState *node, int eflags)
+{
+	TupleDesc		desc;
+
+	desc = node->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
+
+	for (int i = 0; i < desc->natts; i++)
+	{
+		if (desc->attrs[i].atttypid != INT4OID)
+			ereport(ERROR,
+					(errcode(ERRCODE_FDW_INVALID_DATA_TYPE),
+					 errmsg("test_pg_dump_fdw only supports INT4 columns")));
+	}
+}
+
+static TupleTableSlot *
+dumptestIterateForeignScan(ForeignScanState *node)
+{
+	TupleTableSlot *slot;
+	TupleDesc		desc;
+
+	/* limit the testcase to contain 10 rows */
+	if (curr_row > 10)
+		return NULL;
+
+	slot = node->ss.ss_ScanTupleSlot;
+	desc = slot->tts_tupleDescriptor;
+
+	ExecClearTuple(slot);
+	
+	for (int i = 0; i < desc->natts; i++)
+	{
+		slot->tts_isnull[i] = false;
+		slot->tts_values[i] = Int32GetDatum(curr_row);
+	}
+
+	ExecStoreVirtualTuple(slot);
+	curr_row++;
+
+	return slot;
+}
+
+static void
+dumptestReScanForeignScan(ForeignScanState *node)
+{
+	(void) node;
+	curr_row = 0;
+}
+
+static void
+dumptestEndForeignScan(ForeignScanState *node)
+{
+	(void) node;
+	curr_row = 0;
+}
diff --git a/src/test/modules/test_pg_dump/test_pg_dump_fdw.control b/src/test/modules/test_pg_dump/test_pg_dump_fdw.control
new file mode 100644
index 0000000000..cc4a37c441
--- /dev/null
+++ b/src/test/modules/test_pg_dump/test_pg_dump_fdw.control
@@ -0,0 +1,5 @@
+# test_pg_dump_fdw
+comment = 'hardcoded foreign-data wrapper for testing dumping foreign data'
+default_version = '1.0'
+module_pathname = '$libdir/test_pg_dump_fdw'
+relocatable = true

Reply via email to