aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_dump/pg_dump.c
diff options
context:
space:
mode:
authorDaniel Gustafsson <dgustafsson@postgresql.org>2023-11-29 14:56:24 +0100
committerDaniel Gustafsson <dgustafsson@postgresql.org>2023-11-29 14:56:24 +0100
commita5cf808be55bcc68c3917c380f95122436af1be1 (patch)
tree68f5bac3e1612ac30980be826f326904fdc59c17 /src/bin/pg_dump/pg_dump.c
parent15c9ac3629936a9bb5010155d3656e913027ccb7 (diff)
downloadpostgresql-a5cf808be55bcc68c3917c380f95122436af1be1.tar.gz
postgresql-a5cf808be55bcc68c3917c380f95122436af1be1.zip
Read include/exclude commands for dump/restore from file
When there is a need to filter multiple tables with include and/or exclude options it's quite possible to run into the limitations of the commandline. This adds a --filter=FILENAME feature to pg_dump, pg_dumpall and pg_restore which is used to supply a file containing object exclude/include commands which work just like their commandline counterparts. The format of the file is one command per row like: <command> <object> <objectpattern> <command> can be "include" or "exclude", <object> can be table_data, index table_data_and_children, database, extension, foreign_data, function, table schema, table_and_children or trigger. This patch has gone through many revisions and design changes over a long period of time, the list of reviewers reflect reviewers of some version of the patch, not necessarily the final version. Patch by Pavel Stehule with some additional hacking by me. Author: Pavel Stehule <pavel.stehule@gmail.com> Reviewed-by: Justin Pryzby <pryzby@telsasoft.com> Reviewed-by: vignesh C <vignesh21@gmail.com> Reviewed-by: Dean Rasheed <dean.a.rasheed@gmail.com> Reviewed-by: Tomas Vondra <tomas.vondra@enterprisedb.com> Reviewed-by: Julien Rouhaud <rjuju123@gmail.com> Reviewed-by: Erik Rijkers <er@xs4all.nl> Discussion: https://postgr.es/m/CAFj8pRB10wvW0CC9Xq=1XDs=zCQxer3cbLcNZa+qiX4cUH-G_A@mail.gmail.com
Diffstat (limited to 'src/bin/pg_dump/pg_dump.c')
-rw-r--r--src/bin/pg_dump/pg_dump.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 34fd0a86e9c..64e2d754d12 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -60,6 +60,7 @@
#include "dumputils.h"
#include "fe_utils/option_utils.h"
#include "fe_utils/string_utils.h"
+#include "filter.h"
#include "getopt_long.h"
#include "libpq/libpq-fs.h"
#include "parallel.h"
@@ -327,6 +328,7 @@ static char *get_synchronized_snapshot(Archive *fout);
static void setupDumpWorker(Archive *AH);
static TableInfo *getRootTableInfo(const TableInfo *tbinfo);
static bool forcePartitionRootLoad(const TableInfo *tbinfo);
+static void read_dump_filters(const char *filename, DumpOptions *dopt);
int
@@ -433,6 +435,7 @@ main(int argc, char **argv)
{"exclude-table-and-children", required_argument, NULL, 13},
{"exclude-table-data-and-children", required_argument, NULL, 14},
{"sync-method", required_argument, NULL, 15},
+ {"filter", required_argument, NULL, 16},
{NULL, 0, NULL, 0}
};
@@ -664,6 +667,10 @@ main(int argc, char **argv)
exit_nicely(1);
break;
+ case 16: /* read object filters from file */
+ read_dump_filters(optarg, &dopt);
+ break;
+
default:
/* getopt_long already emitted a complaint */
pg_log_error_hint("Try \"%s --help\" for more information.", progname);
@@ -1111,6 +1118,8 @@ help(const char *progname)
" do NOT dump data for the specified table(s),\n"
" including child and partition tables\n"));
printf(_(" --extra-float-digits=NUM override default setting for extra_float_digits\n"));
+ printf(_(" --filter=FILENAME include or exclude objects and data from dump\n"
+ " based expressions in FILENAME\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"
@@ -18771,3 +18780,112 @@ appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
if (!res)
pg_log_warning("could not parse %s array", "reloptions");
}
+
+/*
+ * read_dump_filters - retrieve object identifier patterns from file
+ *
+ * Parse the specified filter file for include and exclude patterns, and add
+ * them to the relevant lists. If the filename is "-" then filters will be
+ * read from STDIN rather than a file.
+ */
+static void
+read_dump_filters(const char *filename, DumpOptions *dopt)
+{
+ FilterStateData fstate;
+ char *objname;
+ FilterCommandType comtype;
+ FilterObjectType objtype;
+
+ filter_init(&fstate, filename, exit_nicely);
+
+ while (filter_read_item(&fstate, &objname, &comtype, &objtype))
+ {
+ if (comtype == FILTER_COMMAND_TYPE_INCLUDE)
+ {
+ switch (objtype)
+ {
+ case FILTER_OBJECT_TYPE_NONE:
+ break;
+ case FILTER_OBJECT_TYPE_DATABASE:
+ case FILTER_OBJECT_TYPE_FUNCTION:
+ case FILTER_OBJECT_TYPE_INDEX:
+ case FILTER_OBJECT_TYPE_TABLE_DATA:
+ case FILTER_OBJECT_TYPE_TABLE_DATA_AND_CHILDREN:
+ case FILTER_OBJECT_TYPE_TRIGGER:
+ pg_log_filter_error(&fstate, _("%s filter for \"%s\" is not allowed."),
+ "include",
+ filter_object_type_name(objtype));
+ exit_nicely(1);
+ break; /* unreachable */
+
+ case FILTER_OBJECT_TYPE_EXTENSION:
+ simple_string_list_append(&extension_include_patterns, objname);
+ break;
+ case FILTER_OBJECT_TYPE_FOREIGN_DATA:
+ simple_string_list_append(&foreign_servers_include_patterns, objname);
+ break;
+ case FILTER_OBJECT_TYPE_SCHEMA:
+ simple_string_list_append(&schema_include_patterns, objname);
+ dopt->include_everything = false;
+ break;
+ case FILTER_OBJECT_TYPE_TABLE:
+ simple_string_list_append(&table_include_patterns, objname);
+ dopt->include_everything = false;
+ break;
+ case FILTER_OBJECT_TYPE_TABLE_AND_CHILDREN:
+ simple_string_list_append(&table_include_patterns_and_children,
+ objname);
+ dopt->include_everything = false;
+ break;
+ }
+ }
+ else if (comtype == FILTER_COMMAND_TYPE_EXCLUDE)
+ {
+ switch (objtype)
+ {
+ case FILTER_OBJECT_TYPE_NONE:
+ break;
+ case FILTER_OBJECT_TYPE_DATABASE:
+ case FILTER_OBJECT_TYPE_FUNCTION:
+ case FILTER_OBJECT_TYPE_INDEX:
+ case FILTER_OBJECT_TYPE_TRIGGER:
+ case FILTER_OBJECT_TYPE_EXTENSION:
+ case FILTER_OBJECT_TYPE_FOREIGN_DATA:
+ pg_log_filter_error(&fstate, _("%s filter for \"%s\" is not allowed."),
+ "exclude",
+ filter_object_type_name(objtype));
+ exit_nicely(1);
+ break;
+
+ case FILTER_OBJECT_TYPE_TABLE_DATA:
+ simple_string_list_append(&tabledata_exclude_patterns,
+ objname);
+ break;
+ case FILTER_OBJECT_TYPE_TABLE_DATA_AND_CHILDREN:
+ simple_string_list_append(&tabledata_exclude_patterns_and_children,
+ objname);
+ break;
+ case FILTER_OBJECT_TYPE_SCHEMA:
+ simple_string_list_append(&schema_exclude_patterns, objname);
+ break;
+ case FILTER_OBJECT_TYPE_TABLE:
+ simple_string_list_append(&table_exclude_patterns, objname);
+ break;
+ case FILTER_OBJECT_TYPE_TABLE_AND_CHILDREN:
+ simple_string_list_append(&table_exclude_patterns_and_children,
+ objname);
+ break;
+ }
+ }
+ else
+ {
+ Assert(comtype == FILTER_COMMAND_TYPE_NONE);
+ Assert(objtype == FILTER_OBJECT_TYPE_NONE);
+ }
+
+ if (objname)
+ free(objname);
+ }
+
+ filter_free(&fstate);
+}