On Tue, Aug 1, 2017 at 4:55 PM, Robert Haas <[email protected]> wrote:
>
> On Tue, Aug 1, 2017 at 3:37 PM, Peter Eisentraut
> <[email protected]> wrote:
> > On 7/21/17 12:59, Robert Haas wrote:
> >> That's an exceedingly-weak argument for rejecting this patch. The
> >> fact that you can probably hack around the lack of a hook for most
> >> reasonable use cases is not an argument for having a hook that does
> >> what people actually want to do.
> >
> > Still nobody has presented a concrete use case so far.
>
> I've been asked for this at EDB, too. Inserting a row into some table
> on each logon, for example.
>
> A quick Google search found 6 previous requests for this feature, some
> of which describe intended use cases:
>
> https://www.postgresql.org/message-id/[email protected] (2011)
>
https://www.postgresql.org/message-id/CAHyXU0wrsYShxmwBxZSGYoiBJa%3DgzEJ17iAeRvaf_vA%2BcoH_qA%40mail.gmail.com
> (2011)
>
https://www.postgresql.org/message-id/[email protected]
> (2009, in Spanish)
>
https://www.postgresql.org/message-id/758d5e7f0803130227m558d32cdl7159bed00d21f084%40mail.gmail.com
> (2008)
>
https://www.postgresql.org/message-id/001a01c48077%240b118e60%240200030a%40gendron.ca
> (2004)
>
https://www.postgresql.org/message-id/[email protected]
> (2000)
>
Hi all,
I'm sending a new rebased patches and added tests to src/tests/modules as
suggested before.
Regards,
--
Fabrízio de Royes Mello
Consultoria/Coaching PostgreSQL
>> Timbira: http://www.timbira.com.br
>> Blog: http://fabriziomello.github.io
>> Linkedin: http://br.linkedin.com/in/fabriziomello
>> Twitter: http://twitter.com/fabriziomello
>> Github: http://github.com/fabriziomello
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index c807b00..5c22f2d 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -165,6 +165,9 @@ static bool RecoveryConflictPending = false;
static bool RecoveryConflictRetryable = true;
static ProcSignalReason RecoveryConflictReason;
+/* Hook for plugins to get control at start of session */
+session_start_hook_type session_start_hook = NULL;
+
/* ----------------------------------------------------------------
* decls for routines only used in this file
* ----------------------------------------------------------------
@@ -3838,6 +3841,9 @@ PostgresMain(int argc, char *argv[],
if (!IsUnderPostmaster)
PgStartTime = GetCurrentTimestamp();
+ if (session_start_hook)
+ (*session_start_hook) (dbname, username);
+
/*
* POSTGRES main processing loop begins here
*
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index f8c535c..d349592 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -35,6 +35,11 @@ extern PGDLLIMPORT const char *debug_query_string;
extern int max_stack_depth;
extern int PostAuthDelay;
+/* Hook for plugins to get control at start of session */
+typedef void (*session_start_hook_type) (const char *dbname,
+ const char *username);
+extern PGDLLIMPORT session_start_hook_type session_start_hook;
+
/* GUC-configurable parameters */
typedef enum
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 5c22f2d..79f3099 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -165,9 +165,9 @@ static bool RecoveryConflictPending = false;
static bool RecoveryConflictRetryable = true;
static ProcSignalReason RecoveryConflictReason;
-/* Hook for plugins to get control at start of session */
+/* Hook for plugins to get control at start or end of session */
session_start_hook_type session_start_hook = NULL;
-
+session_end_hook_type session_end_hook = NULL;
/* ----------------------------------------------------------------
* decls for routines only used in this file
* ----------------------------------------------------------------
@@ -192,6 +192,7 @@ static void drop_unnamed_stmt(void);
static void log_disconnections(int code, Datum arg);
static void enable_statement_timeout(void);
static void disable_statement_timeout(void);
+static void do_session_end_hook(int code, Datum arg);
/* ----------------------------------------------------------------
@@ -3845,6 +3846,12 @@ PostgresMain(int argc, char *argv[],
(*session_start_hook) (dbname, username);
/*
+ * Setup handler to session end hook
+ */
+ if (IsUnderPostmaster)
+ on_proc_exit(do_session_end_hook, 0);
+
+ /*
* POSTGRES main processing loop begins here
*
* If an exception is encountered, processing resumes here so we abort the
@@ -4596,3 +4603,15 @@ disable_statement_timeout(void)
stmt_timeout_active = false;
}
}
+
+/*
+ * on_proc_exit handler to call session end hook
+ */
+static void
+do_session_end_hook(int code, Datum arg)
+{
+ Port *port = MyProcPort;
+
+ if (session_end_hook)
+ (*session_end_hook) (port->database_name, port->user_name);
+}
\ No newline at end of file
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index d349592..b7fb8c3 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -35,10 +35,14 @@ extern PGDLLIMPORT const char *debug_query_string;
extern int max_stack_depth;
extern int PostAuthDelay;
-/* Hook for plugins to get control at start of session */
+/* Hook for plugins to get control at start and end of session */
typedef void (*session_start_hook_type) (const char *dbname,
const char *username);
+typedef void (*session_end_hook_type) (const char *dbname,
+ const char *username);
+
extern PGDLLIMPORT session_start_hook_type session_start_hook;
+extern PGDLLIMPORT session_end_hook_type session_end_hook;
/* GUC-configurable parameters */
diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index b7ed0af..a3c8c1e 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -11,6 +11,7 @@ SUBDIRS = \
snapshot_too_old \
test_ddl_deparse \
test_extensions \
+ test_session_hooks \
test_parser \
test_pg_dump \
test_rbtree \
diff --git a/src/test/modules/test_session_hooks/.gitignore b/src/test/modules/test_session_hooks/.gitignore
new file mode 100644
index 0000000..5dcb3ff
--- /dev/null
+++ b/src/test/modules/test_session_hooks/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/src/test/modules/test_session_hooks/Makefile b/src/test/modules/test_session_hooks/Makefile
new file mode 100644
index 0000000..9cabd3f
--- /dev/null
+++ b/src/test/modules/test_session_hooks/Makefile
@@ -0,0 +1,26 @@
+# src/test/modules/test_session_hooks/Makefile
+
+MODULES = test_session_hooks
+PGFILEDESC = "test_session_hooks - Test session hooks with an extension"
+
+EXTENSION = test_session_hooks
+DATA = test_session_hooks--1.0.sql
+
+REGRESS = test_session_hooks
+REGRESS_OPTS = --temp-config=$(top_srcdir)/src/test/modules/test_session_hooks/session_hooks.conf
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_session_hooks
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
+
+check: prove-check
+
+prove-check:
+ $(prove_check)
diff --git a/src/test/modules/test_session_hooks/README b/src/test/modules/test_session_hooks/README
new file mode 100644
index 0000000..e6c78b8
--- /dev/null
+++ b/src/test/modules/test_session_hooks/README
@@ -0,0 +1,2 @@
+test_pg_dump is an extension explicitly to test pg_dump when
+extensions are present in the system.
diff --git a/src/test/modules/test_session_hooks/expected/test_session_hooks.out b/src/test/modules/test_session_hooks/expected/test_session_hooks.out
new file mode 100644
index 0000000..602819c
--- /dev/null
+++ b/src/test/modules/test_session_hooks/expected/test_session_hooks.out
@@ -0,0 +1,10 @@
+SHOW test_session_hooks.message;
+ERROR: unrecognized configuration parameter "test_session_hooks.message"
+CREATE DATABASE test;
+\c test
+SHOW test_session_hooks.message;
+ test_session_hooks.message
+----------------------------
+ Session Start Hook Handled
+(1 row)
+
diff --git a/src/test/modules/test_session_hooks/session_hooks.conf b/src/test/modules/test_session_hooks/session_hooks.conf
new file mode 100644
index 0000000..a66e60e
--- /dev/null
+++ b/src/test/modules/test_session_hooks/session_hooks.conf
@@ -0,0 +1 @@
+shared_preload_libraries = 'test_session_hooks'
diff --git a/src/test/modules/test_session_hooks/sql/test_session_hooks.sql b/src/test/modules/test_session_hooks/sql/test_session_hooks.sql
new file mode 100644
index 0000000..b75f2f8
--- /dev/null
+++ b/src/test/modules/test_session_hooks/sql/test_session_hooks.sql
@@ -0,0 +1,4 @@
+SHOW test_session_hooks.message;
+CREATE DATABASE test;
+\c test
+SHOW test_session_hooks.message;
diff --git a/src/test/modules/test_session_hooks/t/001_base.pl b/src/test/modules/test_session_hooks/t/001_base.pl
new file mode 100644
index 0000000..442fb8a
--- /dev/null
+++ b/src/test/modules/test_session_hooks/t/001_base.pl
@@ -0,0 +1,24 @@
+# Test session end hook log messages
+
+use strict;
+use warnings;
+
+use TestLib;
+use Test::More tests => 2;
+use PostgresNode;
+
+my $node = get_new_node('main');
+$node->init;
+$node->append_conf(
+ 'postgresql.conf',
+ qq{shared_preload_libraries = 'test_session_hooks'}
+);
+$node->start;
+$node->safe_psql('postgres', 'CREATE DATABASE test');
+my ($ret, $stdout, $stderr) = $node->psql('test','show test_session_hooks.message');
+
+# check session start hook
+like($stdout, qr/Session Start Hook Handled/, 'error during session start hook');
+
+# check session end hook
+like(slurp_file($node->logfile()), qr/Session End Hook Handled/, 'error during session end hook');
diff --git a/src/test/modules/test_session_hooks/test_session_hooks--1.0.sql b/src/test/modules/test_session_hooks/test_session_hooks--1.0.sql
new file mode 100644
index 0000000..16bcee9
--- /dev/null
+++ b/src/test/modules/test_session_hooks/test_session_hooks--1.0.sql
@@ -0,0 +1,4 @@
+/* src/test/modules/test_hook_session/test_hook_session--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION test_hook_session" to load this file. \quit
diff --git a/src/test/modules/test_session_hooks/test_session_hooks.c b/src/test/modules/test_session_hooks/test_session_hooks.c
new file mode 100644
index 0000000..ff63b83
--- /dev/null
+++ b/src/test/modules/test_session_hooks/test_session_hooks.c
@@ -0,0 +1,80 @@
+/* -------------------------------------------------------------------------
+ *
+ * test_session_hooks.c
+ * Code for testing SESSION hooks.
+ *
+ * Copyright (c) 2010-2017, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/test/modules/test_session_hooks/test_session_hooks.c
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/xact.h"
+#include "executor/spi.h"
+#include "tcop/tcopprot.h"
+
+PG_MODULE_MAGIC;
+
+void _PG_init(void);
+void _PG_fini(void);
+
+/* Original Hook */
+static session_start_hook_type prev_session_start_hook = NULL;
+static session_end_hook_type prev_session_end_hook = NULL;
+
+/* sample session start hook function */
+static void
+sample_session_start_hook(const char *dbname, const char *username)
+{
+ if (prev_session_start_hook)
+ prev_session_start_hook(dbname, username);
+
+ if (!strcmp(dbname, "test"))
+ {
+ StartTransactionCommand();
+ SPI_connect();
+ SPI_exec("SET test_session_hooks.message TO 'Session Start Hook Handled'", 1);
+ SPI_finish();
+ CommitTransactionCommand();
+ }
+}
+
+/* sample sessoin end hook function */
+static void
+sample_session_end_hook(const char *dbname, const char *username)
+{
+ if (prev_session_end_hook)
+ prev_session_end_hook(dbname, username);
+
+ if (!strcmp(dbname, "test"))
+ elog(LOG, "Session End Hook Handled");
+}
+
+/*
+ * Module Load Callback
+ */
+void
+_PG_init(void)
+{
+ /* Save Hooks for Unload */
+ prev_session_start_hook = session_start_hook;
+ prev_session_end_hook = session_end_hook;
+
+ /* Set New Hooks */
+ session_start_hook = sample_session_start_hook;
+ session_end_hook = sample_session_end_hook;
+}
+
+/*
+ * Module Unload Callback
+ */
+void
+_PG_fini(void)
+{
+ /* Uninstall Hooks */
+ session_start_hook = prev_session_start_hook;
+ session_end_hook = prev_session_end_hook;
+}
diff --git a/src/test/modules/test_session_hooks/test_session_hooks.control b/src/test/modules/test_session_hooks/test_session_hooks.control
new file mode 100644
index 0000000..7d7ef9f
--- /dev/null
+++ b/src/test/modules/test_session_hooks/test_session_hooks.control
@@ -0,0 +1,3 @@
+comment = 'Test start/end hook session with an extension'
+default_version = '1.0'
+relocatable = true
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers