diff options
author | Daniel Gustafsson <dgustafsson@postgresql.org> | 2023-11-29 14:56:24 +0100 |
---|---|---|
committer | Daniel Gustafsson <dgustafsson@postgresql.org> | 2023-11-29 14:56:24 +0100 |
commit | a5cf808be55bcc68c3917c380f95122436af1be1 (patch) | |
tree | 68f5bac3e1612ac30980be826f326904fdc59c17 /src/bin/pg_dump/pg_dump.c | |
parent | 15c9ac3629936a9bb5010155d3656e913027ccb7 (diff) | |
download | postgresql-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.c | 118 |
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); +} |