From c91334a891490e0541522f0bf1872b4e7b45f802 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Mon, 16 Nov 2020 21:26:42 -0600
Subject: [PATCH 2/2] f!Read additional cmdline args from config

---
 src/bin/pg_dump/pg_dump.c               | 719 +++++++++++-------------
 src/bin/pg_dump/t/004_pg_dump_filter.pl |  50 +-
 2 files changed, 337 insertions(+), 432 deletions(-)

diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index f1f9e8321e..00bbbbf5c6 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -296,109 +296,38 @@ static void appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
 static char *get_synchronized_snapshot(Archive *fout);
 static void setupDumpWorker(Archive *AHX);
 static TableInfo *getRootTableInfo(TableInfo *tbinfo);
-static void read_patterns_from_file(char *filename, DumpOptions *dopt);
-
+static void read_config_file(char *filename, DumpOptions *dopt);
+static void xgetopt(int argc, char **argv, DumpOptions *dopt);
+
+const char *filename = NULL;
+const char *format = "p";
+char	   *endptr;
+const char *dumpencoding = NULL;
+const char *dumpsnapshot = NULL;
+char	   *use_role = NULL;
+long		rowsPerInsert;
+int			numWorkers = 1;
+int			compressLevel = -1;
+int			plainText = 0;
+bool		g_verbose = false;
+char		*configfile = NULL;
+
+static DumpOptions dopt;
 
 int
 main(int argc, char **argv)
 {
-	int			c;
-	const char *filename = NULL;
-	const char *format = "p";
 	TableInfo  *tblinfo;
 	int			numTables;
 	DumpableObject **dobjs;
 	int			numObjs;
 	DumpableObject *boundaryObjs;
 	int			i;
-	int			optindex;
-	char	   *endptr;
 	RestoreOptions *ropt;
 	Archive    *fout;			/* the script file */
-	bool		g_verbose = false;
-	const char *dumpencoding = NULL;
-	const char *dumpsnapshot = NULL;
-	char	   *use_role = NULL;
-	long		rowsPerInsert;
-	int			numWorkers = 1;
-	int			compressLevel = -1;
-	int			plainText = 0;
 	ArchiveFormat archiveFormat = archUnknown;
 	ArchiveMode archiveMode;
 
-	static DumpOptions dopt;
-
-	static struct option long_options[] = {
-		{"data-only", no_argument, NULL, 'a'},
-		{"blobs", no_argument, NULL, 'b'},
-		{"no-blobs", no_argument, NULL, 'B'},
-		{"clean", no_argument, NULL, 'c'},
-		{"create", no_argument, NULL, 'C'},
-		{"dbname", required_argument, NULL, 'd'},
-		{"file", required_argument, NULL, 'f'},
-		{"format", required_argument, NULL, 'F'},
-		{"host", required_argument, NULL, 'h'},
-		{"jobs", 1, NULL, 'j'},
-		{"no-reconnect", no_argument, NULL, 'R'},
-		{"no-owner", no_argument, NULL, 'O'},
-		{"port", required_argument, NULL, 'p'},
-		{"schema", required_argument, NULL, 'n'},
-		{"exclude-schema", required_argument, NULL, 'N'},
-		{"schema-only", no_argument, NULL, 's'},
-		{"superuser", required_argument, NULL, 'S'},
-		{"table", required_argument, NULL, 't'},
-		{"exclude-table", required_argument, NULL, 'T'},
-		{"no-password", no_argument, NULL, 'w'},
-		{"password", no_argument, NULL, 'W'},
-		{"username", required_argument, NULL, 'U'},
-		{"verbose", no_argument, NULL, 'v'},
-		{"no-privileges", no_argument, NULL, 'x'},
-		{"no-acl", no_argument, NULL, 'x'},
-		{"compress", required_argument, NULL, 'Z'},
-		{"encoding", required_argument, NULL, 'E'},
-		{"help", no_argument, NULL, '?'},
-		{"version", no_argument, NULL, 'V'},
-
-		/*
-		 * the following options don't have an equivalent short option letter
-		 */
-		{"attribute-inserts", no_argument, &dopt.column_inserts, 1},
-		{"binary-upgrade", no_argument, &dopt.binary_upgrade, 1},
-		{"column-inserts", no_argument, &dopt.column_inserts, 1},
-		{"disable-dollar-quoting", no_argument, &dopt.disable_dollar_quoting, 1},
-		{"disable-triggers", no_argument, &dopt.disable_triggers, 1},
-		{"enable-row-security", no_argument, &dopt.enable_row_security, 1},
-		{"exclude-table-data", required_argument, NULL, 4},
-		{"extra-float-digits", required_argument, NULL, 8},
-		{"filter", required_argument, NULL, 12},
-		{"if-exists", no_argument, &dopt.if_exists, 1},
-		{"inserts", no_argument, NULL, 9},
-		{"lock-wait-timeout", required_argument, NULL, 2},
-		{"no-tablespaces", no_argument, &dopt.outputNoTablespaces, 1},
-		{"quote-all-identifiers", no_argument, &quote_all_identifiers, 1},
-		{"load-via-partition-root", no_argument, &dopt.load_via_partition_root, 1},
-		{"role", required_argument, NULL, 3},
-		{"section", required_argument, NULL, 5},
-		{"serializable-deferrable", no_argument, &dopt.serializable_deferrable, 1},
-		{"snapshot", required_argument, NULL, 6},
-		{"strict-names", no_argument, &strict_names, 1},
-		{"use-set-session-authorization", no_argument, &dopt.use_setsessauth, 1},
-		{"no-comments", no_argument, &dopt.no_comments, 1},
-		{"no-publications", no_argument, &dopt.no_publications, 1},
-		{"no-security-labels", no_argument, &dopt.no_security_labels, 1},
-		{"no-synchronized-snapshots", no_argument, &dopt.no_synchronized_snapshots, 1},
-		{"no-unlogged-table-data", no_argument, &dopt.no_unlogged_table_data, 1},
-		{"no-subscriptions", no_argument, &dopt.no_subscriptions, 1},
-		{"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},
-		{"index-collation-versions-unknown", no_argument, &dopt.coll_unknown, 1},
-		{"include-foreign-data-file", required_argument, NULL, 17},
-
-		{NULL, 0, NULL, 0}
-	};
-
 	pg_logging_init(argv[0]);
 	pg_logging_set_level(PG_LOG_WARNING);
 	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
@@ -427,200 +356,7 @@ main(int argc, char **argv)
 
 	InitDumpOptions(&dopt);
 
-	while ((c = getopt_long(argc, argv, "abBcCd:E:f:F:h:j:n:N:Op:RsS:t:T:U:vwWxZ:",
-							long_options, &optindex)) != -1)
-	{
-		switch (c)
-		{
-			case 'a':			/* Dump data only */
-				dopt.dataOnly = true;
-				break;
-
-			case 'b':			/* Dump blobs */
-				dopt.outputBlobs = true;
-				break;
-
-			case 'B':			/* Don't dump blobs */
-				dopt.dontOutputBlobs = true;
-				break;
-
-			case 'c':			/* clean (i.e., drop) schema prior to create */
-				dopt.outputClean = 1;
-				break;
-
-			case 'C':			/* Create DB */
-				dopt.outputCreateDB = 1;
-				break;
-
-			case 'd':			/* database name */
-				dopt.cparams.dbname = pg_strdup(optarg);
-				break;
-
-			case 'E':			/* Dump encoding */
-				dumpencoding = pg_strdup(optarg);
-				break;
-
-			case 'f':
-				filename = pg_strdup(optarg);
-				break;
-
-			case 'F':
-				format = pg_strdup(optarg);
-				break;
-
-			case 'h':			/* server host */
-				dopt.cparams.pghost = pg_strdup(optarg);
-				break;
-
-			case 'j':			/* number of dump jobs */
-				numWorkers = atoi(optarg);
-				break;
-
-			case 'n':			/* include schema(s) */
-				simple_string_list_append(&schema_include_patterns, optarg);
-				dopt.include_everything = false;
-				break;
-
-			case 'N':			/* exclude schema(s) */
-				simple_string_list_append(&schema_exclude_patterns, optarg);
-				break;
-
-			case 'O':			/* Don't reconnect to match owner */
-				dopt.outputNoOwner = 1;
-				break;
-
-			case 'p':			/* server port */
-				dopt.cparams.pgport = pg_strdup(optarg);
-				break;
-
-			case 'R':
-				/* no-op, still accepted for backwards compatibility */
-				break;
-
-			case 's':			/* dump schema only */
-				dopt.schemaOnly = true;
-				break;
-
-			case 'S':			/* Username for superuser in plain text output */
-				dopt.outputSuperuser = pg_strdup(optarg);
-				break;
-
-			case 't':			/* include table(s) */
-				simple_string_list_append(&table_include_patterns, optarg);
-				dopt.include_everything = false;
-				break;
-
-			case 'T':			/* exclude table(s) */
-				simple_string_list_append(&table_exclude_patterns, optarg);
-				break;
-
-			case 'U':
-				dopt.cparams.username = pg_strdup(optarg);
-				break;
-
-			case 'v':			/* verbose */
-				g_verbose = true;
-				pg_logging_increase_verbosity();
-				break;
-
-			case 'w':
-				dopt.cparams.promptPassword = TRI_NO;
-				break;
-
-			case 'W':
-				dopt.cparams.promptPassword = TRI_YES;
-				break;
-
-			case 'x':			/* skip ACL dump */
-				dopt.aclsSkip = true;
-				break;
-
-			case 'Z':			/* Compression Level */
-				compressLevel = atoi(optarg);
-				if (compressLevel < 0 || compressLevel > 9)
-				{
-					pg_log_error("compression level must be in range 0..9");
-					exit_nicely(1);
-				}
-				break;
-
-			case 0:
-				/* This covers the long options. */
-				break;
-
-			case 2:				/* lock-wait-timeout */
-				dopt.lockWaitTimeout = pg_strdup(optarg);
-				break;
-
-			case 3:				/* SET ROLE */
-				use_role = pg_strdup(optarg);
-				break;
-
-			case 4:				/* exclude table(s) data */
-				simple_string_list_append(&tabledata_exclude_patterns, optarg);
-				break;
-
-			case 5:				/* section */
-				set_dump_section(optarg, &dopt.dumpSections);
-				break;
-
-			case 6:				/* snapshot */
-				dumpsnapshot = pg_strdup(optarg);
-				break;
-
-			case 7:				/* no-sync */
-				dosync = false;
-				break;
-
-			case 8:
-				have_extra_float_digits = true;
-				extra_float_digits = atoi(optarg);
-				if (extra_float_digits < -15 || extra_float_digits > 3)
-				{
-					pg_log_error("extra_float_digits must be in range -15..3");
-					exit_nicely(1);
-				}
-				break;
-
-			case 9:				/* inserts */
-
-				/*
-				 * dump_inserts also stores --rows-per-insert, careful not to
-				 * overwrite that.
-				 */
-				if (dopt.dump_inserts == 0)
-					dopt.dump_inserts = DUMP_DEFAULT_ROWS_PER_INSERT;
-				break;
-
-			case 10:			/* rows per insert */
-				errno = 0;
-				rowsPerInsert = strtol(optarg, &endptr, 10);
-
-				if (endptr == optarg || *endptr != '\0' ||
-					rowsPerInsert <= 0 || rowsPerInsert > INT_MAX ||
-					errno == ERANGE)
-				{
-					pg_log_error("rows-per-insert must be in range %d..%d",
-								 1, INT_MAX);
-					exit_nicely(1);
-				}
-				dopt.dump_inserts = (int) rowsPerInsert;
-				break;
-
-			case 11:			/* include foreign data */
-				simple_string_list_append(&foreign_servers_include_patterns,
-										  optarg);
-				break;
-
-			case 12:			/* filter implementation */
-				read_patterns_from_file(optarg, &dopt);
-				break;
-
-			default:
-				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
-				exit_nicely(1);
-		}
-	}
+	xgetopt(argc, argv, &dopt);
 
 	/*
 	 * Non-option argument specifies database name as long as it wasn't
@@ -639,6 +375,9 @@ main(int argc, char **argv)
 		exit_nicely(1);
 	}
 
+	if (configfile)
+		read_config_file(configfile, &dopt);
+
 	/* --column-inserts implies --inserts */
 	if (dopt.column_inserts && dopt.dump_inserts == 0)
 		dopt.dump_inserts = DUMP_DEFAULT_ROWS_PER_INSERT;
@@ -1000,6 +739,280 @@ main(int argc, char **argv)
 	exit_nicely(0);
 }
 
+static struct option long_options[] = {
+	{"data-only", no_argument, NULL, 'a'},
+	{"blobs", no_argument, NULL, 'b'},
+	{"no-blobs", no_argument, NULL, 'B'},
+	{"clean", no_argument, NULL, 'c'},
+	{"create", no_argument, NULL, 'C'},
+	{"dbname", required_argument, NULL, 'd'},
+	{"file", required_argument, NULL, 'f'},
+	{"format", required_argument, NULL, 'F'},
+	{"host", required_argument, NULL, 'h'},
+	{"jobs", 1, NULL, 'j'},
+	{"no-reconnect", no_argument, NULL, 'R'},
+	{"no-owner", no_argument, NULL, 'O'},
+	{"port", required_argument, NULL, 'p'},
+	{"schema", required_argument, NULL, 'n'},
+	{"exclude-schema", required_argument, NULL, 'N'},
+	{"schema-only", no_argument, NULL, 's'},
+	{"superuser", required_argument, NULL, 'S'},
+	{"table", required_argument, NULL, 't'},
+	{"exclude-table", required_argument, NULL, 'T'},
+	{"no-password", no_argument, NULL, 'w'},
+	{"password", no_argument, NULL, 'W'},
+	{"username", required_argument, NULL, 'U'},
+	{"verbose", no_argument, NULL, 'v'},
+	{"no-privileges", no_argument, NULL, 'x'},
+	{"no-acl", no_argument, NULL, 'x'},
+	{"compress", required_argument, NULL, 'Z'},
+	{"encoding", required_argument, NULL, 'E'},
+	{"help", no_argument, NULL, '?'},
+	{"version", no_argument, NULL, 'V'},
+
+	/*
+	 * the following options don't have an equivalent short option letter
+	 */
+	{"attribute-inserts", no_argument, &dopt.column_inserts, 1},
+	{"binary-upgrade", no_argument, &dopt.binary_upgrade, 1},
+	{"column-inserts", no_argument, &dopt.column_inserts, 1},
+	{"disable-dollar-quoting", no_argument, &dopt.disable_dollar_quoting, 1},
+	{"disable-triggers", no_argument, &dopt.disable_triggers, 1},
+	{"enable-row-security", no_argument, &dopt.enable_row_security, 1},
+	{"exclude-table-data", required_argument, NULL, 4},
+	{"extra-float-digits", required_argument, NULL, 8},
+	// {"config", required_argument, NULL, 12},
+	{"config", required_argument, NULL, 12},
+	{"if-exists", no_argument, &dopt.if_exists, 1},
+	{"inserts", no_argument, NULL, 9},
+	{"lock-wait-timeout", required_argument, NULL, 2},
+	{"no-tablespaces", no_argument, &dopt.outputNoTablespaces, 1},
+	{"quote-all-identifiers", no_argument, &quote_all_identifiers, 1},
+	{"load-via-partition-root", no_argument, &dopt.load_via_partition_root, 1},
+	{"role", required_argument, NULL, 3},
+	{"section", required_argument, NULL, 5},
+	{"serializable-deferrable", no_argument, &dopt.serializable_deferrable, 1},
+	{"snapshot", required_argument, NULL, 6},
+	{"strict-names", no_argument, &strict_names, 1},
+	{"use-set-session-authorization", no_argument, &dopt.use_setsessauth, 1},
+	{"no-comments", no_argument, &dopt.no_comments, 1},
+	{"no-publications", no_argument, &dopt.no_publications, 1},
+	{"no-security-labels", no_argument, &dopt.no_security_labels, 1},
+	{"no-synchronized-snapshots", no_argument, &dopt.no_synchronized_snapshots, 1},
+	{"no-unlogged-table-data", no_argument, &dopt.no_unlogged_table_data, 1},
+	{"no-subscriptions", no_argument, &dopt.no_subscriptions, 1},
+	{"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},
+	{"index-collation-versions-unknown", no_argument, &dopt.coll_unknown, 1},
+	{"include-foreign-data-file", required_argument, NULL, 17},
+
+	{NULL, 0, NULL, 0}
+};
+
+static void
+xgetopt(int argc, char **argv, DumpOptions *dopt)
+{
+	int			c;
+	int			optindex;
+
+	while ((c = getopt_long(argc, argv, "abBcCd:E:f:F:h:j:n:N:Op:RsS:t:T:U:vwWxZ:",
+							long_options, &optindex)) != -1)
+	{
+		switch (c)
+		{
+			case 'a':			/* Dump data only */
+				dopt->dataOnly = true;
+				break;
+
+			case 'b':			/* Dump blobs */
+				dopt->outputBlobs = true;
+				break;
+
+			case 'B':			/* Don't dump blobs */
+				dopt->dontOutputBlobs = true;
+				break;
+
+			case 'c':			/* clean (i.e., drop) schema prior to create */
+				dopt->outputClean = 1;
+				break;
+
+			case 'C':			/* Create DB */
+				dopt->outputCreateDB = 1;
+				break;
+
+			case 'd':			/* database name */
+				dopt->cparams.dbname = pg_strdup(optarg);
+				break;
+
+			case 'E':			/* Dump encoding */
+				dumpencoding = pg_strdup(optarg);
+				break;
+
+			case 'f':
+				filename = pg_strdup(optarg);
+				break;
+
+			case 'F':
+				format = pg_strdup(optarg);
+				break;
+
+			case 'h':			/* server host */
+				dopt->cparams.pghost = pg_strdup(optarg);
+				break;
+
+			case 'j':			/* number of dump jobs */
+				numWorkers = atoi(optarg);
+				break;
+
+			case 'n':			/* include schema(s) */
+				simple_string_list_append(&schema_include_patterns, optarg);
+				dopt->include_everything = false;
+				break;
+
+			case 'N':			/* exclude schema(s) */
+				simple_string_list_append(&schema_exclude_patterns, optarg);
+				break;
+
+			case 'O':			/* Don't reconnect to match owner */
+				dopt->outputNoOwner = 1;
+				break;
+
+			case 'p':			/* server port */
+				dopt->cparams.pgport = pg_strdup(optarg);
+				break;
+
+			case 'R':
+				/* no-op, still accepted for backwards compatibility */
+				break;
+
+			case 's':			/* dump schema only */
+				dopt->schemaOnly = true;
+				break;
+
+			case 'S':			/* Username for superuser in plain text output */
+				dopt->outputSuperuser = pg_strdup(optarg);
+				break;
+
+			case 't':			/* include table(s) */
+				simple_string_list_append(&table_include_patterns, optarg);
+				dopt->include_everything = false;
+				break;
+
+			case 'T':			/* exclude table(s) */
+				simple_string_list_append(&table_exclude_patterns, optarg);
+				break;
+
+			case 'U':
+				dopt->cparams.username = pg_strdup(optarg);
+				break;
+
+			case 'v':			/* verbose */
+				g_verbose = true;
+				pg_logging_increase_verbosity();
+				break;
+
+			case 'w':
+				dopt->cparams.promptPassword = TRI_NO;
+				break;
+
+			case 'W':
+				dopt->cparams.promptPassword = TRI_YES;
+				break;
+
+			case 'x':			/* skip ACL dump */
+				dopt->aclsSkip = true;
+				break;
+
+			case 'Z':			/* Compression Level */
+				compressLevel = atoi(optarg);
+				if (compressLevel < 0 || compressLevel > 9)
+				{
+					pg_log_error("compression level must be in range 0..9");
+					exit_nicely(1);
+				}
+				break;
+
+			case 0:
+				/* This covers the long options. */
+				break;
+
+			case 2:				/* lock-wait-timeout */
+				dopt->lockWaitTimeout = pg_strdup(optarg);
+				break;
+
+			case 3:				/* SET ROLE */
+				use_role = pg_strdup(optarg);
+				break;
+
+			case 4:				/* exclude table(s) data */
+				simple_string_list_append(&tabledata_exclude_patterns, optarg);
+				break;
+
+			case 5:				/* section */
+				set_dump_section(optarg, &dopt->dumpSections);
+				break;
+
+			case 6:				/* snapshot */
+				dumpsnapshot = pg_strdup(optarg);
+				break;
+
+			case 7:				/* no-sync */
+				dosync = false;
+				break;
+
+			case 8:
+				have_extra_float_digits = true;
+				extra_float_digits = atoi(optarg);
+				if (extra_float_digits < -15 || extra_float_digits > 3)
+				{
+					pg_log_error("extra_float_digits must be in range -15..3");
+					exit_nicely(1);
+				}
+				break;
+
+			case 9:				/* inserts */
+
+				/*
+				 * dump_inserts also stores --rows-per-insert, careful not to
+				 * overwrite that.
+				 */
+				if (dopt->dump_inserts == 0)
+					dopt->dump_inserts = DUMP_DEFAULT_ROWS_PER_INSERT;
+				break;
+
+			case 10:			/* rows per insert */
+				errno = 0;
+				rowsPerInsert = strtol(optarg, &endptr, 10);
+
+				if (endptr == optarg || *endptr != '\0' ||
+					rowsPerInsert <= 0 || rowsPerInsert > INT_MAX ||
+					errno == ERANGE)
+				{
+					pg_log_error("rows-per-insert must be in range %d..%d",
+								 1, INT_MAX);
+					exit_nicely(1);
+				}
+				dopt->dump_inserts = (int) rowsPerInsert;
+				break;
+
+			case 11:			/* include foreign data */
+				simple_string_list_append(&foreign_servers_include_patterns,
+										  optarg);
+				break;
+
+			case 12:			/* config implementation */
+				// read_config_file(optarg, dopt);
+				configfile = optarg;
+				break;
+
+			default:
+				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+				exit_nicely(1);
+		}
+	}
+}
 
 static void
 help(const char *progname)
@@ -1044,8 +1057,7 @@ help(const char *progname)
 			 "                               access to)\n"));
 	printf(_("  --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n"));
 	printf(_("  --extra-float-digits=NUM     override default setting for extra_float_digits\n"));
