Hi,

I occasionally need to perform some action whenever a user connects, and
there's nothing like an "AFTER LOGON" trigger (available in some other
databases).

Is there any particular reason why there's not a "backend start hook",
executed right after a backend is initialized? I've tried a very simple
PoC (basically just a new hook definition, called from PostgresMain(),
see the after-logon-hook.diff (and a simple module that uses it is in
logon.c).

This obviously is not a complete patch or something, but is there a good
reason why this is a stupid idea?

Obviously this is a bit low-level approach, as most of the time the
triggers are implemented in a PL. But who says you can't call a PL from
the C module ...

Tomas
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
new file mode 100644
index 976a832..35f1926
*** a/src/backend/tcop/postgres.c
--- b/src/backend/tcop/postgres.c
*************** int                     max_stack_depth = 100;
*** 104,110 ****
  /* wait N seconds to allow attach from a debugger */
  int                   PostAuthDelay = 0;
  
! 
  
  /* ----------------
   *            private variables
--- 104,110 ----
  /* wait N seconds to allow attach from a debugger */
  int                   PostAuthDelay = 0;
  
! backend_startup_hook_type backend_startup_hook = NULL;
  
  /* ----------------
   *            private variables
*************** PostgresMain(int argc, char *argv[], con
*** 3750,3755 ****
--- 3750,3769 ----
        if (!ignore_till_sync)
                send_ready_for_query = true;    /* initially, or after error */
  
+       if (backend_startup_hook != NULL)
+       {
+               PG_TRY();
+               {
+                       backend_startup_hook(MyProcPid, MyDatabaseId, dbname, 
username);
+               }
+               PG_CATCH();
+               {
+                       elog(FATAL, "Error calling after-logon trigger");
+                       proc_exit(0);
+               }
+               PG_END_TRY();
+       }
+ 
        /*
         * Non-error queries loop here.
         */
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
new file mode 100644
index 9d19417..3971268
*** a/src/include/miscadmin.h
--- b/src/include/miscadmin.h
*************** extern bool is_authenticated_user_replic
*** 388,391 ****
--- 388,396 ----
  extern bool BackupInProgress(void);
  extern void CancelBackup(void);
  
+ typedef void (*backend_startup_hook_type) (pid_t pid, Oid databaseOid,
+                                            const char * dbname, const char * 
username);
+ 
+ extern backend_startup_hook_type backend_startup_hook;
+ 
  #endif   /* MISCADMIN_H */
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <limits.h>

#include "postgres.h"
#include "utils/array.h"
#include "utils/lsyscache.h"
#include "utils/numeric.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "catalog/pg_type.h"

#include "miscadmin.h"

static backend_startup_hook_type prev_backend_startup_hook = NULL;

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

void _PG_init(void);
void _PG_fini(void);

static
void my_startup_hook (pid_t pid, Oid databaseOid,
                      const char * dbname, const char * username);

/*
 * Module load callback
 */
void
_PG_init(void)
{

	prev_backend_startup_hook = backend_startup_hook;
	backend_startup_hook = &my_startup_hook;

}

void
_PG_fini(void)
{

	backend_startup_hook = prev_backend_startup_hook;

}



static
void my_startup_hook (pid_t pid, Oid databaseOid,
                      const char * dbname, const char * username) {
	if (! strcmp(dbname, "testdb")) {
		elog(ERROR, "startup hook is failing");
	} else {
		elog(NOTICE, "startup hook finished OK");
	}
}
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to