v7-0001-Un-deprecate-postgresql_fdw_validator.patch
text/x-patch
Filename: v7-0001-Un-deprecate-postgresql_fdw_validator.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v7-0001
Subject: Un-deprecate postgresql_fdw_validator().
| File | + | − |
|---|---|---|
| src/backend/foreign/foreign.c | 23 | 44 |
| src/backend/replication/libpqwalreceiver/libpqwalreceiver.c | 48 | 0 |
| src/include/replication/walreceiver.h | 20 | 0 |
From 07b7baf50df3ecaf527530ea47435edfc588714f Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Thu, 4 Jan 2024 12:15:54 -0800
Subject: [PATCH v7 1/4] Un-deprecate postgresql_fdw_validator().
Extend the walrcv_ API to retrieve the options list from libpq, and
use that for postgresql_fdw_validator().
By using the correct libpq options, it no longer needs to be
deprecated, and can be used by the upcoming pg_connection_fdw.
Discussion: https://postgr.es/m/2a89b14a2b1622bffb8b137ca1f9ab7866f2d2b9.camel@j-davis.com
---
src/backend/foreign/foreign.c | 67 +++++++------------
.../libpqwalreceiver/libpqwalreceiver.c | 48 +++++++++++++
src/include/replication/walreceiver.h | 20 ++++++
3 files changed, 91 insertions(+), 44 deletions(-)
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c
index 02e1898131..747cc11a60 100644
--- a/src/backend/foreign/foreign.c
+++ b/src/backend/foreign/foreign.c
@@ -23,6 +23,7 @@
#include "funcapi.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"
+#include "replication/walreceiver.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/rel.h"
@@ -549,40 +550,6 @@ pg_options_to_table(PG_FUNCTION_ARGS)
}
-/*
- * Describes the valid options for postgresql FDW, server, and user mapping.
- */
-struct ConnectionOption
-{
- const char *optname;
- Oid optcontext; /* Oid of catalog in which option may appear */
-};
-
-/*
- * Copied from fe-connect.c PQconninfoOptions.
- *
- * The list is small - don't bother with bsearch if it stays so.
- */
-static const struct ConnectionOption libpq_conninfo_options[] = {
- {"authtype", ForeignServerRelationId},
- {"service", ForeignServerRelationId},
- {"user", UserMappingRelationId},
- {"password", UserMappingRelationId},
- {"connect_timeout", ForeignServerRelationId},
- {"dbname", ForeignServerRelationId},
- {"host", ForeignServerRelationId},
- {"hostaddr", ForeignServerRelationId},
- {"port", ForeignServerRelationId},
- {"tty", ForeignServerRelationId},
- {"options", ForeignServerRelationId},
- {"requiressl", ForeignServerRelationId},
- {"sslmode", ForeignServerRelationId},
- {"gsslib", ForeignServerRelationId},
- {"gssdelegation", ForeignServerRelationId},
- {NULL, InvalidOid}
-};
-
-
/*
* Check if the provided option is one of libpq conninfo options.
* context is the Oid of the catalog the option came from, or 0 if we
@@ -593,9 +560,23 @@ is_conninfo_option(const char *option, Oid context)
{
const struct ConnectionOption *opt;
- for (opt = libpq_conninfo_options; opt->optname; opt++)
- if (context == opt->optcontext && strcmp(opt->optname, option) == 0)
- return true;
+ /* skip options that must be overridden */
+ if (strcmp(option, "client_encoding") == 0)
+ return false;
+
+ for (opt = walrcv_conninfo_options(); opt->optname; opt++)
+ {
+ if (strcmp(opt->optname, option) == 0)
+ {
+ if (opt->isdebug)
+ return false;
+
+ if (opt->issecret || strcmp(opt->optname, "user") == 0)
+ return (context == UserMappingRelationId);
+
+ return (context == ForeignServerRelationId);
+ }
+ }
return false;
}
@@ -606,11 +587,6 @@ is_conninfo_option(const char *option, Oid context)
*
* Valid server options are all libpq conninfo options except
* user and password -- these may only appear in USER MAPPING options.
- *
- * Caution: this function is deprecated, and is now meant only for testing
- * purposes, because the list of options it knows about doesn't necessarily
- * square with those known to whichever libpq instance you might be using.
- * Inquire of libpq itself, instead.
*/
Datum
postgresql_fdw_validator(PG_FUNCTION_ARGS)
@@ -620,6 +596,9 @@ postgresql_fdw_validator(PG_FUNCTION_ARGS)
ListCell *cell;
+ /* Load the library providing us libpq calls. */
+ load_file("libpqwalreceiver", false);
+
foreach(cell, options_list)
{
DefElem *def = lfirst(cell);
@@ -636,9 +615,9 @@ postgresql_fdw_validator(PG_FUNCTION_ARGS)
* with a valid option that looks similar, if there is one.
*/
initClosestMatch(&match_state, def->defname, 4);
- for (opt = libpq_conninfo_options; opt->optname; opt++)
+ for (opt = walrcv_conninfo_options(); opt->optname; opt++)
{
- if (catalog == opt->optcontext)
+ if (is_conninfo_option(opt->optname, catalog))
{
has_valid_options = true;
updateClosestMatch(&match_state, opt->optname);
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 201c36cb22..58f8267fce 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -53,6 +53,7 @@ static WalReceiverConn *libpqrcv_connect(const char *conninfo,
const char *appname, char **err);
static void libpqrcv_check_conninfo(const char *conninfo,
bool must_use_password);
+static const struct ConnectionOption *libpqrcv_conninfo_options(void);
static char *libpqrcv_get_conninfo(WalReceiverConn *conn);
static void libpqrcv_get_senderinfo(WalReceiverConn *conn,
char **sender_host, int *sender_port);
@@ -86,6 +87,7 @@ static void libpqrcv_disconnect(WalReceiverConn *conn);
static WalReceiverFunctionsType PQWalReceiverFunctions = {
.walrcv_connect = libpqrcv_connect,
.walrcv_check_conninfo = libpqrcv_check_conninfo,
+ .walrcv_conninfo_options = libpqrcv_conninfo_options,
.walrcv_get_conninfo = libpqrcv_get_conninfo,
.walrcv_get_senderinfo = libpqrcv_get_senderinfo,
.walrcv_identify_system = libpqrcv_identify_system,
@@ -298,6 +300,52 @@ libpqrcv_check_conninfo(const char *conninfo, bool must_use_password)
PQconninfoFree(opts);
}
+static const struct ConnectionOption *
+libpqrcv_conninfo_options(void)
+{
+ static struct ConnectionOption *connection_options = NULL;
+
+ if (connection_options == NULL)
+ {
+ PQconninfoOption *conndefaults = PQconndefaults();
+ PQconninfoOption *lopt;
+ struct ConnectionOption *tmp_options = NULL;
+ struct ConnectionOption *popt;
+ size_t options_size = 0;
+ int num_libpq_opts = 0;
+
+ for (lopt = conndefaults; lopt->keyword; lopt++)
+ num_libpq_opts++;
+
+ /* leave room for all-zero entry at the end */
+ options_size = sizeof(struct ConnectionOption) * (num_libpq_opts + 1);
+ tmp_options = MemoryContextAllocZero(TopMemoryContext, options_size);
+
+ popt = tmp_options;
+ for (lopt = conndefaults; lopt->keyword; lopt++)
+ {
+ if (strchr(lopt->dispchar, '*'))
+ popt->issecret = true;
+ else if (strchr(lopt->dispchar, 'D'))
+ popt->isdebug = true;
+
+ popt->optname = MemoryContextStrdup(TopMemoryContext,
+ lopt->keyword);
+ popt++;
+ }
+
+ /* last entry is all zero */
+ Assert(popt->optname == NULL);
+
+ PQconninfoFree(conndefaults);
+
+ /* if everything succeeded, set static variable */
+ connection_options = tmp_options;
+ }
+
+ return connection_options;
+}
+
/*
* Return a user-displayable conninfo string. Any security-sensitive fields
* are obfuscated.
diff --git a/src/include/replication/walreceiver.h b/src/include/replication/walreceiver.h
index 0899891cdb..541377e095 100644
--- a/src/include/replication/walreceiver.h
+++ b/src/include/replication/walreceiver.h
@@ -223,6 +223,16 @@ typedef struct WalRcvExecResult
TupleDesc tupledesc;
} WalRcvExecResult;
+/*
+ * Describes the valid options for postgresql FDW, server, and user mapping.
+ */
+struct ConnectionOption
+{
+ const char *optname;
+ bool issecret; /* is option for a password? */
+ bool isdebug; /* is option a debug option? */
+};
+
/* WAL receiver - libpqwalreceiver hooks */
/*
@@ -250,6 +260,13 @@ typedef WalReceiverConn *(*walrcv_connect_fn) (const char *conninfo,
typedef void (*walrcv_check_conninfo_fn) (const char *conninfo,
bool must_use_password);
+/*
+ * walrcv_conninfo_options_fn
+ *
+ * Return a pointer to a static array of the available options from libpq.
+ */
+typedef const struct ConnectionOption *(*walrcv_conninfo_options_fn) (void);
+
/*
* walrcv_get_conninfo_fn
*
@@ -389,6 +406,7 @@ typedef struct WalReceiverFunctionsType
{
walrcv_connect_fn walrcv_connect;
walrcv_check_conninfo_fn walrcv_check_conninfo;
+ walrcv_conninfo_options_fn walrcv_conninfo_options;
walrcv_get_conninfo_fn walrcv_get_conninfo;
walrcv_get_senderinfo_fn walrcv_get_senderinfo;
walrcv_identify_system_fn walrcv_identify_system;
@@ -410,6 +428,8 @@ extern PGDLLIMPORT WalReceiverFunctionsType *WalReceiverFunctions;
WalReceiverFunctions->walrcv_connect(conninfo, logical, must_use_password, appname, err)
#define walrcv_check_conninfo(conninfo, must_use_password) \
WalReceiverFunctions->walrcv_check_conninfo(conninfo, must_use_password)
+#define walrcv_conninfo_options() \
+ WalReceiverFunctions->walrcv_conninfo_options()
#define walrcv_get_conninfo(conn) \
WalReceiverFunctions->walrcv_get_conninfo(conn)
#define walrcv_get_senderinfo(conn, sender_host, sender_port) \
--
2.34.1