-	printf(_("  --filter=FILENAME            dump objects and data based on the filter expressions\n"
-			 "                               from the filter file\n"));
+	printf(_("  --config=FILENAME            read additional command line argument config from file\n"));
 	printf(_("  --if-exists                  use IF EXISTS when dropping objects\n"));
 	printf(_("  --include-foreign-data=PATTERN\n"
 			 "                               include data of foreign tables on foreign\n"
@@ -18644,32 +18656,10 @@ appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
 		pg_log_warning("could not parse reloptions array");
 }
 
-/*
- * Print error message and exit.
- */
 static void
-exit_invalid_filter_format(FILE *fp, char *filename, char *message, char *line, int lineno)
-{
-	pg_log_error("invalid format of filter file \"%s\": %s",
-				 filename,
-				 message);
-
-	fprintf(stderr, "%d: %s\n", lineno, line);
-
-	if (fp != stdin)
-		fclose(fp);
-
-	exit_nicely(-1);
-}
-
-/*
- * Read dumped object specification from file
- */
-static void
-read_patterns_from_file(char *filename, DumpOptions *dopt)
+read_config_file(char *filename, DumpOptions *dopt)
 {
 	FILE	   *fp;
-	int			lineno = 0;
 	StringInfoData line;
 
 	/* use "-" as symbol for stdin */
@@ -18685,111 +18675,44 @@ read_patterns_from_file(char *filename, DumpOptions *dopt)
 
 	initStringInfo(&line);
 
-	while (pg_get_line_buf(fp, &line))
+	while (pg_get_line_buf(fp, &line)) // XXX: need to read a "logical" line
 	{
-		bool		is_include;
-		char		objecttype;
-		char	   *objectname;
-		char	   *str = line.data;
-
-		lineno += 1;
+		char	*str = line.data;
+		int		argc;
+		char	*argv[] = {"pg_dump", str, NULL, NULL};
+		char	*argv2;
 
 		(void) pg_strip_crlf(str);
 
-		/* ignore empty rows */
+		/* ignore empty lines */
 		if (*str == '\0')
 			continue;
 
+		/* skip initial spaces */
+		while (isspace(*str))
+			str++;
+
 		/* when first char is hash, ignore whole line */
 		if (*str == '#')
 			continue;
 
-		if (str[1] == '\0')
-			exit_invalid_filter_format(fp,
-									   filename,
-									   "line too short",
-									   str,
-									   lineno);
-
-		if (str[0] == '+')
-			is_include = true;
-		else if (str[0] == '-')
-			is_include = false;
-		else
-			exit_invalid_filter_format(fp,
-									   filename,
-									   "invalid option type (use [+-]",
-									   str,
-									   lineno);
-
-		objecttype = str[1];
-		objectname = &str[2];
-
-		/* skip initial spaces */
-		while (isspace(*objectname))
-			objectname++;
+		/* Not allowed to set dbname */
+		if (*str != '-')
+			fatal("invalid line in file \"%s\": %s", filename, str);
 
-		if (*objectname == '\0')
-			exit_invalid_filter_format(fp,
-									   filename,
-									   "missing object name",
-									   str,
-									   lineno);
-
-		if (objecttype == 't')
-		{
-			if (is_include)
-			{
-				simple_string_list_append(&table_include_patterns,
-										  objectname);
-				dopt->include_everything = false;
-			}
-			else
-				simple_string_list_append(&table_exclude_patterns,
-										  objectname);
-		}
-		else if (objecttype == 'n')
-		{
-			if (is_include)
-			{
-				simple_string_list_append(&schema_include_patterns,
-										  objectname);
-				dopt->include_everything = false;
-			}
-			else
-				simple_string_list_append(&schema_exclude_patterns,
-										  objectname);
-		}
-		else if (objecttype == 'd')
-		{
-			if (is_include)
-				exit_invalid_filter_format(fp,
-										   filename,
-										   "include filter is not supported for this type of object",
-										   str,
-										   lineno);
-			else
-				simple_string_list_append(&tabledata_exclude_patterns,
-										  objectname);
-		}
-		else if (objecttype == 'f')
+		argv2 = strchr(str, ' ');
+		if (argv2 == NULL)
+			argc = 2;
+		else
 		{
-			if (is_include)
-				simple_string_list_append(&foreign_servers_include_patterns,
-										  objectname);
-			else
-				exit_invalid_filter_format(fp,
-										   filename,
-										   "exclude filter is not supported for this type of object",
-										   str,
-										   lineno);
+			argc = 3;
+			*argv2 = '\0';
+			argv[2] = argv2 + 1;
+			// fprintf(stderr, "passing argv %s..%s\n", argv[1], argv[2]);
 		}
-		else
-			exit_invalid_filter_format(fp,
-									   filename,
-									   "invalid object type (use [tndf])",
-									   str,
-									   lineno);
+
+		optind = 0; /* Reset it */
+		xgetopt(argc, argv, dopt);
 	}
 
 	pfree(line.data);
diff --git a/src/bin/pg_dump/t/004_pg_dump_filter.pl b/src/bin/pg_dump/t/004_pg_dump_filter.pl
index 957442c5e4..77632a7b99 100644
--- a/src/bin/pg_dump/t/004_pg_dump_filter.pl
+++ b/src/bin/pg_dump/t/004_pg_dump_filter.pl
@@ -4,7 +4,7 @@ use warnings;
 use Config;
 use PostgresNode;
 use TestLib;
-use Test::More tests => 22;
+use Test::More tests => 18;
 
 my $tempdir       = TestLib::tempdir;
 my $inputfile;
@@ -27,16 +27,16 @@ $node->safe_psql('postgres', "INSERT INTO table_three VALUES('*** TABLE THREE **
 
 open $inputfile, '>', "$tempdir/inputfile.txt";
 
-print $inputfile "+t table_one\n";
-print $inputfile "+t table_two\n";
+print $inputfile "-t table_one\n";
+print $inputfile "-t table_two\n";
 print $inputfile "# skip this line\n";
 print $inputfile "\n";
-print $inputfile "-d table_one\n";
+print $inputfile "--exclude-table-data table_one\n";
 close $inputfile;
 
 my ($cmd, $stdout, $stderr, $result);
 command_ok(
-	[ "pg_dump", '-p', $port, "-f", $plainfile, "--filter=$tempdir/inputfile.txt", 'postgres' ],
+	[ "pg_dump", '-p', $port, "-f", $plainfile, "--config=$tempdir/inputfile.txt", 'postgres' ],
 	"dump tables with filter");
 
 my $dump = slurp_file($plainfile);
@@ -49,11 +49,11 @@ ok($dump =~ qr/^COPY public.table_two/m, "content of table two is included");
 
 open $inputfile, '>', "$tempdir/inputfile.txt";
 
-print $inputfile "-t table_one\n";
+print $inputfile "-T table_one\n";
 close $inputfile;
 
 command_ok(
-	[ "pg_dump", '-p', $port, "-f", $plainfile, "--filter=$tempdir/inputfile.txt", 'postgres' ],
+	[ "pg_dump", '-p', $port, "-f", $plainfile, "--config=$tempdir/inputfile.txt", 'postgres' ],
 	"dump tables with filter");
 
 $dump = slurp_file($plainfile);
@@ -64,11 +64,11 @@ ok($dump =~ qr/^CREATE TABLE public.table_three/m, "dumped table three");
 
 open $inputfile, '>', "$tempdir/inputfile.txt";
 
-print $inputfile "-n public\n";
+print $inputfile "-N public\n";
 close $inputfile;
 
 command_ok(
-	[ "pg_dump", '-p', $port, "-f", $plainfile, "--filter=$tempdir/inputfile.txt", 'postgres' ],
+	[ "pg_dump", '-p', $port, "-f", $plainfile, "--config=$tempdir/inputfile.txt", 'postgres' ],
 	"dump tables with filter");
 
 $dump = slurp_file($plainfile);
@@ -81,11 +81,11 @@ ok($dump !~ qr/^CREATE TABLE/m, "no table dumped");
 
 open $inputfile, '>', "$tempdir/inputfile.txt";
 
-print $inputfile "+f doesnt_exists\n";
+print $inputfile "--include-foreign-data=doesnt_exists\n";
 close $inputfile;
 
 command_fails_like(
-	[ "pg_dump", '-p', $port, "-f", $plainfile, "--filter=$tempdir/inputfile.txt", 'postgres' ],
+	[ "pg_dump", '-p', $port, "-f", $plainfile, "--config=$tempdir/inputfile.txt", 'postgres' ],
 	qr/pg_dump: error: no matching foreign servers were found for pattern/,
 	"dump foreign server");
 
@@ -97,33 +97,15 @@ print $inputfile "k";
 close $inputfile;
 
 command_fails_like(
-	[ "pg_dump", '-p', $port, "-f", $plainfile, "--filter=$tempdir/inputfile.txt", 'postgres' ],
-	qr/pg_dump: error: invalid format of filter file/,
-	"broken format check");
-
-open $inputfile, '>', "$tempdir/inputfile.txt";
-print $inputfile "+";
-close $inputfile;
-
-command_fails_like(
-	[ "pg_dump", '-p', $port, "-f", $plainfile, "--filter=$tempdir/inputfile.txt", 'postgres' ],
-	qr/pg_dump: error: invalid format of filter file/,
-	"broken format check");
-
-open $inputfile, '>', "$tempdir/inputfile.txt";
-print $inputfile "+d sometable";
-close $inputfile;
-
-command_fails_like(
-	[ "pg_dump", '-p', $port, "-f", $plainfile, "--filter=$tempdir/inputfile.txt", 'postgres' ],
-	qr/include filter is not supported for this type of object/,
+	[ "pg_dump", '-p', $port, "-f", $plainfile, "--config=$tempdir/inputfile.txt", 'postgres' ],
+	qr/pg_dump: error: invalid line in file "[^"]*": k/,
 	"broken format check");
 
 open $inputfile, '>', "$tempdir/inputfile.txt";
-print $inputfile "-f someforeignserver";
+print $inputfile "-k";
 close $inputfile;
 
 command_fails_like(
-	[ "pg_dump", '-p', $port, "-f", $plainfile, "--filter=$tempdir/inputfile.txt", 'postgres' ],
-	qr/exclude filter is not supported for this type of object/,
+	[ "pg_dump", '-p', $port, "-f", $plainfile, "--config=$tempdir/inputfile.txt", 'postgres' ],
+	qr/pg_dump: invalid option -- 'k'/,
 	"broken format check");
-- 
2.17.0

