pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Dimitri Fontaine <dimitri@2ndQuadrant.fr>
To: Robert Haas <robertmhaas@gmail.com>
Cc: Alvaro Herrera <alvherre@2ndquadrant.com>
Cc: PostgreSQL Hackers <pgsql-hackers@postgresql.org>
Subject: Re: Event Triggers: adding information
Date: Tue, 22 Jan 2013 13:29:26 +0100
Message-ID: <m2vcapl7tl.fsf@2ndQuadrant.fr> (raw)
In-Reply-To: <m2622pmnnn.fsf@2ndQuadrant.fr>
References: <m2txrsdzxa.fsf@2ndQuadrant.fr>
	<m2zk1j9c44.fsf@2ndQuadrant.fr>
	<CA+Tgmob6kmAySE5yXvd3uE9LifHunufMg9iU3GmbJ5bpGPiHjQ@mail.gmail.com>
	<m2k3sbe51z.fsf@2ndQuadrant.fr>
	<CA+TgmoZjOACnHOKrz-eucj3FJXrYJzA-_yjSqajOQR8qkjCi=w@mail.gmail.com>
	<m2bodi55yn.fsf@2ndQuadrant.fr>
	<CA+TgmoZTxXGAkoyQD0aNOyju1X19SnVfk7KV9fsJCv63bS-C4g@mail.gmail.com>
	<m27go1ot1a.fsf@2ndQuadrant.fr>
	<20130104205251.GB9191@alvh.no-ip.org>
	<m28v88pqin.fsf@2ndQuadrant.fr>
	<20130109165829.GB4490@alvh.no-ip.org>
	<CA+TgmobykpymdGyfbCDEfS6+-50X-AKYTdK88fjMS4-mY5SBdw@mail.gmail.com>
	<m2ehhkrfqk.fsf@2ndQuadrant.fr>
	<CA+TgmobfeB_YpgMv5NjW52tG36Hg_DY=jq0XDkE5zwCstPQ4pg@mail.gmail.com>
	<m2pq14m7sx.fsf@2ndQuadrant.fr>
	<CA+TgmoYEW583z+oisToCYQMz2grzpavdXrCi3-W2D_+nucVhzQ@mail.gmail.com>
	<m2k3rbhh79.fsf@2ndQuadrant.fr>
	<CA+TgmoZYFhn=DyenBLr8KUZXYHtgjo-O8YE-7y61WKR6F05UQA@mail.gmail.com>
	<m21udesaz3.fsf@2ndQuadrant.fr>
	<CA+TgmoZPhj6Rw-DottwresCJnOmRewbOxp2AABwyxP2k7vZf-Q@mail.gmail.com>
	<m2622pmnnn.fsf@2ndQuadrant.fr>
List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>

Dimitri Fontaine <dimitri@2ndQuadrant.fr> writes:
> I added some in the attached patch.
>
>  doc/src/sgml/event-trigger.sgml             |   10 ++
>  src/backend/commands/event_trigger.c        |    6 +-
>  src/test/regress/expected/event_trigger.out |  106 +++++++++++++++++++
>  src/test/regress/sql/event_trigger.sql      |   47 ++++++++
>  4 files changed, 167 insertions(+), 2 deletions(-)

And I did drop a comment line I didn't mean to when trying things out,
so here's the update copy. There's a bug fix in there too, in both the
versions of the patch, that the new regression tests exercise.

Regards,
-- 
Dimitri Fontaine
http://2ndQuadrant.fr     PostgreSQL : Expertise, Formation et Support

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Attachments:

