From e83d1b0c40ccda8955f1245087f0697652c4df86 Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Mon, 16 Oct 2023 03:16:55 +0300 Subject: Add support event triggers on authenticated login This commit introduces trigger on login event, allowing to fire some actions right on the user connection. This can be useful for logging or connection check purposes as well as for some personalization of environment. Usage details are described in the documentation included, but shortly usage is the same as for other triggers: create function returning event_trigger and then create event trigger on login event. In order to prevent the connection time overhead when there are no triggers the commit introduces pg_database.dathasloginevt flag, which indicates database has active login triggers. This flag is set by CREATE/ALTER EVENT TRIGGER command, and unset at connection time when no active triggers found. Author: Konstantin Knizhnik, Mikhail Gribkov Discussion: https://postgr.es/m/0d46d29f-4558-3af9-9c85-7774e14a7709%40postgrespro.ru Reviewed-by: Pavel Stehule, Takayuki Tsunakawa, Greg Nancarrow, Ivan Panchenko Reviewed-by: Daniel Gustafsson, Teodor Sigaev, Robert Haas, Andres Freund Reviewed-by: Tom Lane, Andrey Sokolov, Zhihong Yu, Sergey Shinderuk Reviewed-by: Gregory Stark, Nikita Malakhov, Ted Yu --- src/backend/commands/dbcommands.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src/backend/commands/dbcommands.c') diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 307729ab7ef..c52ecc61a6b 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -116,7 +116,7 @@ static void movedb(const char *dbname, const char *tblspcname); static void movedb_failure_callback(int code, Datum arg); static bool get_db_info(const char *name, LOCKMODE lockmode, Oid *dbIdP, Oid *ownerIdP, - int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP, + int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP, bool *dbHasLoginEvtP, TransactionId *dbFrozenXidP, MultiXactId *dbMinMultiP, Oid *dbTablespace, char **dbCollate, char **dbCtype, char **dbIculocale, char **dbIcurules, @@ -680,6 +680,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) char src_locprovider = '\0'; char *src_collversion = NULL; bool src_istemplate; + bool src_hasloginevt; bool src_allowconn; TransactionId src_frozenxid = InvalidTransactionId; MultiXactId src_minmxid = InvalidMultiXactId; @@ -968,7 +969,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) if (!get_db_info(dbtemplate, ShareLock, &src_dboid, &src_owner, &src_encoding, - &src_istemplate, &src_allowconn, + &src_istemplate, &src_allowconn, &src_hasloginevt, &src_frozenxid, &src_minmxid, &src_deftablespace, &src_collate, &src_ctype, &src_iculocale, &src_icurules, &src_locprovider, &src_collversion)) @@ -1375,6 +1376,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt) new_record[Anum_pg_database_datlocprovider - 1] = CharGetDatum(dblocprovider); new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(dbistemplate); new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(dballowconnections); + new_record[Anum_pg_database_dathasloginevt - 1] = BoolGetDatum(src_hasloginevt); new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit); new_record[Anum_pg_database_datfrozenxid - 1] = TransactionIdGetDatum(src_frozenxid); new_record[Anum_pg_database_datminmxid - 1] = TransactionIdGetDatum(src_minmxid); @@ -1603,7 +1605,7 @@ dropdb(const char *dbname, bool missing_ok, bool force) pgdbrel = table_open(DatabaseRelationId, RowExclusiveLock); if (!get_db_info(dbname, AccessExclusiveLock, &db_id, NULL, NULL, - &db_istemplate, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) + &db_istemplate, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) { if (!missing_ok) { @@ -1817,7 +1819,7 @@ RenameDatabase(const char *oldname, const char *newname) */ rel = table_open(DatabaseRelationId, RowExclusiveLock); - if (!get_db_info(oldname, AccessExclusiveLock, &db_id, NULL, NULL, + if (!get_db_info(oldname, AccessExclusiveLock, &db_id, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_DATABASE), @@ -1927,7 +1929,7 @@ movedb(const char *dbname, const char *tblspcname) */ pgdbrel = table_open(DatabaseRelationId, RowExclusiveLock); - if (!get_db_info(dbname, AccessExclusiveLock, &db_id, NULL, NULL, + if (!get_db_info(dbname, AccessExclusiveLock, &db_id, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &src_tblspcoid, NULL, NULL, NULL, NULL, NULL, NULL)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_DATABASE), @@ -2693,7 +2695,7 @@ pg_database_collation_actual_version(PG_FUNCTION_ARGS) static bool get_db_info(const char *name, LOCKMODE lockmode, Oid *dbIdP, Oid *ownerIdP, - int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP, + int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP, bool *dbHasLoginEvtP, TransactionId *dbFrozenXidP, MultiXactId *dbMinMultiP, Oid *dbTablespace, char **dbCollate, char **dbCtype, char **dbIculocale, char **dbIcurules, @@ -2778,6 +2780,9 @@ get_db_info(const char *name, LOCKMODE lockmode, /* allowed as template? */ if (dbIsTemplateP) *dbIsTemplateP = dbform->datistemplate; + /* Has on login event trigger? */ + if (dbHasLoginEvtP) + *dbHasLoginEvtP = dbform->dathasloginevt; /* allowing connections? */ if (dbAllowConnP) *dbAllowConnP = dbform->datallowconn; -- cgit v1.2.3