From b7e65e27a28d3fb4a2da75947a8093bfff0e7d9a Mon Sep 17 00:00:00 2001 From: Fujii Masao Date: Thu, 25 Jul 2024 20:42:00 +0900 Subject: [PATCH v43 2/3] postgres_fdw: Add "used_in_xact" column to postgres_fdw_get_connections(). This commit extends the postgres_fdw_get_connections() function to include a new used_in_xact column, indicating whether each connection is used in the current transaction. This addition is particularly useful for the upcoming feature that will check if connections are closed. By using those information, users can verify if postgres_fdw connections used in a transaction remain open. If any connection is closed, the transaction cannot be committed successfully. In this case users can roll back it immediately without waiting for transaction end. The SQL API for postgres_fdw_get_connections() is updated by this commit and may change in the future. To handle compatibility with older SQL declarations, an API versioning system is introduced, allowing the function to behave differently based on the API version. --- contrib/postgres_fdw/Makefile | 2 +- contrib/postgres_fdw/connection.c | 84 +++++++++++++++++-- .../postgres_fdw/expected/postgres_fdw.out | 8 +- contrib/postgres_fdw/meson.build | 1 + .../postgres_fdw/postgres_fdw--1.1--1.2.sql | 16 ++++ contrib/postgres_fdw/postgres_fdw.control | 2 +- doc/src/sgml/postgres-fdw.sgml | 21 +++-- src/tools/pgindent/typedefs.list | 1 + 8 files changed, 114 insertions(+), 21 deletions(-) create mode 100644 contrib/postgres_fdw/postgres_fdw--1.1--1.2.sql diff --git a/contrib/postgres_fdw/Makefile b/contrib/postgres_fdw/Makefile index b9fa699305..88fdce40d6 100644 --- a/contrib/postgres_fdw/Makefile +++ b/contrib/postgres_fdw/Makefile @@ -14,7 +14,7 @@ PG_CPPFLAGS = -I$(libpq_srcdir) SHLIB_LINK_INTERNAL = $(libpq) EXTENSION = postgres_fdw -DATA = postgres_fdw--1.0.sql postgres_fdw--1.0--1.1.sql +DATA = postgres_fdw--1.0.sql postgres_fdw--1.0--1.1.sql postgres_fdw--1.1--1.2.sql REGRESS = postgres_fdw query_cancel diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c index 33e8054f64..2e587de023 100644 --- a/contrib/postgres_fdw/connection.c +++ b/contrib/postgres_fdw/connection.c @@ -107,10 +107,20 @@ static uint32 pgfdw_we_get_result = 0; (entry)->xact_depth, (entry)->xact_depth); \ } while(0) +/* + * Extension version number, for supporting older extension versions' objects + */ +typedef enum pgfdwVersion +{ + PGFDW_V1_1 = 0, + PGFDW_V1_2, +} pgfdwVersion; + /* * SQL functions */ PG_FUNCTION_INFO_V1(postgres_fdw_get_connections); +PG_FUNCTION_INFO_V1(postgres_fdw_get_connections_1_2); PG_FUNCTION_INFO_V1(postgres_fdw_disconnect); PG_FUNCTION_INFO_V1(postgres_fdw_disconnect_all); @@ -159,6 +169,8 @@ static void pgfdw_security_check(const char **keywords, const char **values, UserMapping *user, PGconn *conn); static bool UserMappingPasswordRequired(UserMapping *user); static bool disconnect_cached_connections(Oid serverid); +static void postgres_fdw_get_connections_internal(FunctionCallInfo fcinfo, + pgfdwVersion api_version); /* * Get a PGconn which can be used to execute queries on the remote PostgreSQL @@ -1977,23 +1989,34 @@ pgfdw_finish_abort_cleanup(List *pending_entries, List *cancel_requested, } } +/* Number of output arguments (columns) for various API versions */ +#define POSTGRES_FDW_GET_CONNECTIONS_COLS_V1_1 2 +#define POSTGRES_FDW_GET_CONNECTIONS_COLS_V1_2 3 +#define POSTGRES_FDW_GET_CONNECTIONS_COLS 3 /* maximum of above */ + /* - * List active foreign server connections. + * Internal function used by postgres_fdw_get_connections variants. + * + * For API version 1.1, this function returns a set of records with + * the following values: * - * This function takes no input parameter and returns setof record made of - * following values: * - server_name - server name of active connection. In case the foreign server * is dropped but still the connection is active, then the server name will * be NULL in output. * - valid - true/false representing whether the connection is valid or not. - * Note that the connections can get invalidated in pgfdw_inval_callback. + * Note that connections can become invalid in pgfdw_inval_callback. + * + * For API version 1.2 and later, this function returns the following + * additional value along with the two values from version 1.1: + * + * - used_in_xact - true if the connection is used in the current transaction. * * No records are returned when there are no cached connections at all. */ -Datum -postgres_fdw_get_connections(PG_FUNCTION_ARGS) +static void +postgres_fdw_get_connections_internal(FunctionCallInfo fcinfo, + pgfdwVersion api_version) { -#define POSTGRES_FDW_GET_CONNECTIONS_COLS 2 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; HASH_SEQ_STATUS scan; ConnCacheEntry *entry; @@ -2002,7 +2025,22 @@ postgres_fdw_get_connections(PG_FUNCTION_ARGS) /* If cache doesn't exist, we return no records */ if (!ConnectionHash) - PG_RETURN_VOID(); + return; + + /* Check we have the expected number of output arguments */ + switch (rsinfo->setDesc->natts) + { + case POSTGRES_FDW_GET_CONNECTIONS_COLS_V1_1: + if (api_version != PGFDW_V1_1) + elog(ERROR, "incorrect number of output arguments"); + break; + case POSTGRES_FDW_GET_CONNECTIONS_COLS_V1_2: + if (api_version != PGFDW_V1_2) + elog(ERROR, "incorrect number of output arguments"); + break; + default: + elog(ERROR, "incorrect number of output arguments"); + } hash_seq_init(&scan, ConnectionHash); while ((entry = (ConnCacheEntry *) hash_seq_search(&scan))) @@ -2061,10 +2099,38 @@ postgres_fdw_get_connections(PG_FUNCTION_ARGS) values[1] = BoolGetDatum(!entry->invalidated); + if (api_version >= PGFDW_V1_2) + { + /* Is this connection used in the current transaction? */ + values[2] = BoolGetDatum(entry->xact_depth > 0); + } + tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls); } +} + +/* + * List active foreign server connections. + * + * The SQL API of this function has changed multiple times, and will likely + * do so again in future. To support the case where a newer version of this + * loadable module is being used with an old SQL declaration of the function, + * we continue to support the older API versions. + */ +Datum +postgres_fdw_get_connections_1_2(PG_FUNCTION_ARGS) +{ + postgres_fdw_get_connections_internal(fcinfo, PGFDW_V1_2); + + return (Datum) 0; +} + +Datum +postgres_fdw_get_connections(PG_FUNCTION_ARGS) +{ + postgres_fdw_get_connections_internal(fcinfo, PGFDW_V1_1); - PG_RETURN_VOID(); + return (Datum) 0; } /* diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out index 39b2b317e8..82fdc0e26f 100644 --- a/contrib/postgres_fdw/expected/postgres_fdw.out +++ b/contrib/postgres_fdw/expected/postgres_fdw.out @@ -10464,10 +10464,10 @@ drop cascades to foreign table ft7 -- should be output as invalid connections. Also the server name for -- loopback3 should be NULL because the server was dropped. SELECT * FROM postgres_fdw_get_connections() ORDER BY 1; - server_name | valid --------------+------- - loopback | f - | f + server_name | valid | used_in_xact +-------------+-------+-------------- + loopback | f | t + | f | t (2 rows) -- The invalid connections get closed in pgfdw_xact_callback during commit. diff --git a/contrib/postgres_fdw/meson.build b/contrib/postgres_fdw/meson.build index f0803ee077..3014086ba6 100644 --- a/contrib/postgres_fdw/meson.build +++ b/contrib/postgres_fdw/meson.build @@ -26,6 +26,7 @@ install_data( 'postgres_fdw.control', 'postgres_fdw--1.0.sql', 'postgres_fdw--1.0--1.1.sql', + 'postgres_fdw--1.1--1.2.sql', kwargs: contrib_data_args, ) diff --git a/contrib/postgres_fdw/postgres_fdw--1.1--1.2.sql b/contrib/postgres_fdw/postgres_fdw--1.1--1.2.sql new file mode 100644 index 0000000000..0c65bf2e14 --- /dev/null +++ b/contrib/postgres_fdw/postgres_fdw--1.1--1.2.sql @@ -0,0 +1,16 @@ +/* contrib/postgres_fdw/postgres_fdw--1.1--1.2.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION postgres_fdw UPDATE TO '1.2'" to load this file. \quit + +/* First we have to remove it from the extension */ +ALTER EXTENSION postgres_fdw DROP FUNCTION postgres_fdw_get_connections (); + +/* Then we can drop it */ +DROP FUNCTION postgres_fdw_get_connections (); + +CREATE FUNCTION postgres_fdw_get_connections (OUT server_name text, + OUT valid boolean, OUT used_in_xact boolean) +RETURNS SETOF record +AS 'MODULE_PATHNAME', 'postgres_fdw_get_connections_1_2' +LANGUAGE C STRICT PARALLEL RESTRICTED; diff --git a/contrib/postgres_fdw/postgres_fdw.control b/contrib/postgres_fdw/postgres_fdw.control index d489382064..a4b800be4f 100644 --- a/contrib/postgres_fdw/postgres_fdw.control +++ b/contrib/postgres_fdw/postgres_fdw.control @@ -1,5 +1,5 @@ # postgres_fdw extension comment = 'foreign-data wrapper for remote PostgreSQL servers' -default_version = '1.1' +default_version = '1.2' module_pathname = '$libdir/postgres_fdw' relocatable = true diff --git a/doc/src/sgml/postgres-fdw.sgml b/doc/src/sgml/postgres-fdw.sgml index c7e0a7d2a6..819dca3e00 100644 --- a/doc/src/sgml/postgres-fdw.sgml +++ b/doc/src/sgml/postgres-fdw.sgml @@ -777,7 +777,9 @@ OPTIONS (ADD password_required 'false'); - postgres_fdw_get_connections(OUT server_name text, OUT valid boolean) returns setof record + postgres_fdw_get_connections(OUT server_name text, + OUT valid boolean, OUT used_in_xact boolean) + returns setof record This function returns information about all open connections that @@ -785,11 +787,11 @@ OPTIONS (ADD password_required 'false'); If there are no open connections, no records are returned. Example usage of the function: -postgres=# SELECT * FROM postgres_fdw_get_connections() ORDER BY 1; - server_name | valid --------------+------- - loopback1 | t - loopback2 | f +postgres=*# SELECT * FROM postgres_fdw_get_connections() ORDER BY 1; + server_name | valid | used_in_xact +-------------+-------+-------------- + loopback1 | t | t + loopback2 | f | t The output columns are described in . @@ -827,6 +829,13 @@ postgres=# SELECT * FROM postgres_fdw_get_connections() ORDER BY 1; the transaction. True is returned otherwise. + + used_in_xact + boolean + + True if this connection is used in the current transaction. + + diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index b4d7f9217c..508c74a22b 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -3731,6 +3731,7 @@ pg_wc_probefunc pg_wchar pg_wchar_tbl pgp_armor_headers_state +pgfdwVersion pgsocket pgsql_thing_t pgssEntry -- 2.45.2