event_trigger_harness.v1.patch (text/x-patch, 10.7K) download *** a/doc/src/sgml/event-trigger.sgml --- b/doc/src/sgml/event-trigger.sgml *************** *** 52,57 **** --- 52,67 ---- </para> <para> + Event Triggers themselves are not run in + a <xref linkend="sql-savepoint">. That means that you can stop the + execution of the current command by issuing a <command>RAISE + EXCEPTION</command> command from anywhere in your trigger function, and + that if an error occurs in the command itself (e.g. + when <command>DROP</command> targets an object that does not exists), + the <literal>ddl_command_end</> triggers will not get run. + </para> + + <para> For a complete list of commands supported by the event trigger mechanism, see <xref linkend="event-trigger-matrix">. </para> *** a/src/backend/commands/event_trigger.c --- b/src/backend/commands/event_trigger.c *************** *** 551,557 **** filter_event_trigger(const char **tag, EventTriggerCacheItem *item) } /* Filter by tags, if any were specified. */ ! if (item->ntags != 0 && bsearch(&tag, item->tag, item->ntags, sizeof(char *), pg_qsort_strcmp) == NULL) return false; --- 551,557 ---- } /* Filter by tags, if any were specified. */ ! if (item->ntags != 0 && bsearch(tag, item->tag, item->ntags, sizeof(char *), pg_qsort_strcmp) == NULL) return false; *************** *** 752,757 **** EventTriggerInvoke(List *fn_oid_list, EventTriggerData *trigdata) --- 752,760 ---- ListCell *lc; bool first = true; + /* Guard against stack overflow due to recursive event trigger */ + check_stack_depth(); + /* * Let's evaluate event triggers in their own memory context, so * that any leaks get cleaned up promptly. *** a/src/test/regress/expected/event_trigger.out --- b/src/test/regress/expected/event_trigger.out *************** *** 67,72 **** alter event trigger regress_event_trigger enable; --- 67,73 ---- alter event trigger regress_event_trigger disable; -- regress_event_trigger2 should fire, but not regress_event_trigger create table event_trigger_fire1 (a int); + NOTICE: test_event_trigger: ddl_command_start CREATE TABLE NOTICE: test_event_trigger: ddl_command_end CREATE TABLE -- but nothing should fire here drop table event_trigger_fire1; *************** *** 90,95 **** ERROR: event trigger "regress_event_trigger" does not exist --- 91,201 ---- drop role regression_bob; ERROR: role "regression_bob" cannot be dropped because some objects depend on it DETAIL: owner of event trigger regress_event_trigger3 + -- now try something crazy to ensure we don't crash the backend + create function test_event_trigger_drop_function() + returns event_trigger + set max_stack_depth to '100' -- limit the size of the stack trace we output + as $$ + BEGIN + drop function test_event_trigger2() cascade; + END + $$ language plpgsql; + NOTICE: test_event_trigger: ddl_command_start CREATE FUNCTION + NOTICE: test_event_trigger: ddl_command_end CREATE FUNCTION + create function test_event_trigger2() returns event_trigger as $$ + BEGIN + RAISE NOTICE 'test_event_trigger2: % %', tg_event, tg_tag; + END + $$ language plpgsql; + NOTICE: test_event_trigger: ddl_command_start CREATE FUNCTION + NOTICE: test_event_trigger: ddl_command_end CREATE FUNCTION + create event trigger drop_test_a on "ddl_command_start" + execute procedure test_event_trigger_drop_function(); + create event trigger drop_test_b on "ddl_command_start" + execute procedure test_event_trigger2(); + -- now watch the fun + create table event_trigger_fire1 (a int); + ERROR: stack depth limit exceeded + HINT: Increase the configuration parameter "max_stack_depth" (currently 100kB), after ensuring the platform's stack depth limit is adequate. + CONTEXT: SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + SQL statement "drop function test_event_trigger2() cascade" + PL/pgSQL function test_event_trigger_drop_function() line 3 at SQL statement + -- now limit the event trigger to avoid infinite recursion + drop event trigger drop_test_a; + create event trigger drop_test_a on "ddl_command_start" + when tag in ('create table') + execute procedure test_event_trigger_drop_function(); + -- and try again, see if we crash + -- + -- we want to avoid seeing the following in the regression tests: + -- ERROR: cache lookup failed for function 30201 + -- because the OID of course changes each time + -- + set client_min_messages to fatal; + create table event_trigger_fire1 (a int); + reset client_min_messages; + -- then cleanup the crazy test + drop event trigger drop_test_a; + drop event trigger drop_test_b; + drop function test_event_trigger_drop_function(); + NOTICE: test_event_trigger: ddl_command_end DROP FUNCTION -- these are all OK; the second one should emit a NOTICE drop event trigger if exists regress_event_trigger2; drop event trigger if exists regress_event_trigger2; *** a/src/test/regress/sql/event_trigger.sql --- b/src/test/regress/sql/event_trigger.sql *************** *** 95,100 **** drop event trigger regress_event_trigger; --- 95,147 ---- -- should fail, regression_bob owns regress_event_trigger2/3 drop role regression_bob; + -- now try something crazy to ensure we don't crash the backend + create function test_event_trigger_drop_function() + returns event_trigger + set max_stack_depth to '100' -- limit the size of the stack trace we output + as $$ + BEGIN + drop function test_event_trigger2() cascade; + END + $$ language plpgsql; + + create function test_event_trigger2() returns event_trigger as $$ + BEGIN + RAISE NOTICE 'test_event_trigger2: % %', tg_event, tg_tag; + END + $$ language plpgsql; + + create event trigger drop_test_a on "ddl_command_start" + execute procedure test_event_trigger_drop_function(); + + create event trigger drop_test_b on "ddl_command_start" + execute procedure test_event_trigger2(); + + -- now watch the fun + create table event_trigger_fire1 (a int); + + -- now limit the event trigger to avoid infinite recursion + drop event trigger drop_test_a; + + create event trigger drop_test_a on "ddl_command_start" + when tag in ('create table') + execute procedure test_event_trigger_drop_function(); + + -- and try again, see if we crash + -- + -- we want to avoid seeing the following in the regression tests: + -- ERROR: cache lookup failed for function 30201 + -- because the OID of course changes each time + -- + set client_min_messages to fatal; + create table event_trigger_fire1 (a int); + reset client_min_messages; + + -- then cleanup the crazy test + drop event trigger drop_test_a; + drop event trigger drop_test_b; + drop function test_event_trigger_drop_function(); + -- these are all OK; the second one should emit a NOTICE drop event trigger if exists regress_event_trigger2; drop event trigger if exists regress_event_trigger2;

view thread (114+ messages)  latest in thread

Message-ID: <m2vcapl7tl.fsf@2ndQuadrant.fr>
Permalink:  ../m2vcapl7tl.fsf@2ndQuadrant.fr/
Also on:    postgresql.org/message-id/m2vcapl7tl.fsf@2ndQuadrant.fr

 ·  · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-hackers@postgresql.org
  Cc: dimitri@2ndQuadrant.fr, robertmhaas@gmail.com, alvherre@2ndquadrant.com
  Subject: Re: Event Triggers: adding information
  In-Reply-To: <m2vcapl7tl.fsf@2ndQuadrant.fr>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox