v31-0008-Normalizing-option_utils-interface.patch
application/octet-stream
Filename: v31-0008-Normalizing-option_utils-interface.patch
Type: application/octet-stream
Part: 7
Message:
Re: new heapcheck contrib module
Patch
Format: format-patch
Series: patch v31-0008
Subject: Normalizing option_utils interface.
| File | + | − |
|---|---|---|
| src/bin/pg_dump/pg_dumpall.c | 2 | 2 |
| src/bin/pg_dump/pg_dump.c | 44 | 14 |
| src/fe_utils/option_utils.c | 47 | 19 |
| src/fe_utils/string_utils.c | 50 | 0 |
| src/include/fe_utils/option_utils.h | 20 | 9 |
| src/include/fe_utils/string_utils.h | 6 | 0 |
From e0eb07b74c78a6259dbe8546c6d03699ec1e0fbd Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 6 Jan 2021 14:37:44 -0800
Subject: [PATCH v31 8/9] Normalizing option_utils interface.
The functions in option_utils were copied from pg_dump, mostly preserving
the function signatures. But the signatures and corresponding functionality
were originally written based solely on pg_dump's needs, not with the goal
of creating a consistent interface. Fixing that.
---
src/bin/pg_dump/pg_dump.c | 58 +++++++++++++++++++------
src/bin/pg_dump/pg_dumpall.c | 4 +-
src/fe_utils/option_utils.c | 66 ++++++++++++++++++++---------
src/fe_utils/string_utils.c | 50 ++++++++++++++++++++++
src/include/fe_utils/option_utils.h | 29 +++++++++----
src/include/fe_utils/string_utils.h | 6 +++
6 files changed, 169 insertions(+), 44 deletions(-)
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index c334b9e829..5c446c0f24 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -125,6 +125,17 @@ static SimpleOidList tabledata_exclude_oids = {NULL, NULL};
static SimpleStringList foreign_servers_include_patterns = {NULL, NULL};
static SimpleOidList foreign_servers_include_oids = {NULL, NULL};
+/*
+ * Cstring list of relkinds which qualify as tables for our purposes when
+ * processing table inclusion or exclusion patterns.
+ */
+#define TABLE_RELKIND_LIST CppAsString2(RELKIND_RELATION) ", " \
+ CppAsString2(RELKIND_SEQUENCE) ", " \
+ CppAsString2(RELKIND_VIEW) ", " \
+ CppAsString2(RELKIND_MATVIEW) ", " \
+ CppAsString2(RELKIND_FOREIGN_TABLE) ", " \
+ CppAsString2(RELKIND_PARTITIONED_TABLE)
+
static const CatalogId nilCatalogId = {0, 0};
/* override for standard extra_float_digits setting */
@@ -791,6 +802,7 @@ main(int argc, char **argv)
{
expand_schema_name_patterns(GetConnection(fout),
&schema_include_patterns,
+ NULL,
&schema_include_oids,
strict_names);
if (schema_include_oids.head == NULL)
@@ -798,6 +810,7 @@ main(int argc, char **argv)
}
expand_schema_name_patterns(GetConnection(fout),
&schema_exclude_patterns,
+ NULL,
&schema_exclude_oids,
false);
/* non-matching exclusion patterns aren't an error */
@@ -805,26 +818,43 @@ main(int argc, char **argv)
/* Expand table selection patterns into OID lists */
if (table_include_patterns.head != NULL)
{
- expand_table_name_patterns(GetConnection(fout),
- &table_include_patterns,
- &table_include_oids,
- strict_names);
+ expand_rel_name_patterns(GetConnection(fout),
+ &table_include_patterns,
+ NULL,
+ NULL,
+ TABLE_RELKIND_LIST,
+ AMTYPE_TABLE,
+ &table_include_oids,
+ strict_names,
+ true);
if (table_include_oids.head == NULL)
fatal("no matching tables were found");
}
- expand_table_name_patterns(GetConnection(fout),
- &table_exclude_patterns,
- &table_exclude_oids,
- false);
-
- expand_table_name_patterns(GetConnection(fout),
- &tabledata_exclude_patterns,
- &tabledata_exclude_oids,
- false);
+ expand_rel_name_patterns(GetConnection(fout),
+ &table_exclude_patterns,
+ NULL,
+ NULL,
+ TABLE_RELKIND_LIST,
+ AMTYPE_TABLE,
+ &table_exclude_oids,
+ false,
+ true);
+
+ expand_rel_name_patterns(GetConnection(fout),
+ &tabledata_exclude_patterns,
+ NULL,
+ NULL,
+ TABLE_RELKIND_LIST,
+ AMTYPE_TABLE,
+ &tabledata_exclude_oids,
+ false,
+ true);
expand_foreign_server_name_patterns(GetConnection(fout),
&foreign_servers_include_patterns,
- &foreign_servers_include_oids);
+ NULL,
+ &foreign_servers_include_oids,
+ true);
/* non-matching exclusion patterns aren't an error */
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 01db15dfda..2b3a4e3349 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -471,8 +471,8 @@ main(int argc, char *argv[])
/*
* Get a list of database names that match the exclude patterns
*/
- expand_dbname_patterns(conn, &database_exclude_patterns,
- &database_exclude_names);
+ expand_dbname_patterns(conn, &database_exclude_patterns, NULL,
+ &database_exclude_names, false);
/*
* Open the output file if required, otherwise use stdout
diff --git a/src/fe_utils/option_utils.c b/src/fe_utils/option_utils.c
index 7893df77aa..76ca456784 100644
--- a/src/fe_utils/option_utils.c
+++ b/src/fe_utils/option_utils.c
@@ -14,6 +14,7 @@
*/
#include "postgres_fe.h"
+#include "catalog/pg_am.h"
#include "catalog/pg_class.h"
#include "common/connect.h"
#include "fe_utils/exit_utils.h"
@@ -30,7 +31,8 @@
*/
void
expand_schema_name_patterns(PGconn *conn,
- SimpleStringList *patterns,
+ const SimpleStringList *patterns,
+ const SimpleOidList *exclude_oids,
SimpleOidList *oids,
bool strict_names)
{
@@ -55,6 +57,7 @@ expand_schema_name_patterns(PGconn *conn,
"SELECT oid FROM pg_catalog.pg_namespace n\n");
processSQLNamePattern(conn, query, cell->val, false,
false, NULL, "n.nspname", NULL, NULL);
+ exclude_filter(query, "n.oid", exclude_oids);
res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK);
if (strict_names && PQntuples(res) == 0)
@@ -78,8 +81,10 @@ expand_schema_name_patterns(PGconn *conn,
*/
void
expand_foreign_server_name_patterns(PGconn *conn,
- SimpleStringList *patterns,
- SimpleOidList *oids)
+ const SimpleStringList *patterns,
+ const SimpleOidList *exclude_oids,
+ SimpleOidList *oids,
+ bool strict_names)
{
PQExpBuffer query;
PGresult *res;
@@ -102,9 +107,10 @@ expand_foreign_server_name_patterns(PGconn *conn,
"SELECT oid FROM pg_catalog.pg_foreign_server s\n");
processSQLNamePattern(conn, query, cell->val, false,
false, NULL, "s.srvname", NULL, NULL);
+ exclude_filter(query, "s.oid", exclude_oids);
res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK);
- if (PQntuples(res) == 0)
+ if (strict_names && PQntuples(res) == 0)
fatal("no matching foreign servers were found for pattern \"%s\"", cell->val);
for (i = 0; i < PQntuples(res); i++)
@@ -118,18 +124,32 @@ expand_foreign_server_name_patterns(PGconn *conn,
}
/*
- * Find the OIDs of all tables matching the given list of patterns,
- * and append them to the given OID list.
+ * Find the OIDs of all relations matching the given list of patterns
+ * and restrictions, and append them to the given OID list.
*/
void
-expand_table_name_patterns(PGconn *conn,
- SimpleStringList *patterns, SimpleOidList *oids,
- bool strict_names)
+expand_rel_name_patterns(PGconn *conn,
+ const SimpleStringList *patterns,
+ const SimpleOidList *exclude_nsp_oids,
+ const SimpleOidList *exclude_oids,
+ const char *relkinds,
+ char amtype,
+ SimpleOidList *oids,
+ bool strict_names,
+ bool restrict_visible)
{
PQExpBuffer query;
PGresult *res;
SimpleStringListCell *cell;
int i;
+ const char *visibility_rule;
+
+ Assert(amtype == AMTYPE_TABLE || amtype == AMTYPE_INDEX);
+
+ if (restrict_visible)
+ visibility_rule = "pg_catalog.pg_table_is_visible(c.oid)";
+ else
+ visibility_rule = NULL;
if (patterns->head == NULL)
return; /* nothing to do */
@@ -154,20 +174,22 @@ expand_table_name_patterns(PGconn *conn,
"\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);
+ "\n (array[%s])\n", relkinds);
processSQLNamePattern(conn, query, cell->val, true,
- false, "n.nspname", "c.relname", NULL,
- "pg_catalog.pg_table_is_visible(c.oid)");
+ false, "n.nspname", "c.relname", NULL, visibility_rule);
+ exclude_filter(query, "n.oid", exclude_nsp_oids);
+ exclude_filter(query, "c.oid", exclude_oids);
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);
+ {
+ if (amtype == AMTYPE_TABLE)
+ fatal("no matching tables were found for pattern \"%s\"", cell->val);
+ fatal("no matching indexes were found for pattern \"%s\"", cell->val);
+ }
for (i = 0; i < PQntuples(res); i++)
{
@@ -186,8 +208,10 @@ expand_table_name_patterns(PGconn *conn,
*/
void
expand_dbname_patterns(PGconn *conn,
- SimpleStringList *patterns,
- SimpleStringList *names)
+ const SimpleStringList *patterns,
+ const SimpleOidList *exclude_oids,
+ SimpleStringList *names,
+ bool strict_names)
{
PQExpBuffer query;
PGresult *res;
@@ -206,12 +230,16 @@ expand_dbname_patterns(PGconn *conn,
for (SimpleStringListCell *cell = patterns->head; cell; cell = cell->next)
{
appendPQExpBufferStr(query,
- "SELECT datname FROM pg_catalog.pg_database n\n");
+ "SELECT datname FROM pg_catalog.pg_database d\n");
processSQLNamePattern(conn, query, cell->val, false,
false, NULL, "datname", NULL, NULL);
+ exclude_filter(query, "d.oid", exclude_oids);
pg_log_info("executing %s", query->data);
res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK);
+ if (strict_names && PQntuples(res) == 0)
+ fatal("no matching databases were found for pattern \"%s\"", cell->val);
+
for (int i = 0; i < PQntuples(res); i++)
{
simple_string_list_append(names, PQgetvalue(res, i, 0));
diff --git a/src/fe_utils/string_utils.c b/src/fe_utils/string_utils.c
index a1a9d691d5..4e57a6f940 100644
--- a/src/fe_utils/string_utils.c
+++ b/src/fe_utils/string_utils.c
@@ -797,6 +797,56 @@ appendReloptionsArray(PQExpBuffer buffer, const char *reloptions,
return true;
}
+/*
+ * Internal implementation of include_filter and exclude_filter.
+ */
+static void
+apply_filter(PQExpBuffer querybuf, const char *lval, const SimpleOidList *oids,
+ bool include)
+{
+ const SimpleOidListCell *cell;
+ const char *comma;
+
+ if (!oids || !oids->head)
+ return;
+
+ if (include)
+ appendPQExpBuffer(querybuf, "\nAND %s OPERATOR(pg_catalog.=) ANY(array[", lval);
+ else
+ appendPQExpBuffer(querybuf, "\nAND %s OPERATOR(pg_catalog.!=) ALL(array[", lval);
+
+ for (comma = "", cell = oids->head; cell; comma = ", ", cell = cell->next)
+ appendPQExpBuffer(querybuf, "%s%u", comma, cell->val);
+ appendPQExpBuffer(querybuf, "]::OID[])");
+}
+
+/*
+ * Conditionally add a restriction to a query such that lval must be an Oid in
+ * the given list of Oids, except that for a null or empty oids list argument,
+ * no filtering is done and we return without having modified the query buffer.
+ *
+ * The query argument must already have begun the WHERE clause and must be in a
+ * state where we can append an AND clause. No checking of this requirement is
+ * done here.
+ *
+ * On return, the query buffer will be extended with an AND clause that filters
+ * only those rows where the lval is an Oid present in the given list of oids.
+ */
+void
+include_filter(PQExpBuffer querybuf, const char *lval, const SimpleOidList *oids)
+{
+ apply_filter(querybuf, lval, oids, true);
+}
+
+/*
+ * Same as include_filter, above, except that for a non-null, non-empty oids
+ * list, the lval is restricted to not be any of the values in the list.
+ */
+void
+exclude_filter(PQExpBuffer querybuf, const char *lval, const SimpleOidList *oids)
+{
+ apply_filter(querybuf, lval, oids, false);
+}
/*
* processSQLNamePattern
diff --git a/src/include/fe_utils/option_utils.h b/src/include/fe_utils/option_utils.h
index d626a0bbc9..53da30754f 100644
--- a/src/include/fe_utils/option_utils.h
+++ b/src/include/fe_utils/option_utils.h
@@ -19,17 +19,28 @@
#include "libpq-fe.h"
extern void expand_schema_name_patterns(PGconn *conn,
- SimpleStringList *patterns,
+ const SimpleStringList *patterns,
+ const SimpleOidList *exclude_oids,
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);
+ const SimpleStringList *patterns,
+ const SimpleOidList *exclude_oids,
+ SimpleOidList *oids,
+ bool strict_names);
+extern void expand_rel_name_patterns(PGconn *conn,
+ const SimpleStringList *patterns,
+ const SimpleOidList *exclude_nsp_oids,
+ const SimpleOidList *exclude_oids,
+ const char *relkinds,
+ char amtype,
+ SimpleOidList *oids,
+ bool strict_names,
+ bool restrict_visible);
+extern void expand_dbname_patterns(PGconn *conn,
+ const SimpleStringList *patterns,
+ const SimpleOidList *exclude_oids,
+ SimpleStringList *names,
+ bool strict_names);
#endif /* OPTION_UTILS_H */
diff --git a/src/include/fe_utils/string_utils.h b/src/include/fe_utils/string_utils.h
index c290c302f5..301a8eef4d 100644
--- a/src/include/fe_utils/string_utils.h
+++ b/src/include/fe_utils/string_utils.h
@@ -16,6 +16,7 @@
#ifndef STRING_UTILS_H
#define STRING_UTILS_H
+#include "fe_utils/simple_list.h"
#include "libpq-fe.h"
#include "pqexpbuffer.h"
@@ -50,6 +51,11 @@ extern bool parsePGArray(const char *atext, char ***itemarray, int *nitems);
extern bool appendReloptionsArray(PQExpBuffer buffer, const char *reloptions,
const char *prefix, int encoding, bool std_strings);
+extern void include_filter(PQExpBuffer querybuf, const char *lval,
+ const SimpleOidList *oids);
+extern void exclude_filter(PQExpBuffer querybuf, const char *lval,
+ const SimpleOidList *oids);
+
extern bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf,
const char *pattern,
bool have_where, bool force_escape,
--
2.21.1 (Apple Git-122.3)