Skip to content

Commit 32aa14d

Browse files
committed
Fix confusion about event trigger vs. plain function in plpgsql.
The function hash table keys made by compute_function_hashkey() failed to distinguish event-trigger call context from regular call context. This meant that once we'd successfully made a hash entry for an event trigger (either by validation, or by normal use as an event trigger), an attempt to call the trigger function as a plain function would find this hash entry and thereby bypass the you-can't-do-that check in do_compile(). Thus we'd attempt to execute the function, leading to strange errors or even crashes, depending on function contents and server version. To fix, add an isEventTrigger field to PLpgSQL_func_hashkey, paralleling the longstanding infrastructure for regular triggers. This fits into what had been pad space, so there's no risk of an ABI break, even assuming that any third-party code is looking at these hash keys. (I considered replacing isTrigger with a PLpgSQL_trigtype enum field, but felt that that carried some API/ABI risk. Maybe we should change it in HEAD though.) Per bug #16266 from Alexander Lakhin. This has been broken since event triggers were invented, so back-patch to all supported branches. Discussion: https://postgr.es/m/16266-fcd7f838e97ba5d4@postgresql.org
1 parent 16e6c96 commit 32aa14d

File tree

4 files changed

+21
-6
lines changed

4 files changed

+21
-6
lines changed

src/pl/plpgsql/src/pl_comp.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2420,12 +2420,19 @@ compute_function_hashkey(FunctionCallInfo fcinfo,
24202420

24212421
/* get call context */
24222422
hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo);
2423+
hashkey->isEventTrigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
24232424

24242425
/*
2425-
* if trigger, get its OID. In validation mode we do not know what
2426-
* relation or transition table names are intended to be used, so we leave
2427-
* trigOid zero; the hash entry built in this case will never really be
2428-
* used.
2426+
* If DML trigger, include trigger's OID in the hash, so that each trigger
2427+
* usage gets a different hash entry, allowing for e.g. different relation
2428+
* rowtypes or transition table names. In validation mode we do not know
2429+
* what relation or transition table names are intended to be used, so we
2430+
* leave trigOid zero; the hash entry built in this case will never be
2431+
* used for any actual calls.
2432+
*
2433+
* We don't currently need to distinguish different event trigger usages
2434+
* in the same way, since the special parameter variables don't vary in
2435+
* type in that case.
24292436
*/
24302437
if (hashkey->isTrigger && !forValidator)
24312438
{

src/pl/plpgsql/src/plpgsql.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -938,15 +938,16 @@ typedef struct PLpgSQL_func_hashkey
938938
{
939939
Oid funcOid;
940940

941-
bool isTrigger; /* true if called as a trigger */
941+
bool isTrigger; /* true if called as a DML trigger */
942+
bool isEventTrigger; /* true if called as an event trigger */
942943

943944
/* be careful that pad bytes in this struct get zeroed! */
944945

945946
/*
946947
* For a trigger function, the OID of the trigger is part of the hash key
947948
* --- we want to compile the trigger function separately for each trigger
948949
* it is used with, in case the rowtype or transition table names are
949-
* different. Zero if not called as a trigger.
950+
* different. Zero if not called as a DML trigger.
950951
*/
951952
Oid trigOid;
952953

src/test/regress/expected/event_trigger.out

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ BEGIN
99
RAISE NOTICE 'test_event_trigger: % %', tg_event, tg_tag;
1010
END
1111
$$ language plpgsql;
12+
-- should fail, can't call it as a plain function
13+
SELECT test_event_trigger();
14+
ERROR: trigger functions can only be called as triggers
15+
CONTEXT: compilation of PL/pgSQL function "test_event_trigger" near line 1
1216
-- should fail, event triggers cannot have declared arguments
1317
create function test_event_trigger_arg(name text)
1418
returns event_trigger as $$ BEGIN RETURN 1; END $$ language plpgsql;

src/test/regress/sql/event_trigger.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ BEGIN
1010
END
1111
$$ language plpgsql;
1212

13+
-- should fail, can't call it as a plain function
14+
SELECT test_event_trigger();
15+
1316
-- should fail, event triggers cannot have declared arguments
1417
create function test_event_trigger_arg(name text)
1518
returns event_trigger as $$ BEGIN RETURN 1; END $$ language plpgsql;

0 commit comments

Comments
 (0)