[1mdiff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml[m
[1mindex 50809b4..e02359e 100644[m
[1m--- a/doc/src/sgml/ref/pg_dump.sgml[m
[1m+++ b/doc/src/sgml/ref/pg_dump.sgml[m
[36m@@ -771,6 +771,28 @@[m [mPostgreSQL documentation[m
[m
[m
[m
[32m+[m[32m [m
[32m+[m[32m [m
[32m+[m[32m [m
[32m+[m[32m When dumping data for any tables matching the table pattern, only include rows[m
[32m+[m[32m that meet the filter_clause condition.[m
[32m+[m[32m This option is useful when you want to dump only a subset of a particular table.[m
[32m+[m[32m The table pattern is interpreted according to the same rules as for .[m
[32m+[m[32m can be given more than once to[m
[32m+[m[32m provide different filters for multiple tables.[m
[32m+[m[32m Note that if multiple options refer to the same table, only the first filter_clause will be applied.[m
[32m+[m[32m If necessary, use quotes in your shell to provide an argument that contains spaces.[m
[32m+[m[32m E.g. --include-table-data-where=mytable:"created_at >= '2018-01-01' AND test = 'f'"[m
[32m+[m[32m [m
[32m+[m[32m [m
[32m+[m[32m To exclude data for all tables in the database, see .[m
[32m+[m[32m [m
[32m+[m[32m [m
[32m+[m[32m [m
[32m+[m
[32m+[m[32m [m
[m
[m
[m
[1mdiff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c[m
[1mindex d6ceb72..e2cfea1 100644[m
[1m--- a/src/bin/pg_dump/pg_dump.c[m
[1m+++ b/src/bin/pg_dump/pg_dump.c[m
[36m@@ -119,6 +119,8 @@[m [mstatic SimpleOidList schema_exclude_oids = {NULL, NULL};[m
[m
static SimpleStringList table_include_patterns = {NULL, NULL};[m
static SimpleOidList table_include_oids = {NULL, NULL};[m
[32m+[m[32mstatic SimpleStringList tabledata_include_where_patterns = {NULL, NULL};[m
[32m+[m[32mstatic SimpleOidList tabledata_include_where_oids = {NULL, NULL};[m
static SimpleStringList table_exclude_patterns = {NULL, NULL};[m
static SimpleOidList table_exclude_oids = {NULL, NULL};[m
static SimpleStringList tabledata_exclude_patterns = {NULL, NULL};[m
[36m@@ -154,7 +156,8 @@[m [mstatic void expand_schema_name_patterns(Archive *fout,[m
static void expand_table_name_patterns(Archive *fout,[m
SimpleStringList *patterns,[m
SimpleOidList *oids,[m
[31m- bool strict_names);[m
[32m+[m [32m bool strict_names,[m
[32m+[m [32m bool match_data);[m
static NamespaceInfo *findNamespace(Archive *fout, Oid nsoid);[m
static void dumpTableData(Archive *fout, TableDataInfo *tdinfo);[m
static void refreshMatViewData(Archive *fout, TableDataInfo *tdinfo);[m
[36m@@ -360,6 +363,7 @@[m [mmain(int argc, char **argv)[m
{"enable-row-security", no_argument, &dopt.enable_row_security, 1},[m
{"exclude-table-data", required_argument, NULL, 4},[m
{"if-exists", no_argument, &dopt.if_exists, 1},[m
[32m+[m [32m{"include-table-data-where", required_argument, NULL, 8},[m
{"inserts", no_argument, &dopt.dump_inserts, 1},[m
{"lock-wait-timeout", required_argument, NULL, 2},[m
{"no-tablespaces", no_argument, &dopt.outputNoTablespaces, 1},[m
[36m@@ -562,6 +566,10 @@[m [mmain(int argc, char **argv)[m
dosync = false;[m
break;[m
[m
[32m+[m [32mcase 8: /* include table(s) data WHERE clause */[m
[32m+[m [32msimple_string_list_append(&tabledata_include_where_patterns, optarg);[m
[32m+[m [32mbreak;[m
[32m+[m
default:[m
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);[m
exit_nicely(1);[m
[36m@@ -761,17 +769,26 @@[m [mmain(int argc, char **argv)[m
{[m
expand_table_name_patterns(fout, &table_include_patterns,[m
&table_include_oids,[m
[31m- strict_names);[m
[32m+[m [32m strict_names, false);[m
if (table_include_oids.head == NULL)[m
exit_horribly(NULL, "no matching tables were found\n");[m
}[m
[32m+[m [32mif (tabledata_include_where_patterns.head != NULL)[m
[32m+[m [32m{[m
[32m+[m [32mexpand_table_name_patterns(fout, &tabledata_include_where_patterns,[m
[32m+[m [32m &tabledata_include_where_oids,[m
[32m+[m [32m true, /* Always use strict names for WHERE pattern */[m
[32m+[m [32m true); /* Match extra data after ':' character in each argument */[m
[32m+[m [32mif (tabledata_include_where_oids.head == NULL)[m
[32m+[m [32mexit_horribly(NULL, "no matching tables were found for WHERE clause\n");[m
[32m+[m [32m}[m
expand_table_name_patterns(fout, &table_exclude_patterns,[m
&table_exclude_oids,[m
[31m- false);[m
[32m+[m [32m false, false);[m
[m
expand_table_name_patterns(fout, &tabledata_exclude_patterns,[m
&tabledata_exclude_oids,[m
[31m- false);[m
[32m+[m [32m false, false);[m
[m
/* non-matching exclusion patterns aren't an error */[m
[m
[36m@@ -980,6 +997,8 @@[m [mhelp(const char *progname)[m
" access to)\n"));[m
printf(_(" --exclude-table-data=TABLE do NOT dump data for the named table(s)\n"));[m
printf(_(" --if-exists use IF EXISTS when dropping objects\n"));[m
[32m+[m [32mprintf(_(" --include-table-data-where=TABLE:WHERE_CLAUSE\n"));[m
[32m+[m [32mprintf(_(" only dump selected rows for the given table(s)\n"));[m
printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));[m
printf(_(" --no-comments do not dump comments\n"));[m
printf(_(" --no-publications do not dump publications\n"));[m
[36m@@ -1290,11 +1309,13 @@[m [mexpand_schema_name_patterns(Archive *fout,[m
/*[m
* Find the OIDs of all tables matching the given list of patterns,[m
* and append them to the given OID list.[m
[32m+[m[32m * If match_data is set, then each pattern is first split on the ':' character,[m
[32m+[m[32m * and the portion after the colon is appended to the SimpleOidList extra data.[m
*/[m
static void[m
expand_table_name_patterns(Archive *fout,[m
SimpleStringList *patterns, SimpleOidList *oids,[m
[31m- bool strict_names)[m
[32m+[m [32m bool strict_names, bool match_data)[m
{[m
PQExpBuffer query;[m
PGresult *res;[m
[36m@@ -1313,6 +1334,17 @@[m [mexpand_table_name_patterns(Archive *fout,[m
[m
for (cell = patterns->head; cell; cell = cell->next)[m
{[m
[32m+[m [32m/* When match_data is set, split the pattern on the ':' chararcter,[m
[32m+[m [32m * and treat the second-half as extra data to append to the list.[m
[32m+[m [32m */[m
[32m+[m [32mchar *extra_data = NULL;[m
[32m+[m [32mif (match_data) {[m
[32m+[m [32mchar *colon_char = strchr(cell->val, ':');[m
[32m+[m [32mif (colon_char) {[m
[32m+[m [32m*colon_char = '\0'; /* overwrite the colon, terminating the string before it */[m
[32m+[m [32mextra_data = colon_char+1; /* use remaining portion of the string as extra data */[m
[32m+[m [32m}[m
[32m+[m [32m}[m
/*[m
* Query must remain ABSOLUTELY devoid of unqualified names. This[m
* would be unnecessary given a pg_table_is_visible() variant taking a[m
[36m@@ -1341,7 +1373,7 @@[m [mexpand_table_name_patterns(Archive *fout,[m
[m
for (i = 0; i < PQntuples(res); i++)[m
{[m
[31m- simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));[m
[32m+[m [32msimple_oid_list_append2(oids, atooid(PQgetvalue(res, i, 0)), extra_data);[m
}[m
[m
PQclear(res);[m
[36m@@ -2281,7 +2313,29 @@[m [mmakeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo, bool oids)[m
tdinfo->dobj.namespace = tbinfo->dobj.namespace;[m
tdinfo->tdtable = tbinfo;[m
tdinfo->oids = oids;[m
[31m- tdinfo->filtercond = NULL; /* might get set later */[m
[32m+[m [32mtdinfo->filtercond = NULL;[m
[32m+[m
[32m+[m [32m/*[m
[32m+[m [32m * --include-table-data-where=: may be provided for this table.[m
[32m+[m [32m * If provided, filter_clause will be something like "foo < 5".[m
[32m+[m [32m * Prepend "WHERE (" and append ")" to produce "WHERE (foo < 5)" as filtercond.[m
[32m+[m [32m */[m
[32m+[m [32mchar *filter_clause = NULL;[m
[32m+[m [32mif (simple_oid_list_member2(&tabledata_include_where_oids,[m
[32m+[m [32mtbinfo->dobj.catId.oid,[m
[32m+[m [32m(void**) &filter_clause))[m
[32m+[m [32m{[m
[32m+[m [32mif (filter_clause) {[m
[32m+[m [32mchar *where_clause = pg_malloc(strlen(filter_clause) + 8 + 1);[m
[32m+[m [32mstrcpy(where_clause, "WHERE (");[m
[32m+[m [32mstrcat(where_clause, filter_clause);[m
[32m+[m [32mstrcat(where_clause, ")");[m
[32m+[m [32mtdinfo->filtercond = where_clause;[m
[32m+[m [32m} else {[m
[32m+[m [32mexit_horribly(NULL, "invalid pattern provided for --include-table-data-where\n");[m
[32m+[m [32m}[m
[32m+[m [32m}[m
[32m+[m
addObjectDependency(&tdinfo->dobj, tbinfo->dobj.dumpId);[m
[m
tbinfo->dataObj = tdinfo;[m
[1mdiff --git a/src/fe_utils/simple_list.c b/src/fe_utils/simple_list.c[m
[1mindex ef94b34..726b54f 100644[m
[1m--- a/src/fe_utils/simple_list.c[m
[1m+++ b/src/fe_utils/simple_list.c[m
[36m@@ -25,11 +25,30 @@[m
void[m
simple_oid_list_append(SimpleOidList *list, Oid val)[m
{[m
[32m+[m [32msimple_oid_list_append2(list, val, NULL);[m
[32m+[m[32m}[m
[32m+[m
[32m+[m[32m/*[m
[32m+[m[32m * Is OID present in the list?[m
[32m+[m[32m */[m
[32m+[m[32mbool[m
[32m+[m[32msimple_oid_list_member(SimpleOidList *list, Oid val)[m
[32m+[m[32m{[m
[32m+[m [32mreturn simple_oid_list_member2(list, val, NULL);[m
[32m+[m[32m}[m
[32m+[m
[32m+[m[32m/*[m
[32m+[m[32m * Append an OID to the list, along with extra pointer-sized data.[m
[32m+[m[32m */[m
[32m+[m[32mvoid[m
[32m+[m[32msimple_oid_list_append2(SimpleOidList *list, Oid val, void *extra_data)[m
[32m+[m[32m{[m
SimpleOidListCell *cell;[m
[m
cell = (SimpleOidListCell *) pg_malloc(sizeof(SimpleOidListCell));[m
cell->next = NULL;[m
cell->val = val;[m
[32m+[m [32mcell->extra_data = extra_data;[m
[m
if (list->tail)[m
list->tail->next = cell;[m
[36m@@ -40,16 +59,20 @@[m [msimple_oid_list_append(SimpleOidList *list, Oid val)[m
[m
/*[m
* Is OID present in the list?[m
[32m+[m[32m * Also return extra pointer-sized data by setting extra_data paramter[m
*/[m
bool[m
[31m-simple_oid_list_member(SimpleOidList *list, Oid val)[m
[32m+[m[32msimple_oid_list_member2(SimpleOidList *list, Oid val, void **extra_data)[m
{[m
SimpleOidListCell *cell;[m
[m
for (cell = list->head; cell; cell = cell->next)[m
{[m
[31m- if (cell->val == val)[m
[32m+[m [32mif (cell->val == val) {[m
[32m+[m [32mif (extra_data)[m
[32m+[m [32m*extra_data = cell->extra_data;[m
return true;[m
[32m+[m [32m}[m
}[m
return false;[m
}[m
[1mdiff --git a/src/include/fe_utils/simple_list.h b/src/include/fe_utils/simple_list.h[m
[1mindex 9785489..40bc962 100644[m
[1m--- a/src/include/fe_utils/simple_list.h[m
[1m+++ b/src/include/fe_utils/simple_list.h[m
[36m@@ -21,6 +21,7 @@[m [mtypedef struct SimpleOidListCell[m
{[m
struct SimpleOidListCell *next;[m
Oid val;[m
[32m+[m [32mvoid *extra_data;[m
} SimpleOidListCell;[m
[m
typedef struct SimpleOidList[m
[36m@@ -47,6 +48,9 @@[m [mtypedef struct SimpleStringList[m
extern void simple_oid_list_append(SimpleOidList *list, Oid val);[m
extern bool simple_oid_list_member(SimpleOidList *list, Oid val);[m
[m
[32m+[m[32mextern void simple_oid_list_append2(SimpleOidList *list, Oid val, void *extra_data);[m
[32m+[m[32mextern bool simple_oid_list_member2(SimpleOidList *list, Oid val, void **extra_data);[m
[32m+[m
extern void simple_string_list_append(SimpleStringList *list, const char *val);[m
extern bool simple_string_list_member(SimpleStringList *list, const char *val);[m
[m