From 9a5054196a13165b9a2c752ee822b84babead275 Mon Sep 17 00:00:00 2001 From: Mark Dilger Date: Wed, 6 Jan 2021 14:07:58 -0800 Subject: [PATCH v3 7/9] Moving pg_dump functions to new file option_utils Moving the recently refactored functions expand_schema_name_patterns, expand_foreign_server_name_patterns, and expand_table_name_patterns from pg_dump.c, along with the function expand_dbname_patterns from pg_dumpall.c, into the new file fe_utils/option_utils.c --- src/bin/pg_dump/pg_dump.c | 170 +-------------------- src/bin/pg_dump/pg_dumpall.c | 46 +----- src/fe_utils/Makefile | 1 + src/fe_utils/option_utils.c | 225 ++++++++++++++++++++++++++++ src/include/fe_utils/option_utils.h | 35 +++++ 5 files changed, 263 insertions(+), 214 deletions(-) create mode 100644 src/fe_utils/option_utils.c create mode 100644 src/include/fe_utils/option_utils.h diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 41ce4b7866..c334b9e829 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -55,6 +55,7 @@ #include "catalog/pg_type_d.h" #include "common/connect.h" #include "dumputils.h" +#include "fe_utils/option_utils.h" #include "fe_utils/query_utils.h" #include "fe_utils/string_utils.h" #include "getopt_long.h" @@ -148,17 +149,6 @@ static void setup_connection(Archive *AH, const char *dumpencoding, const char *dumpsnapshot, char *use_role); static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode); -static void expand_schema_name_patterns(PGconn *conn, - SimpleStringList *patterns, - SimpleOidList *oids, - bool strict_names); -static void expand_foreign_server_name_patterns(PGconn *conn, - SimpleStringList *patterns, - SimpleOidList *oids); -static void expand_table_name_patterns(PGconn *conn, - SimpleStringList *patterns, - SimpleOidList *oids, - bool strict_names); static NamespaceInfo *findNamespace(Oid nsoid); static void dumpTableData(Archive *fout, TableDataInfo *tdinfo); static void refreshMatViewData(Archive *fout, TableDataInfo *tdinfo); @@ -1318,164 +1308,6 @@ parseArchiveFormat(const char *format, ArchiveMode *mode) return archiveFormat; } -/* - * Find the OIDs of all schemas matching the given list of patterns, - * and append them to the given OID list. - */ -static void -expand_schema_name_patterns(PGconn *conn, - SimpleStringList *patterns, - SimpleOidList *oids, - bool strict_names) -{ - 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) - { - appendPQExpBufferStr(query, - "SELECT oid FROM pg_catalog.pg_namespace n\n"); - processSQLNamePattern(conn, query, cell->val, false, - false, NULL, "n.nspname", NULL, NULL); - - res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK); - if (strict_names && PQntuples(res) == 0) - fatal("no matching schemas 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 foreign servers matching the given list of patterns, - * and append them to the given OID list. - */ -static void -expand_foreign_server_name_patterns(PGconn *conn, - 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) - { - appendPQExpBufferStr(query, - "SELECT oid FROM pg_catalog.pg_foreign_server s\n"); - processSQLNamePattern(conn, query, cell->val, false, - false, NULL, "s.srvname", NULL, NULL); - - res = ExecuteSqlQuery(conn, 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() - * in pg_dumpall.c - */ -static void -expand_table_name_patterns(PGconn *conn, - SimpleStringList *patterns, SimpleOidList *oids, - bool strict_names) -{ - PQExpBuffer query; - PGresult *res; - SimpleStringListCell *cell; - int i; - - if (patterns->head == NULL) - return; /* nothing to do */ - - query = createPQExpBuffer(); - - /* - * this might sometimes result in duplicate entries in the OID list, but - * we don't care. - */ - - for (cell = patterns->head; cell; cell = cell->next) - { - /* - * Query must remain ABSOLUTELY devoid of unqualified names. This - * would be unnecessary given a pg_table_is_visible() variant taking a - * search_path argument. - */ - appendPQExpBuffer(query, - "SELECT c.oid" - "\nFROM pg_catalog.pg_class c" - "\n LEFT JOIN pg_catalog.pg_namespace n" - "\n ON n.oid OPERATOR(pg_catalog.=) c.relnamespace" - "\nWHERE c.relkind OPERATOR(pg_catalog.=) ANY" - "\n (array['%c', '%c', '%c', '%c', '%c', '%c'])\n", - RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, - RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE, - RELKIND_PARTITIONED_TABLE); - processSQLNamePattern(conn, query, cell->val, true, - false, "n.nspname", "c.relname", NULL, - "pg_catalog.pg_table_is_visible(c.oid)"); - - ExecuteSqlStatement(conn, "RESET search_path"); - res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK); - PQclear(ExecuteSqlQueryForSingleRow(conn, - ALWAYS_SECURE_SEARCH_PATH_SQL)); - if (strict_names && PQntuples(res) == 0) - fatal("no matching tables 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); -} - /* * checkExtensionMembership * Determine whether object is an extension member, and if so, diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 807226537a..01db15dfda 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -23,6 +23,7 @@ #include "common/logging.h" #include "common/string.h" #include "dumputils.h" +#include "fe_utils/option_utils.h" #include "fe_utils/query_utils.h" #include "fe_utils/string_utils.h" #include "getopt_long.h" @@ -54,8 +55,6 @@ static PGconn *connectDatabase(const char *dbname, const char *connstr, const ch static char *constructConnStr(const char **keywords, const char **values); static PGresult *executeQuery(PGconn *conn, const char *query); static void executeCommand(PGconn *conn, const char *query); -static void expand_dbname_patterns(PGconn *conn, SimpleStringList *patterns, - SimpleStringList *names); static char pg_dump_bin[MAXPGPATH]; static const char *progname; @@ -1409,49 +1408,6 @@ dumpUserConfig(PGconn *conn, const char *username) destroyPQExpBuffer(buf); } -/* - * Find a list of database names that match the given patterns. - * See also expand_table_name_patterns() in pg_dump.c - */ -static void -expand_dbname_patterns(PGconn *conn, - SimpleStringList *patterns, - SimpleStringList *names) -{ - PQExpBuffer query; - PGresult *res; - - if (patterns->head == NULL) - return; /* nothing to do */ - - query = createPQExpBuffer(); - - /* - * The loop below runs multiple SELECTs, which might sometimes result in - * duplicate entries in the name list, but we don't care, since all we're - * going to do is test membership of the list. - */ - - for (SimpleStringListCell *cell = patterns->head; cell; cell = cell->next) - { - appendPQExpBufferStr(query, - "SELECT datname FROM pg_catalog.pg_database n\n"); - processSQLNamePattern(conn, query, cell->val, false, - false, NULL, "datname", NULL, NULL); - - res = executeQuery(conn, query->data); - for (int i = 0; i < PQntuples(res); i++) - { - simple_string_list_append(names, PQgetvalue(res, i, 0)); - } - - PQclear(res); - resetPQExpBuffer(query); - } - - destroyPQExpBuffer(query); -} - /* * Dump contents of databases. */ diff --git a/src/fe_utils/Makefile b/src/fe_utils/Makefile index 7fdbe08e11..eb937e4648 100644 --- a/src/fe_utils/Makefile +++ b/src/fe_utils/Makefile @@ -25,6 +25,7 @@ OBJS = \ conditional.o \ exit_utils.o \ mbprint.o \ + option_utils.o \ print.o \ psqlscan.o \ query_utils.o \ diff --git a/src/fe_utils/option_utils.c b/src/fe_utils/option_utils.c new file mode 100644 index 0000000000..7893df77aa --- /dev/null +++ b/src/fe_utils/option_utils.c @@ -0,0 +1,225 @@ +/*------------------------------------------------------------------------- + * + * Command-line option facilities for frontend code + * + * Functions for converting shell-style patterns into simple lists of Oids for + * database objects that match the patterns. + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/fe_utils/option_utils.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include "catalog/pg_class.h" +#include "common/connect.h" +#include "fe_utils/exit_utils.h" +#include "fe_utils/option_utils.h" +#include "fe_utils/query_utils.h" +#include "fe_utils/simple_list.h" +#include "fe_utils/string_utils.h" +#include "libpq-fe.h" +#include "pqexpbuffer.h" + +/* + * Find the OIDs of all schemas matching the given list of patterns, + * and append them to the given OID list. + */ +void +expand_schema_name_patterns(PGconn *conn, + SimpleStringList *patterns, + SimpleOidList *oids, + bool strict_names) +{ + 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) + { + appendPQExpBufferStr(query, + "SELECT oid FROM pg_catalog.pg_namespace n\n"); + processSQLNamePattern(conn, query, cell->val, false, + false, NULL, "n.nspname", NULL, NULL); + + res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK); + if (strict_names && PQntuples(res) == 0) + fatal("no matching schemas 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 foreign servers matching the given list of patterns, + * and append them to the given OID list. + */ +void +expand_foreign_server_name_patterns(PGconn *conn, + 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) + { + appendPQExpBufferStr(query, + "SELECT oid FROM pg_catalog.pg_foreign_server s\n"); + processSQLNamePattern(conn, query, cell->val, false, + false, NULL, "s.srvname", NULL, NULL); + + res = ExecuteSqlQuery(conn, 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. + */ +void +expand_table_name_patterns(PGconn *conn, + SimpleStringList *patterns, SimpleOidList *oids, + bool strict_names) +{ + PQExpBuffer query; + PGresult *res; + SimpleStringListCell *cell; + int i; + + if (patterns->head == NULL) + return; /* nothing to do */ + + query = createPQExpBuffer(); + + /* + * this might sometimes result in duplicate entries in the OID list, but + * we don't care. + */ + + for (cell = patterns->head; cell; cell = cell->next) + { + /* + * Query must remain ABSOLUTELY devoid of unqualified names. This + * would be unnecessary given a pg_table_is_visible() variant taking a + * search_path argument. + */ + appendPQExpBuffer(query, + "SELECT c.oid" + "\nFROM pg_catalog.pg_class c" + "\n LEFT JOIN pg_catalog.pg_namespace n" + "\n ON n.oid OPERATOR(pg_catalog.=) c.relnamespace" + "\nWHERE c.relkind OPERATOR(pg_catalog.=) ANY" + "\n (array['%c', '%c', '%c', '%c', '%c', '%c'])\n", + RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, + RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE, + RELKIND_PARTITIONED_TABLE); + processSQLNamePattern(conn, query, cell->val, true, + false, "n.nspname", "c.relname", NULL, + "pg_catalog.pg_table_is_visible(c.oid)"); + + ExecuteSqlStatement(conn, "RESET search_path"); + res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK); + PQclear(ExecuteSqlQueryForSingleRow(conn, + ALWAYS_SECURE_SEARCH_PATH_SQL)); + if (strict_names && PQntuples(res) == 0) + fatal("no matching tables 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 a list of database names that match the given patterns. + */ +void +expand_dbname_patterns(PGconn *conn, + SimpleStringList *patterns, + SimpleStringList *names) +{ + PQExpBuffer query; + PGresult *res; + + if (patterns->head == NULL) + return; /* nothing to do */ + + query = createPQExpBuffer(); + + /* + * The loop below runs multiple SELECTs, which might sometimes result in + * duplicate entries in the name list, but we don't care, since all we're + * going to do is test membership of the list. + */ + + for (SimpleStringListCell *cell = patterns->head; cell; cell = cell->next) + { + appendPQExpBufferStr(query, + "SELECT datname FROM pg_catalog.pg_database n\n"); + processSQLNamePattern(conn, query, cell->val, false, + false, NULL, "datname", NULL, NULL); + + pg_log_info("executing %s", query->data); + res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK); + for (int i = 0; i < PQntuples(res); i++) + { + simple_string_list_append(names, PQgetvalue(res, i, 0)); + } + + PQclear(res); + resetPQExpBuffer(query); + } + + destroyPQExpBuffer(query); +} diff --git a/src/include/fe_utils/option_utils.h b/src/include/fe_utils/option_utils.h new file mode 100644 index 0000000000..d626a0bbc9 --- /dev/null +++ b/src/include/fe_utils/option_utils.h @@ -0,0 +1,35 @@ +/*------------------------------------------------------------------------- + * + * Command-line option facilities for frontend code + * + * Functions for converting shell-style patterns into simple lists of Oids for + * database objects that match the patterns. + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/fe_utils/option_utils.h + * + *------------------------------------------------------------------------- + */ +#ifndef OPTION_UTILS_H +#define OPTION_UTILS_H + +#include "fe_utils/simple_list.h" +#include "libpq-fe.h" + +extern void expand_schema_name_patterns(PGconn *conn, + SimpleStringList *patterns, + SimpleOidList *oids, + bool strict_names); +extern void expand_foreign_server_name_patterns(PGconn *conn, + SimpleStringList *patterns, + SimpleOidList *oids); +extern void expand_table_name_patterns(PGconn *conn, + SimpleStringList *patterns, + SimpleOidList *oids, + bool strict_names); +extern void expand_dbname_patterns(PGconn *conn, SimpleStringList *patterns, + SimpleStringList *names); + +#endif /* OPTION_UTILS_H */ -- 2.21.1 (Apple Git-122.3)