event_triggers_v1.7--v1.8.patch

text/x-patch

Filename: event_triggers_v1.7--v1.8.patch
Type: text/x-patch
Part: 0
Message: Re: Event Triggers reduced, v1

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
Series: patch v1
File+
doc/src/sgml/catalogs.sgml 20 11
doc/src/sgml/event-trigger.sgml 466 0
doc/src/sgml/filelist.sgml 1 0
doc/src/sgml/plperl.sgml 7 7
doc/src/sgml/plpgsql.sgml 10 14
doc/src/sgml/plpython.sgml 6 6
doc/src/sgml/pltcl.sgml 4 4
doc/src/sgml/postgres.sgml 1 0
doc/src/sgml/ref/alter_event_trigger.sgml 5 5
doc/src/sgml/ref/create_event_trigger.sgml 43 172
doc/src/sgml/ref/drop_event_trigger.sgml 9 7
doc/src/sgml/trigger.sgml 0 18
src/backend/catalog/aclchk.c 40 0
src/backend/catalog/Makefile 1 2
src/backend/catalog/objectaddress.c 5 1
src/backend/catalog/pg_event_trigger.c 0 409
src/backend/commands/alter.c 4 4
src/backend/commands/dropcmds.c 4 0
src/backend/commands/event_trigger.c 107 630
src/backend/parser/gram.y 3 24
src/backend/tcop/utility.c 66 6
src/backend/utils/adt/pseudotypes.c 27 0
src/backend/utils/adt/ruleutils.c 1 2
src/backend/utils/cache/evtcache.c 1241 30
src/bin/pg_dump/common.c 3 3
src/bin/pg_dump/pg_dump.c 32 30
src/bin/pg_dump/pg_dump.h 2 2
src/bin/pg_dump/pg_dump_sort.c 4 3
src/bin/psql/command.c 1 1
src/bin/psql/describe.c 5 6
src/bin/psql/describe.h 1 1
src/bin/psql/help.c 1 1
src/include/catalog/pg_event_trigger.h 0 118
src/include/catalog/pg_proc.h 5 0
src/include/catalog/pg_type.h 1 1
src/include/commands/event_trigger.h 6 1
src/include/utils/acl.h 2 0
src/include/utils/builtins.h 2 1
src/include/utils/evtcache.h 130 0
src/pl/plperl/expected/plperl_trigger.out 2 2
src/pl/plperl/plperl.c 10 4
src/pl/plperl/sql/plperl_trigger.sql 2 2
src/pl/plpgsql/src/pl_comp.c 20 4
src/pl/plpgsql/src/pl_exec.c 28 4
src/pl/plpgsql/src/plpgsql.h 3 0
src/pl/plpython/expected/plpython_trigger.out 2 2
src/pl/plpython/plpy_exec.c 24 4
src/pl/plpython/sql/plpython_trigger.sql 2 2
src/pl/tcl/expected/pltcl_setup.out 2 2
src/pl/tcl/pltcl.c 4 2
src/pl/tcl/sql/pltcl_setup.sql 2 2
src/test/regress/expected/event_triggers.out 250 247
src/test/regress/expected/type_sanity.out 8 10
src/test/regress/sql/event_triggers.sql 14 15
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 2b46b75..b100a42 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -99,11 +99,6 @@
      </row>
 
      <row>
-      <entry><link linkend="catalog-pg-event-trigger"><structname>pg_event_trigger</structname></link></entry>
-      <entry>event triggers</entry>
-     </row>
-
-     <row>
       <entry><link linkend="catalog-pg-constraint"><structname>pg_constraint</structname></link></entry>
       <entry>check constraints, unique constraints, primary key constraints, foreign key constraints</entry>
      </row>
@@ -149,6 +144,11 @@
      </row>
 
      <row>
+      <entry><link linkend="catalog-pg-event-trigger"><structname>pg_event_trigger</structname></link></entry>
+      <entry>event triggers</entry>
+     </row>
+
+     <row>
       <entry><link linkend="catalog-pg-extension"><structname>pg_extension</structname></link></entry>
       <entry>installed extensions</entry>
      </row>
@@ -1871,6 +1871,7 @@
 
   <para>
    The catalog <structname>pg_event_trigger</structname> stores event triggers.
+   See <xref linkend="event-triggers"> for more information.
   </para>
 
   <table>
@@ -1891,23 +1892,28 @@
       <entry><structfield>evtname</structfield></entry>
       <entry><type>name</type></entry>
       <entry></entry>
-      <entry>Trigger name (unique)</entry>
+      <entry>Trigger name (must be unique)</entry>
      </row>
 
      <row>
       <entry><structfield>evtevent</structfield></entry>
       <entry><type>name</type></entry>
       <entry></entry>
-      <entry>The event this trigger fires for.</entry>
+      <entry>Identifies the event for which this trigger fires</entry>
+     </row>
+
+     <row>
+      <entry><structfield>evtowner</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry>
+      <entry>Owner of the event trigger</entry>
      </row>
 
      <row>
       <entry><structfield>evtfoid</structfield></entry>
       <entry><type>oid</type></entry>
       <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
-      <entry>
-       The OID of the function called by this event trigger.
-      </entry>
+      <entry>The function to be called</entry>
      </row>
 
      <row>
@@ -1928,7 +1934,10 @@
       <entry><structfield>evttags</structfield></entry>
       <entry><type>text[]</type></entry>
       <entry></entry>
-      <entry>Command tags of the commands this trigger is restricted to.</entry>
+      <entry>
+        Command tags for which this trigger will fire.  If NULL, the firing
+        of this trigger is not restricted on the basis of the command tag.
+      </entry>
      </row>
     </tbody>
    </tgroup>
diff --git a/doc/src/sgml/event-trigger.sgml b/doc/src/sgml/event-trigger.sgml
new file mode 100644
index 0000000..52e9764
--- /dev/null
+++ b/doc/src/sgml/event-trigger.sgml
@@ -0,0 +1,466 @@
+<!-- doc/src/sgml/event-trigger.sgml -->
+
+ <chapter id="event-triggers">
+  <title>Event Triggers</title>
+
+  <indexterm zone="event-triggers">
+   <primary>event trigger</primary>
+  </indexterm>
+
+  <para>
+   To supplement the trigger mechanism discussed in <xref linkend="triggers">,
+   <productname>PostgreSQL</> also provides event triggers.  Unlike regular
+   triggers, which are attached to a single table and capture only DML events,
+   event triggers are global to a particular database and are capable of
+   capturing DDL events.
+  </para>
+
+  <para>
+   Like regular triggers, event triggers can be written in any procedural
+   language that includes event trigger support, or in C, but not in plain
+   SQL.
+  </para>
+
+  <sect1 id="event-trigger-definition">
+   <title>Overview of Event Trigger Behavior</title>
+
+   <para>
+     An event trigger fires whenever the event with which it is
+     associated occurs in the database in which it is defined.  Currently,
+     the only supported event is <literal>command_start</>.  Support for
+     additional events may be added in future releases.
+   </para>
+
+   <para>
+     The <literal>command_start</> event occurs just before the execution of
+     many SQL commands, most of which can be broadly described as
+     <link linkend="ddl">DDL</link>.  There are a number of commands that,
+     for various reasons, are specifically excluded from the event trigger
+     system:
+
+    <itemizedlist>
+     <listitem>
+      <para>
+       The <literal>command_start</> event does not occur for commands that
+       access or modify data within a particular table, such
+       <xref linkend="sql-select">, <xref linkend="sql-insert">, 
+       <xref linkend="sql-update">, <xref linkend="sql-delete">, and
+       <xref linkend="sql-truncate">.  This also includes commands related
+       to prepared plans, such as <xref linkend="sql-prepare">,
+       <xref linkend="sql-deallocate">, <xref linkend="sql-declare">,
+       and <xref linkend="sql-fetch">.  Ordinary triggers or rules should
+       be used in these cases.
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+       The <literal>command_start</> event does not occur for commands that
+       create, alter, or drop global objects.  Unlike the event trigger, these
+       objects are not part of the current database; they are accessible from
+       all databases in the cluster, and are therefore unaffected by event
+       triggers.  Such objects include databases, tablespaces, and roles.
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+       The <literal>command_start</> event does not occur for commands where
+       firing a trigger might result either result in system instability or
+       interfere with the administrator's ability to regain control of the
+       database.  These include transaction control commands, such as
+       <xref linkend="sql-begin"> or <xref linkend="sql-commit">; configuration
+       commands, such as <xref linkend="sql-set"> or <xref linkend="sql-show">;
+       and commands related to the event trigger mechanism itself, such as
+       <xref linkend="sql-createeventtrigger">,
+       <xref linkend="sql-altereventtrigger">, and
+       <xref linkend="sql-dropeventtrigger">.
+      </para>
+     </listitem>
+    </itemizedlist>
+   </para>
+
+   <para>
+     For a complete list of commands supported by the event trigger mechanism,
+     see <xref linkend="event-trigger-matrix">.
+   </para>
+
+   <para>
+     In order to create an event trigger, you must first create a function with
+     the special return type <literal>event_trigger</literal>.  This function
+     need not (and may not) return a value; the return type serves merely as
+     a signal that the function is to be invoked as an event trigger.
+   </para>
+
+   <para>
+     If more than one event trigger is defined for a particular event, they will
+     fire in alphabetical order by trigger name.
+   </para>
+
+   <para>
+     A trigger definition can also specify a <literal>WHEN</literal>
+     condition so that, for example, a <literal>command_start</literal>
+     trigger can be fired only for particular commands which the user wishes
+     to intercept. A common use of such triggers is to restrict the range of
+     DDL operations which users may perform.
+   </para>
+  </sect1>
+
+  <sect1 id="event-trigger-matrix">
+   <title>Event Trigger Firing Matrix</title>
+
+   <para>
+     <xref linkend="event-trigger-by-command-tag"> lists all commands
+     for which event triggers are supported.
+   </para>
+
+   <table id="event-trigger-by-command-tag">
+     <title>Event Trigger Support by Command Tag</title>
+     <tgroup cols="2">
+      <thead>
+       <row>
+        <entry>command tag</entry>
+        <entry><literal>command_start</literal></entry>
+       </row>
+      </thead>
+      <tbody>
+       <row>
+        <entry align="left"><literal>ALTER AGGREGATE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER COLLATION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER CONVERSION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER DOMAIN</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER EXTENSION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER FOREIGN DATA WRAPPER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER FOREIGN TABLE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER FUNCTION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER LANGUAGE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER OPERATOR</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER OPERATOR CLASS</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER OPERATOR FAMILY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER SCHEMA</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER SEQUENCE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER SERVER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TABLE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TEXT SEARCH CONFIGURATION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TEXT SEARCH DICTIONARY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TEXT SEARCH PARSER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TEXT SEARCH TEMPLATE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TRIGGER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TYPE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER USER MAPPING</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER VIEW</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CLUSTER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE AGGREGATE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE CAST</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE COLLATION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE CONVERSION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE DOMAIN</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE EXTENSION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE FOREIGN DATA WRAPPER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE FOREIGN TABLE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE FUNCTION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE INDEX</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE LANGUAGE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE OPERATOR</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE OPERATOR CLASS</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE OPERATOR FAMILY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE RULE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE SCHEMA</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE SEQUENCE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE SERVER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TABLE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TABLE AS</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TEXT SEARCH CONFIGURATION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TEXT SEARCH DICTIONARY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TEXT SEARCH PARSER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TEXT SEARCH TEMPLATE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TRIGGER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TYPE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE USER MAPPING</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE VIEW</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP AGGREGATE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP CAST</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP COLLATION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP CONVERSION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP DOMAIN</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP EXTENSION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP FOREIGN DATA WRAPPER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP FOREIGN TABLE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP FUNCTION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP INDEX</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP LANGUAGE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP OPERATOR</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP OPERATOR CLASS</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP OPERATOR FAMILY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP RULE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP SCHEMA</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP SEQUENCE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP SERVER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TABLE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TEXT SEARCH CONFIGURATION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TEXT SEARCH DICTIONARY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TEXT SEARCH PARSER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TEXT SEARCH TEMPLATE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TRIGGER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TYPE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP USER MAPPING</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP VIEW</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>LOAD</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>REINDEX</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>SELECT INTO</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>VACUUM</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+       </row>
+      </tbody>
+     </tgroup>
+   </table>
+  </sect1>
+
+</chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 82b9e39..db4cc3a 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -61,6 +61,7 @@
 <!ENTITY rules      SYSTEM "rules.sgml">
 <!ENTITY spi        SYSTEM "spi.sgml">
 <!ENTITY trigger    SYSTEM "trigger.sgml">
+<!ENTITY event-trigger SYSTEM "event-trigger.sgml">
 <!ENTITY xaggr      SYSTEM "xaggr.sgml">
 <!ENTITY xfunc      SYSTEM "xfunc.sgml">
 <!ENTITY xindex     SYSTEM "xindex.sgml">
diff --git a/doc/src/sgml/plperl.sgml b/doc/src/sgml/plperl.sgml
index b783e86..e490086 100644
--- a/doc/src/sgml/plperl.sgml
+++ b/doc/src/sgml/plperl.sgml
@@ -634,7 +634,7 @@ SELECT init_hosts_query();
 SELECT query_hosts('192.168.1.0/30');
 SELECT release_hosts_query();
 
-    query_hosts
+    query_hosts    
 -----------------
  (1,192.168.1.1)
  (2,192.168.1.2)
@@ -1220,7 +1220,7 @@ CREATE TRIGGER test_valid_id_trig
   </sect2>
 
     <sect2 id="plperl-event-trigger">
-     <title>Trigger Procedures on Events in PL/Perl </title>
+     <title>Trigger Procedures on Events in PL/Perl</title>
 
      <indexterm>
       <primary>event trigger</primary>
@@ -1229,9 +1229,9 @@ CREATE TRIGGER test_valid_id_trig
 
     <para>
      Event trigger procedures can be written in PL/Perl.
-     <productname>PostgreSQL</productname> requires that a procedure that is to be called
-     as a trigger must be declared as a function with no arguments
-     and a return type of <literal>event_trigger</>.
+     <productname>PostgreSQL</productname> requires that a procedure that
+     is to be called as an event trigger must be declared as a function with
+     no arguments and a return type of <literal>event_trigger</>.
     </para>
 
     <para>
@@ -1272,7 +1272,7 @@ CREATE TRIGGER test_valid_id_trig
        <term><varname>$_TD-&gt;{objectname}</varname></term>
        <listitem>
         <para>
-         The name of the objectthat caused the trigger procedure
+         The name of the object that caused the trigger procedure
          to be invoked.
         </para>
        </listitem>
@@ -1289,7 +1289,7 @@ CREATE TRIGGER test_valid_id_trig
       </varlistentry>
      </variablelist>
     </para>
-      </sect2>
+  </sect2>
 
  </sect1>
 
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index fadd5d7..a21aaf2 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -3378,7 +3378,7 @@ RAISE unique_violation USING MESSAGE = 'Duplicate user ID: ' || user_id;
   </indexterm>
 
   <sect2 id="plpgsql-dml-trigger">
-   <title>Triggers on data change</title>
+   <title>Triggers on data changes</title>
 
    <para>
     <application>PL/pgSQL</application> can be used to define trigger
@@ -3930,19 +3930,19 @@ SELECT * FROM sales_summary_bytime;
 </sect2>
 
   <sect2 id="plpgsql-event-trigger">
-   <title>Triggers on event</title>
+   <title>Triggers on events</title>
 
    <para>
-    <application>PL/pgSQL</application> can be used to define command
-    trigger procedures. An event trigger procedure is created with the
-    <command>CREATE FUNCTION</> command, declaring it as a function with
-    no arguments and a return type of <type>event trigger</type>.
+    <application>PL/pgSQL</application> can be used to define event
+    triggers.  <productname>PostgreSQL</> requires that a procedure that
+    is to be called as an event trigger must be declared as a function with
+    no arguments and a return type of <literal>event_trigger</>.
    </para>
 
-  <para>
-   When a <application>PL/pgSQL</application> function is called as a
-   event trigger, several special variables are created automatically
-   in the top-level block. They are:
+   <para>
+    When a <application>PL/pgSQL</application> function is called as a
+    event trigger, several special variables are created automatically
+    in the top-level block. They are:
 
    <variablelist>
     <varlistentry>
@@ -3999,10 +3999,6 @@ SELECT * FROM sales_summary_bytime;
    </variablelist>
   </para>
 
-  <para>
-   The event trigger function's return value is not used.
-  </para>
-
    <para>
     <xref linkend="plpgsql-event-trigger-example"> shows an example of a
     event trigger procedure in <application>PL/pgSQL</application>.
diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml
index 07f017a..99ce8f9 100644
--- a/doc/src/sgml/plpython.sgml
+++ b/doc/src/sgml/plpython.sgml
@@ -441,7 +441,7 @@ return (1, 2, 3, 4, 5)
 $$ LANGUAGE plpythonu;
 
 SELECT return_arr();
- return_arr
+ return_arr  
 -------------
  {1,2,3,4,5}
 (1 row)
@@ -872,7 +872,7 @@ $$ LANGUAGE plpythonu;
   </sect2>
 
    <sect2 id="plpython-event-trigger">
-     <title>Trigger Procedures on Events in PL/Python </title>
+     <title>Trigger Procedures on Events in PL/Python</title>
 
      <indexterm>
       <primary>event trigger</primary>
@@ -881,9 +881,9 @@ $$ LANGUAGE plpythonu;
 
     <para>
      Event trigger procedures can be written in PL/Python.
-     <productname>PostgreSQL</productname> requires that a procedure that is to be called
-     as a trigger must be declared as a function with no arguments
-     and a return type of <literal>event_trigger</>.
+     <productname>PostgreSQL</productname> requires that a procedure that
+     is to be called as an event trigger must be declared as a function with
+     no arguments and a return type of <literal>event_trigger</>.
     </para>
 
     <para>
@@ -924,7 +924,7 @@ $$ LANGUAGE plpythonu;
        <term><varname>TD["objectname"]</varname></term>
        <listitem>
         <para>
-         The name of the objectthat caused the trigger procedure
+         The name of the object that caused the trigger procedure
          to be invoked.
         </para>
        </listitem>
diff --git a/doc/src/sgml/pltcl.sgml b/doc/src/sgml/pltcl.sgml
index c9a4e4c..c932ddb 100644
--- a/doc/src/sgml/pltcl.sgml
+++ b/doc/src/sgml/pltcl.sgml
@@ -725,9 +725,9 @@ CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
 
     <para>
      Event trigger procedures can be written in PL/Tcl.
-     <productname>PostgreSQL</productname> requires that a procedure that is to be called
-     as a trigger must be declared as a function with no arguments
-     and a return type of <literal>event_trigger</>.
+     <productname>PostgreSQL</productname> requires that a procedure that
+     is to be called as an event trigger must be declared as a function with
+     no arguments and a return type of <literal>event_trigger</>.
     </para>
 
     <para>
@@ -768,7 +768,7 @@ CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
        <term><varname>$TG_objectname</varname></term>
        <listitem>
         <para>
-         The name of the objectthat caused the trigger procedure
+         The name of the object that caused the trigger procedure
          to be invoked.
         </para>
        </listitem>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 7e80265..4ef1fc1 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -208,6 +208,7 @@
 
   &extend;
   &trigger;
+  &event-trigger;
   &rules;
 
   &xplang;
diff --git a/doc/src/sgml/ref/alter_event_trigger.sgml b/doc/src/sgml/ref/alter_event_trigger.sgml
index e236921..db4727b 100644
--- a/doc/src/sgml/ref/alter_event_trigger.sgml
+++ b/doc/src/sgml/ref/alter_event_trigger.sgml
@@ -12,7 +12,7 @@ PostgreSQL documentation
 
  <refnamediv>
   <refname>ALTER EVENT TRIGGER</refname>
-  <refpurpose>change the definition of a trigger</refpurpose>
+  <refpurpose>change the definition of an event trigger</refpurpose>
  </refnamediv>
 
  <indexterm zone="sql-altereventtrigger">
@@ -46,7 +46,7 @@ ALTER EVENT TRIGGER <replaceable class="PARAMETER">name</replaceable> RENAME TO
   </para>
 
   <para>
-   You must be superuser to alter a event trigger.
+   You must be superuser to alter an event trigger.
   </para>
  </refsect1>
 
@@ -93,12 +93,12 @@ ALTER EVENT TRIGGER <replaceable class="PARAMETER">name</replaceable> RENAME TO
   </variablelist>
  </refsect1>
 
- <refsect1>
+ <refsect1 id="sql-alterventtrigger-compatibility">
   <title>Compatibility</title>
 
   <para>
-   <command>ALTER EVENT TRIGGER</command> is a <productname>PostgreSQL</>
-   extension of the SQL standard.
+   There is no <command>ALTER EVENT TRIGGER</command> statement in the
+   SQL standard.
   </para>
  </refsect1>
 
diff --git a/doc/src/sgml/ref/create_event_trigger.sgml b/doc/src/sgml/ref/create_event_trigger.sgml
index af06c88..3b3d474 100644
--- a/doc/src/sgml/ref/create_event_trigger.sgml
+++ b/doc/src/sgml/ref/create_event_trigger.sgml
@@ -12,7 +12,7 @@ PostgreSQL documentation
 
  <refnamediv>
   <refname>CREATE EVENT TRIGGER</refname>
-  <refpurpose>define a new trigger</refpurpose>
+  <refpurpose>define a new event trigger</refpurpose>
  </refnamediv>
 
  <indexterm zone="sql-createeventtrigger">
@@ -23,100 +23,8 @@ PostgreSQL documentation
 <synopsis>
 CREATE EVENT TRIGGER <replaceable class="PARAMETER">name</replaceable>
   ON <replaceable class="PARAMETER">event</replaceable>
-  [ WHEN <replaceable class="PARAMETER">variable</replaceable> IN (tag [, tag [, ...] ] ) ]
-  EXECUTE PROCEDURE <replaceable class="PARAMETER">function_name</replaceable> ()
-
-<phrase>where <replaceable class="parameter">event</replaceable> can be one of:</phrase>
-
-  command_start
-
-<phrase>where <replaceable class="parameter">tag</replaceable> can be one of:</phrase>
-
-    ALTER AGGREGATE
-    ALTER COLLATION
-    ALTER CONVERSION
-    ALTER DOMAIN
-    ALTER EXTENSION
-    ALTER FOREIGN DATA WRAPPER
-    ALTER FOREIGN TABLE
-    ALTER FUNCTION
-    ALTER LANGUAGE
-    ALTER OPERATOR
-    ALTER OPERATOR CLASS
-    ALTER OPERATOR FAMILY
-    ALTER SCHEMA
-    ALTER SEQUENCE
-    ALTER SERVER
-    ALTER TABLE
-    ALTER TEXT SEARCH CONFIGURATION
-    ALTER TEXT SEARCH DICTIONARY
-    ALTER TEXT SEARCH PARSER
-    ALTER TEXT SEARCH TEMPLATE
-    ALTER TRIGGER
-    ALTER TYPE
-    ALTER USER MAPPING
-    ALTER VIEW
-    CLUSTER
-    CREATE AGGREGATE
-    CREATE CAST
-    CREATE COLLATION
-    CREATE CONVERSION
-    CREATE DOMAIN
-    CREATE EXTENSION
-    CREATE FOREIGN DATA WRAPPER
-    CREATE FOREIGN TABLE
-    CREATE FUNCTION
-    CREATE INDEX
-    CREATE LANGUAGE
-    CREATE OPERATOR
-    CREATE OPERATOR CLASS
-    CREATE OPERATOR FAMILY
-    CREATE RULE
-    CREATE SCHEMA
-    CREATE SEQUENCE
-    CREATE SERVER
-    CREATE TABLE
-    CREATE TABLE AS
-    CREATE TEXT SEARCH CONFIGURATION
-    CREATE TEXT SEARCH DICTIONARY
-    CREATE TEXT SEARCH PARSER
-    CREATE TEXT SEARCH TEMPLATE
-    CREATE TRIGGER
-    CREATE TYPE
-    CREATE USER MAPPING
-    CREATE VIEW
-    DROP AGGREGATE
-    DROP CAST
-    DROP COLLATION
-    DROP CONVERSION
-    DROP DOMAIN
-    DROP EXTENSION
-    DROP FOREIGN DATA WRAPPER
-    DROP FOREIGN TABLE
-    DROP FUNCTION
-    DROP INDEX
-    DROP LANGUAGE
-    DROP OPERATOR
-    DROP OPERATOR CLASS
-    DROP OPERATOR FAMILY
-    DROP RULE
-    DROP SCHEMA
-    DROP SEQUENCE
-    DROP SERVER
-    DROP TABLE
-    DROP TEXT SEARCH CONFIGURATION
-    DROP TEXT SEARCH DICTIONARY
-    DROP TEXT SEARCH PARSER
-    DROP TEXT SEARCH TEMPLATE
-    DROP TRIGGER
-    DROP TYPE
-    DROP USER MAPPING
-    DROP VIEW
-    LOAD
-    REINDEX
-    SELECT INTO
-    VACUUM
-
+  [ WHEN <replaceable class="PARAMETER">filter_variable</replaceable> IN (filter_value [ , ... ] ) ]
+  EXECUTE PROCEDURE <replaceable class="PARAMETER">function_name</replaceable>()
 </synopsis>
  </refsynopsisdiv>
 
@@ -125,35 +33,11 @@ CREATE EVENT TRIGGER <replaceable class="PARAMETER">name</replaceable>
 
   <para>
    <command>CREATE EVENT TRIGGER</command> creates a new event trigger.
-   The trigger will be associated with the specified event and will
-   execute the specified
-   function <replaceable class="parameter">function_name</replaceable> when
-   that event is run.
-  </para>
-
-  <para>
-   The command trigger gives a procedure to fire before the event is
-   executed. In some cases the procedure can be fired instead of the event
-   code PostgreSQL would run itself. A command trigger's function must
-   return <literal>event_trigger</literal> data type. It can then only
-   abort the execution of the command by raising an exception.
-  </para>
-
-  <para>
-   If multiple triggers of the same kind are defined for the same event,
-   they will be fired in alphabetical order by name.
-  </para>
-
-  <para>
-   Note that objects dropped by the effect of <literal>DROP
-   CASCADE</literal> will not result in a event trigger firing, only the
-   top-level event for the main object will fire a event trigger. That
-   also applies to other dependencies following, as in <literal>DROP OWNED
-   BY</literal>.
-  </para>
-
-  <para>
-   Refer to <xref linkend="triggers"> for more information about triggers.
+   Whenever the designated event occurs and the <literal>WHEN</> condition
+   associated with the trigger, if any, is satisfied, the trigger function
+   will be executed.  For a general introduction to event triggers, see
+   <xref linkend="event-triggers">.  The user who creates an event trigger
+   becomes its owner.
   </para>
  </refsect1>
 
@@ -165,52 +49,44 @@ CREATE EVENT TRIGGER <replaceable class="PARAMETER">name</replaceable>
     <term><replaceable class="parameter">name</replaceable></term>
     <listitem>
      <para>
-      The name to give the new trigger. This must be distinct from the name
-      of any other trigger for the same table. The name cannot be
-      schema-qualified.
+      The name to give the new trigger.  This name must be unique within
+      the database.
      </para>
     </listitem>
    </varlistentry>
 
    <varlistentry>
-    <term><replaceable class="parameter">tag</replaceable></term>
+    <term><replaceable class="parameter">event</replaceable></term>
     <listitem>
      <para>
-      The tag of the command the trigger is for. Supported commands are
-      mainly those acting on database objects, plus some more facilities.
-      That leaves out the following list of non supported commands.
-     </para>
-     <para>
-      Commands that refer to global objects, such as databases, tablespaces
-      and roles, are not supported.
-     </para>
-     <para>
-      The command <literal>ALTER TYPE ... ADD VALUE ...</literal> prevents
-      transaction control entirely, thus no command trigger will get fired
-      when it's used.
-     </para>
-     <para>
-      Commands that are related to transaction control (such
-      as <literal>BEGIN</literal> or <literal>COMMIT</literal>), related to
-      prepared plans
-      (e.g. <literal>PREPARE</literal>, <literal>DEALLOCATE</literal>),
-      cursors management
-      (e.g. <literal>DECLARE</literal>, <literal>FETCH</literal>), setting
-      variables (<literal>SET</literal>), the <literal>LISTEN</literal>
-      feature, and security are not supported either.
+      The name of the event that triggers a call to the given function.
+      See <xref linkend="event-trigger-definition"> for more information
+      on event names.
      </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">filter_variable</replaceable></term>
+    <listitem>
      <para>
-      Event triggers on <literal>CREATE EVENT
-      TRIGGER</literal>, <literal>ALTER EVENT TRIGGER</literal>
-      and <literal>DROP EVENT TRIGGER</literal> are not supported so as
-      not to be able to take over control from a superuser.
+      The name of a variable used to filter events.  This makes it possible
+      to restrict the firing of the trigger to a subset of the cases in which
+      it is supported.  Currently the only suppoted
+      <replaceable class="parameter">filter_variable</replaceable>
+      is <literal>TAG</literal>.
      </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">filter_value</replaceable></term>
+    <listitem>
      <para>
-      Triggers on <literal>ANY</literal> command support more commands than
-      just this list, and will only provide the <literal>command
-      tag</literal> argument as <literal>NOT NULL</literal>. Supporting more
-      commands is made so that you can actually block <xref linkend="ddl">
-      commands in one go.
+      A list of values for the
+      associated <replaceable class="parameter">filter_variable</replaceable>
+      for which the trigger should fire.  For <literal>TAG</>, this means a
+      list of command tags (e.g. <literal>'DROP FUNCTION'</>).
      </para>
     </listitem>
    </varlistentry>
@@ -220,7 +96,7 @@ CREATE EVENT TRIGGER <replaceable class="PARAMETER">name</replaceable>
     <listitem>
      <para>
       A user-supplied function that is declared as taking no argument and
-      returning type <literal>event trigger</literal>.
+      returning type <literal>event_trigger</literal>.
      </para>
      <para>
       If your event trigger is implemented in <literal>C</literal> then it
@@ -234,24 +110,20 @@ CREATE EVENT TRIGGER <replaceable class="PARAMETER">name</replaceable>
   </variablelist>
  </refsect1>
 
- <refsect1 id="SQL-CREATEEVENTTRIGGER-notes">
+ <refsect1 id="sql-createeventtrigger-notes">
   <title>Notes</title>
 
   <para>
    To create a trigger on a event, the user must be superuser.
   </para>
-
-  <para>
-   Use <xref linkend="sql-dropeventtrigger"> to remove a event trigger.
-  </para>
  </refsect1>
 
- <refsect1 id="SQL-CREATEEVENTTRIGGER-examples">
+ <refsect1 id="sql-createeventtrigger-examples">
   <title>Examples</title>
 
   <para>
-   Forbids the execution of any command supported by the event trigger
-   mechanism, which includes all commands listed above:
+   Forbid the execution of any command supported by the event trigger
+   mechanism:
 
 <programlisting>
 CREATE OR REPLACE FUNCTION abort_any_command()
@@ -291,13 +163,12 @@ $$;
   </para>
  </refsect1>
 
- <refsect1 id="SQL-CREATEEVENTTRIGGER-compatibility">
+ <refsect1 id="sql-createeventtrigger-compatibility">
   <title>Compatibility</title>
 
   <para>
-   <command>CREATE EVENT TRIGGER</command> is a
-   <productname>PostgreSQL</productname> extension of the <acronym>SQL</>
-   standard.
+   There is no <command>CREATE EVENT TRIGGER</command> statement in the
+   SQL standard.
   </para>
 
  </refsect1>
diff --git a/doc/src/sgml/ref/drop_event_trigger.sgml b/doc/src/sgml/ref/drop_event_trigger.sgml
index fc45dff..86f9628 100644
--- a/doc/src/sgml/ref/drop_event_trigger.sgml
+++ b/doc/src/sgml/ref/drop_event_trigger.sgml
@@ -12,7 +12,7 @@ PostgreSQL documentation
 
  <refnamediv>
   <refname>DROP EVENT TRIGGER</refname>
-  <refpurpose>remove a event trigger</refpurpose>
+  <refpurpose>remove an event trigger</refpurpose>
  </refnamediv>
 
  <indexterm zone="sql-dropeventtrigger">
@@ -29,8 +29,9 @@ DROP EVENT TRIGGER [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceabl
   <title>Description</title>
 
   <para>
-   <command>DROP EVENT TRIGGER</command> removes an existing trigger definition.
-   To execute this command, the current user must be superuser.
+   <command>DROP EVENT TRIGGER</command> removes an existing event trigger.
+   To execute this command, the current user must be the owner of the event
+   trigger.
   </para>
  </refsect1>
 
@@ -79,7 +80,7 @@ DROP EVENT TRIGGER [ IF EXISTS ] <replaceable class="PARAMETER">name</replaceabl
   </variablelist>
  </refsect1>
 
- <refsect1 id="SQL-DROPEVENTTRIGGER-examples">
+ <refsect1 id="sql-dropeventtrigger-examples">
   <title>Examples</title>
 
   <para>
@@ -90,13 +91,14 @@ DROP EVENT TRIGGER snitch;
 </programlisting></para>
  </refsect1>
 
- <refsect1 id="SQL-DROPEVENTTRIGGER-compatibility">
+ <refsect1 id="sql-dropeventtrigger-compatibility">
   <title>Compatibility</title>
 
   <para>
-   The <command>DROP EVENT TRIGGER</command> statement is a
-   <productname>PostgreSQL</productname> extension.
+   There is no <command>DROP EVENT TRIGGER</command> statement in the
+   SQL standard.
   </para>
+
  </refsect1>
 
  <refsect1>
diff --git a/doc/src/sgml/trigger.sgml b/doc/src/sgml/trigger.sgml
index 32994b9..f579340 100644
--- a/doc/src/sgml/trigger.sgml
+++ b/doc/src/sgml/trigger.sgml
@@ -27,24 +27,6 @@
    plain SQL function language.
   </para>
 
-  <para>
-   <productname>PostgreSQL</productname> offers both triggers on commands
-   (see <xref linkend="ddl">) and triggers on data manipulation
-   (see <xref linkend="dml">).
-  </para>
-
-  <sect1 id="command-triggers">
-   <title>Overview of Event Trigger Behavior</title>
-
-   <para>
-    A trigger is a specification that the database should automatically
-    execute a particular function whenever a certain command is performed.
-    The whole set of <productname>PostgreSQL</productname> commands is not
-    supported for triggers, see <xref linkend="sql-createeventtrigger">
-    for details.
-   </para>
-  </sect1>
-
   <sect1 id="trigger-definition">
    <title>Overview of Trigger Behavior</title>
 
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 6e29758..df6da1f 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -12,8 +12,7 @@ include $(top_builddir)/src/Makefile.global
 
 OBJS = catalog.o dependency.o heap.o index.o indexing.o namespace.o aclchk.o \
        objectaddress.o pg_aggregate.o pg_collation.o pg_constraint.o pg_conversion.o \
-       pg_depend.o pg_enum.o pg_event_trigger.o pg_inherits.o pg_largeobject.o \
-       pg_namespace.o \
+       pg_depend.o pg_enum.o pg_inherits.o pg_largeobject.o pg_namespace.o \
        pg_operator.o pg_proc.o pg_range.o pg_db_role_setting.o pg_shdepend.o \
        pg_type.o storage.o toasting.o
 
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 56c40b1..b097813 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -29,6 +29,7 @@
 #include "catalog/pg_conversion.h"
 #include "catalog/pg_database.h"
 #include "catalog/pg_default_acl.h"
+#include "catalog/pg_event_trigger.h"
 #include "catalog/pg_extension.h"
 #include "catalog/pg_foreign_data_wrapper.h"
 #include "catalog/pg_foreign_server.h"
@@ -277,6 +278,10 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
 		case ACL_KIND_FOREIGN_SERVER:
 			whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
 			break;
+		case ACL_KIND_EVENT_TRIGGER:
+			elog(ERROR, "grantable rights not supported for event triggers");
+			/* not reached, but keep compiler quiet */
+			return ACL_NO_RIGHTS;
 		case ACL_KIND_TYPE:
 			whole_mask = ACL_ALL_RIGHTS_TYPE;
 			break;
@@ -3286,6 +3291,8 @@ static const char *const no_priv_msg[MAX_ACL_KIND] =
 	gettext_noop("permission denied for foreign-data wrapper %s"),
 	/* ACL_KIND_FOREIGN_SERVER */
 	gettext_noop("permission denied for foreign server %s"),
+	/* ACL_KIND_EVENT_TRIGGER */
+	gettext_noop("permission denied for event trigger %s"),
 	/* ACL_KIND_EXTENSION */
 	gettext_noop("permission denied for extension %s"),
 };
@@ -3330,6 +3337,8 @@ static const char *const not_owner_msg[MAX_ACL_KIND] =
 	gettext_noop("must be owner of foreign-data wrapper %s"),
 	/* ACL_KIND_FOREIGN_SERVER */
 	gettext_noop("must be owner of foreign server %s"),
+	/* ACL_KIND_EVENT_TRIGGER */
+	gettext_noop("must be owner of event trigger %s"),
 	/* ACL_KIND_EXTENSION */
 	gettext_noop("must be owner of extension %s"),
 };
@@ -3455,6 +3464,10 @@ pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnum, Oid roleid,
 			return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
 		case ACL_KIND_FOREIGN_SERVER:
 			return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
+		case ACL_KIND_EVENT_TRIGGER:
+			elog(ERROR, "grantable rights not supported for event triggers");
+			/* not reached, but keep compiler quiet */
+			return ACL_NO_RIGHTS;
 		case ACL_KIND_TYPE:
 			return pg_type_aclmask(table_oid, roleid, mask, how);
 		default:
@@ -4876,6 +4889,33 @@ pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
 }
 
 /*
+ * Ownership check for an event trigger (specified by OID).
+ */
+bool
+pg_event_trigger_ownercheck(Oid et_oid, Oid roleid)
+{
+	HeapTuple	tuple;
+	Oid			ownerId;
+
+	/* Superusers bypass all permission checking. */
+	if (superuser_arg(roleid))
+		return true;
+
+	tuple = SearchSysCache1(EVENTTRIGGEROID, ObjectIdGetDatum(et_oid));
+	if (!HeapTupleIsValid(tuple))
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_OBJECT),
+				 errmsg("event trigger with OID %u does not exist",
+						et_oid)));
+
+	ownerId = ((Form_pg_event_trigger) GETSTRUCT(tuple))->evtowner;
+
+	ReleaseSysCache(tuple);
+
+	return has_privs_of_role(roleid, ownerId);
+}
+
+/*
  * Ownership check for a database (specified by OID).
  */
 bool
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 40ae60d..5b8140b 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -997,6 +997,11 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
 							   NameListToString(objname));
 			break;
+		case OBJECT_EVENT_TRIGGER:
+			if (!pg_event_trigger_ownercheck(address.objectId, roleid))
+				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EVENT_TRIGGER,
+							   NameListToString(objname));
+			break;
 		case OBJECT_LANGUAGE:
 			if (!pg_language_ownercheck(address.objectId, roleid))
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
@@ -1075,7 +1080,6 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
 			break;
 		case OBJECT_TSPARSER:
 		case OBJECT_TSTEMPLATE:
-		case OBJECT_EVENT_TRIGGER:
 			/* We treat these object types as being owned by superusers */
 			if (!superuser_arg(roleid))
 				ereport(ERROR,
diff --git a/src/backend/catalog/pg_event_trigger.c b/src/backend/catalog/pg_event_trigger.c
deleted file mode 100644
index 4995d2b..0000000
--- a/src/backend/catalog/pg_event_trigger.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * pg_event_trigger.c
- *	  routines to support manipulation of the pg_event_trigger relation
- *
- * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *	  src/backend/catalog/pg_event_trigger.c
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include "catalog/pg_event_trigger.h"
-#include "utils/builtins.h"
-
-char *
-event_to_string(TrigEvent event)
-{
-	switch (event)
-	{
-		case E_CommandStart:
-			return "command_start";
-	}
-	return NULL;
-}
-
-TrigEvent
-parse_event_name(char *event)
-{
-	if (pg_strcasecmp(event, "command_start") == 0)
-		return E_CommandStart;
-	else
-		ereport(ERROR,
-				(errcode(ERRCODE_SYNTAX_ERROR),
-				 errmsg("unrecognized event \"%s\"", event)));
-
-	/* make compiler happy */
-	return -1;
-}
-
-TrigEventCommand
-parse_event_tag(char *command, bool noerror)
-{
-	if (pg_strcasecmp(command, "ALTER AGGREGATE") == 0)
-		return E_AlterAggregate;
-	else if (pg_strcasecmp(command, "ALTER COLLATION") == 0)
-		return E_AlterCollation;
-	else if (pg_strcasecmp(command, "ALTER CONVERSION") == 0)
-		return E_AlterConversion;
-	else if (pg_strcasecmp(command, "ALTER DOMAIN") == 0)
-		return E_AlterDomain;
-	else if (pg_strcasecmp(command, "ALTER EXTENSION") == 0)
-		return E_AlterExtension;
-	else if (pg_strcasecmp(command, "ALTER FOREIGN DATA WRAPPER") == 0)
-		return E_AlterForeignDataWrapper;
-	else if (pg_strcasecmp(command, "ALTER FOREIGN TABLE") == 0)
-		return E_AlterForeignTable;
-	else if (pg_strcasecmp(command, "ALTER FUNCTION") == 0)
-		return E_AlterFunction;
-	else if (pg_strcasecmp(command, "ALTER LANGUAGE") == 0)
-		return E_AlterLanguage;
-	else if (pg_strcasecmp(command, "ALTER OPERATOR") == 0)
-		return E_AlterOperator;
-	else if (pg_strcasecmp(command, "ALTER OPERATOR CLASS") == 0)
-		return E_AlterOperatorClass;
-	else if (pg_strcasecmp(command, "ALTER OPERATOR FAMILY") == 0)
-		return E_AlterOperatorFamily;
-	else if (pg_strcasecmp(command, "ALTER SEQUENCE") == 0)
-		return E_AlterSequence;
-	else if (pg_strcasecmp(command, "ALTER SERVER") == 0)
-		return E_AlterServer;
-	else if (pg_strcasecmp(command, "ALTER SCHEMA") == 0)
-		return E_AlterSchema;
-	else if (pg_strcasecmp(command, "ALTER TABLE") == 0)
-		return E_AlterTable;
-	else if (pg_strcasecmp(command, "ALTER TEXT SEARCH CONFIGURATION") == 0)
-		return E_AlterTextSearchConfiguration;
-	else if (pg_strcasecmp(command, "ALTER TEXT SEARCH DICTIONARY") == 0)
-		return E_AlterTextSearchDictionary;
-	else if (pg_strcasecmp(command, "ALTER TEXT SEARCH PARSER") == 0)
-		return E_AlterTextSearchParser;
-	else if (pg_strcasecmp(command, "ALTER TEXT SEARCH TEMPLATE") == 0)
-		return E_AlterTextSearchTemplate;
-	else if (pg_strcasecmp(command, "ALTER TRIGGER") == 0)
-		return E_AlterTrigger;
-	else if (pg_strcasecmp(command, "ALTER TYPE") == 0)
-		return E_AlterType;
-	else if (pg_strcasecmp(command, "ALTER USER MAPPING") == 0)
-		return E_AlterUserMapping;
-	else if (pg_strcasecmp(command, "ALTER VIEW") == 0)
-		return E_AlterView;
-	else if (pg_strcasecmp(command, "CLUSTER") == 0)
-		return E_Cluster;
-	else if (pg_strcasecmp(command, "CREATE AGGREGATE") == 0)
-		return E_CreateAggregate;
-	else if (pg_strcasecmp(command, "CREATE CAST") == 0)
-		return E_CreateCast;
-	else if (pg_strcasecmp(command, "CREATE COLLATION") == 0)
-		return E_CreateCollation;
-	else if (pg_strcasecmp(command, "CREATE CONVERSION") == 0)
-		return E_CreateConversion;
-	else if (pg_strcasecmp(command, "CREATE DOMAIN") == 0)
-		return E_CreateDomain;
-	else if (pg_strcasecmp(command, "CREATE EXTENSION") == 0)
-		return E_CreateExtension;
-	else if (pg_strcasecmp(command, "CREATE FOREIGN DATA WRAPPER") == 0)
-		return E_CreateForeignDataWrapper;
-	else if (pg_strcasecmp(command, "CREATE FOREIGN TABLE") == 0)
-		return E_CreateForeignTable;
-	else if (pg_strcasecmp(command, "CREATE FUNCTION") == 0)
-		return E_CreateFunction;
-	else if (pg_strcasecmp(command, "CREATE INDEX") == 0)
-		return E_CreateIndex;
-	else if (pg_strcasecmp(command, "CREATE LANGUAGE") == 0)
-		return E_CreateLanguage;
-	else if (pg_strcasecmp(command, "CREATE OPERATOR") == 0)
-		return E_CreateOperator;
-	else if (pg_strcasecmp(command, "CREATE OPERATOR CLASS") == 0)
-		return E_CreateOperatorClass;
-	else if (pg_strcasecmp(command, "CREATE OPERATOR FAMILY") == 0)
-		return E_CreateOperatorFamily;
-	else if (pg_strcasecmp(command, "CREATE RULE") == 0)
-		return E_CreateRule;
-	else if (pg_strcasecmp(command, "CREATE SEQUENCE") == 0)
-		return E_CreateSequence;
-	else if (pg_strcasecmp(command, "CREATE SERVER") == 0)
-		return E_CreateServer;
-	else if (pg_strcasecmp(command, "CREATE SCHEMA") == 0)
-		return E_CreateSchema;
-	else if (pg_strcasecmp(command, "CREATE TABLE") == 0)
-		return E_CreateTable;
-	else if (pg_strcasecmp(command, "CREATE TABLE AS") == 0)
-		return E_CreateTableAs;
-	else if (pg_strcasecmp(command, "CREATE TEXT SEARCH CONFIGURATION") == 0)
-		return E_CreateTextSearchConfiguration;
-	else if (pg_strcasecmp(command, "CREATE TEXT SEARCH DICTIONARY") == 0)
-		return E_CreateTextSearchDictionary;
-	else if (pg_strcasecmp(command, "CREATE TEXT SEARCH PARSER") == 0)
-		return E_CreateTextSearchParser;
-	else if (pg_strcasecmp(command, "CREATE TEXT SEARCH TEMPLATE") == 0)
-		return E_CreateTextSearchTemplate;
-	else if (pg_strcasecmp(command, "CREATE TRIGGER") == 0)
-		return E_CreateTrigger;
-	else if (pg_strcasecmp(command, "CREATE TYPE") == 0)
-		return E_CreateType;
-	else if (pg_strcasecmp(command, "CREATE USER MAPPING") == 0)
-		return E_CreateUserMapping;
-	else if (pg_strcasecmp(command, "CREATE VIEW") == 0)
-		return E_CreateView;
-	else if (pg_strcasecmp(command, "DROP AGGREGATE") == 0)
-		return E_DropAggregate;
-	else if (pg_strcasecmp(command, "DROP CAST") == 0)
-		return E_DropCast;
-	else if (pg_strcasecmp(command, "DROP COLLATION") == 0)
-		return E_DropCollation;
-	else if (pg_strcasecmp(command, "DROP CONVERSION") == 0)
-		return E_DropConversion;
-	else if (pg_strcasecmp(command, "DROP DOMAIN") == 0)
-		return E_DropDomain;
-	else if (pg_strcasecmp(command, "DROP EXTENSION") == 0)
-		return E_DropExtension;
-	else if (pg_strcasecmp(command, "DROP FOREIGN DATA WRAPPER") == 0)
-		return E_DropForeignDataWrapper;
-	else if (pg_strcasecmp(command, "DROP FOREIGN TABLE") == 0)
-		return E_DropForeignTable;
-	else if (pg_strcasecmp(command, "DROP FUNCTION") == 0)
-		return E_DropFunction;
-	else if (pg_strcasecmp(command, "DROP INDEX") == 0)
-		return E_DropIndex;
-	else if (pg_strcasecmp(command, "DROP LANGUAGE") == 0)
-		return E_DropLanguage;
-	else if (pg_strcasecmp(command, "DROP OPERATOR") == 0)
-		return E_DropOperator;
-	else if (pg_strcasecmp(command, "DROP OPERATOR CLASS") == 0)
-		return E_DropOperatorClass;
-	else if (pg_strcasecmp(command, "DROP OPERATOR FAMILY") == 0)
-		return E_DropOperatorFamily;
-	else if (pg_strcasecmp(command, "DROP RULE") == 0)
-		return E_DropRule;
-	else if (pg_strcasecmp(command, "DROP SCHEMA") == 0)
-		return E_DropSchema;
-	else if (pg_strcasecmp(command, "DROP SEQUENCE") == 0)
-		return E_DropSequence;
-	else if (pg_strcasecmp(command, "DROP SERVER") == 0)
-		return E_DropServer;
-	else if (pg_strcasecmp(command, "DROP TABLE") == 0)
-		return E_DropTable;
-	else if (pg_strcasecmp(command, "DROP TEXT SEARCH CONFIGURATION") == 0)
-		return E_DropTextSearchConfiguration;
-	else if (pg_strcasecmp(command, "DROP TEXT SEARCH DICTIONARY") == 0)
-		return E_DropTextSearchDictionary;
-	else if (pg_strcasecmp(command, "DROP TEXT SEARCH PARSER") == 0)
-		return E_DropTextSearchParser;
-	else if (pg_strcasecmp(command, "DROP TEXT SEARCH TEMPLATE") == 0)
-		return E_DropTextSearchTemplate;
-	else if (pg_strcasecmp(command, "DROP TRIGGER") == 0)
-		return E_DropTrigger;
-	else if (pg_strcasecmp(command, "DROP TYPE") == 0)
-		return E_DropType;
-	else if (pg_strcasecmp(command, "DROP USER MAPPING") == 0)
-		return E_DropUserMapping;
-	else if (pg_strcasecmp(command, "DROP VIEW") == 0)
-		return E_DropView;
-	else if (pg_strcasecmp(command, "LOAD") == 0)
-		return E_Load;
-	else if (pg_strcasecmp(command, "REINDEX") == 0)
-		return E_Reindex;
-	else if (pg_strcasecmp(command, "SELECT INTO") == 0)
-		return E_SelectInto;
-	else if (pg_strcasecmp(command, "VACUUM") == 0)
-		return E_Vacuum;
-	else
-	{
-		if (!noerror)
-			ereport(ERROR,
-					(errcode(ERRCODE_SYNTAX_ERROR),
-					 errmsg("unrecognized command \"%s\"", command)));
-	}
-	return E_UNKNOWN;
-}
-
-char *
-command_to_string(TrigEventCommand command)
-{
-	switch (command)
-	{
-		case E_UNKNOWN:
-			return "UNKNOWN";
-		case E_ANY:
-			return "ANY";
-		case E_AlterCast:
-			return "ALTER CAST";
-		case E_AlterIndex:
-			return "ALTER INDEX";
-		case E_AlterAggregate:
-			return "ALTER AGGREGATE";
-		case E_AlterCollation:
-			return "ALTER COLLATION";
-		case E_AlterConversion:
-			return "ALTER CONVERSION";
-		case E_AlterDomain:
-			return "ALTER DOMAIN";
-		case E_AlterExtension:
-			return "ALTER EXTENSION";
-		case E_AlterForeignDataWrapper:
-			return "ALTER FOREIGN DATA WRAPPER";
-		case E_AlterForeignTable:
-			return "ALTER FOREIGN TABLE";
-		case E_AlterFunction:
-			return "ALTER FUNCTION";
-		case E_AlterLanguage:
-			return "ALTER LANGUAGE";
-		case E_AlterOperator:
-			return "ALTER OPERATOR";
-		case E_AlterOperatorClass:
-			return "ALTER OPERATOR CLASS";
-		case E_AlterOperatorFamily:
-			return "ALTER OPERATOR FAMILY";
-		case E_AlterSequence:
-			return "ALTER SEQUENCE";
-		case E_AlterServer:
-			return "ALTER SERVER";
-		case E_AlterSchema:
-			return "ALTER SCHEMA";
-		case E_AlterTable:
-			return "ALTER TABLE";
-		case E_AlterTextSearchConfiguration:
-			return "ALTER TEXT SEARCH CONFIGURATION";
-		case E_AlterTextSearchDictionary:
-			return "ALTER TEXT SEARCH DICTIONARY";
-		case E_AlterTextSearchParser:
-			return "ALTER TEXT SEARCH PARSER";
-		case E_AlterTextSearchTemplate:
-			return "ALTER TEXT SEARCH TEMPLATE";
-		case E_AlterTrigger:
-			return "ALTER TRIGGER";
-		case E_AlterType:
-			return "ALTER TYPE";
-		case E_AlterUserMapping:
-			return "ALTER USER MAPPING";
-		case E_AlterView:
-			return "ALTER VIEW";
-		case E_Cluster:
-			return "CLUSTER";
-		case E_CreateAggregate:
-			return "CREATE AGGREGATE";
-		case E_CreateCast:
-			return "CREATE CAST";
-		case E_CreateCollation:
-			return "CREATE COLLATION";
-		case E_CreateConversion:
-			return "CREATE CONVERSION";
-		case E_CreateDomain:
-			return "CREATE DOMAIN";
-		case E_CreateExtension:
-			return "CREATE EXTENSION";
-		case E_CreateForeignDataWrapper:
-			return "CREATE FOREIGN DATA WRAPPER";
-		case E_CreateForeignTable:
-			return "CREATE FOREIGN TABLE";
-		case E_CreateFunction:
-			return "CREATE FUNCTION";
-		case E_CreateIndex:
-			return "CREATE INDEX";
-		case E_CreateLanguage:
-			return "CREATE LANGUAGE";
-		case E_CreateOperator:
-			return "CREATE OPERATOR";
-		case E_CreateOperatorClass:
-			return "CREATE OPERATOR CLASS";
-		case E_CreateOperatorFamily:
-			return "CREATE OPERATOR FAMILY";
-		case E_CreateRule:
-			return "CREATE RULE";
-		case E_CreateSequence:
-			return "CREATE SEQUENCE";
-		case E_CreateServer:
-			return "CREATE SERVER";
-		case E_CreateSchema:
-			return "CREATE SCHEMA";
-		case E_CreateTable:
-			return "CREATE TABLE";
-		case E_CreateTableAs:
-			return "CREATE TABLE AS";
-		case E_CreateTextSearchConfiguration:
-			return "CREATE TEXT SEARCH CONFIGURATION";
-		case E_CreateTextSearchDictionary:
-			return "CREATE TEXT SEARCH DICTIONARY";
-		case E_CreateTextSearchParser:
-			return "CREATE TEXT SEARCH PARSER";
-		case E_CreateTextSearchTemplate:
-			return "CREATE TEXT SEARCH TEMPLATE";
-		case E_CreateTrigger:
-			return "CREATE TRIGGER";
-		case E_CreateType:
-			return "CREATE TYPE";
-		case E_CreateUserMapping:
-			return "CREATE USER MAPPING";
-		case E_CreateView:
-			return "CREATE VIEW";
-		case E_DropAggregate:
-			return "DROP AGGREGATE";
-		case E_DropCast:
-			return "DROP CAST";
-		case E_DropCollation:
-			return "DROP COLLATION";
-		case E_DropConversion:
-			return "DROP CONVERSION";
-		case E_DropDomain:
-			return "DROP DOMAIN";
-		case E_DropExtension:
-			return "DROP EXTENSION";
-		case E_DropForeignDataWrapper:
-			return "DROP FOREIGN DATA WRAPPER";
-		case E_DropForeignTable:
-			return "DROP FOREIGN TABLE";
-		case E_DropFunction:
-			return "DROP FUNCTION";
-		case E_DropIndex:
-			return "DROP INDEX";
-		case E_DropLanguage:
-			return "DROP LANGUAGE";
-		case E_DropOperator:
-			return "DROP OPERATOR";
-		case E_DropOperatorClass:
-			return "DROP OPERATOR CLASS";
-		case E_DropOperatorFamily:
-			return "DROP OPERATOR FAMILY";
-		case E_DropRule:
-			return "DROP RULE";
-		case E_DropSchema:
-			return "DROP SCHEMA";
-		case E_DropSequence:
-			return "DROP SEQUENCE";
-		case E_DropServer:
-			return "DROP SERVER";
-		case E_DropTable:
-			return "DROP TABLE";
-		case E_DropTextSearchConfiguration:
-			return "DROP TEXT SEARCH CONFIGURATION";
-		case E_DropTextSearchDictionary:
-			return "DROP TEXT SEARCH DICTIONARY";
-		case E_DropTextSearchParser:
-			return "DROP TEXT SEARCH PARSER";
-		case E_DropTextSearchTemplate:
-			return "DROP TEXT SEARCH TEMPLATE";
-		case E_DropTrigger:
-			return "DROP TRIGGER";
-		case E_DropType:
-			return "DROP TYPE";
-		case E_DropUserMapping:
-			return "DROP USER MAPPING";
-		case E_DropView:
-			return "DROP VIEW";
-		case E_Load:
-			return "LOAD";
-		case E_Reindex:
-			return "REINDEX";
-		case E_SelectInto:
-			return "SELECT INTO";
-		case E_Vacuum:
-			return "VACUUM";
-	}
-	return NULL;
-}
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 78ef831..19f9895 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -70,10 +70,6 @@ ExecRenameStmt(RenameStmt *stmt)
 			RenameDatabase(stmt->subname, stmt->newname);
 			break;
 
-		case OBJECT_EVENT_TRIGGER:
-			RenameEventTrigger(stmt->subname, stmt->newname);
-			break;
-
 		case OBJECT_FDW:
 			RenameForeignDataWrapper(stmt->subname, stmt->newname);
 			break;
@@ -82,6 +78,10 @@ ExecRenameStmt(RenameStmt *stmt)
 			RenameForeignServer(stmt->subname, stmt->newname);
 			break;
 
+		case OBJECT_EVENT_TRIGGER:
+			RenameEventTrigger(stmt->subname, stmt->newname);
+			break;
+
 		case OBJECT_FUNCTION:
 			RenameFunction(stmt->object, stmt->objarg, stmt->newname);
 			break;
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c
index 1b8529e..8f5d7e0 100644
--- a/src/backend/commands/dropcmds.c
+++ b/src/backend/commands/dropcmds.c
@@ -206,6 +206,10 @@ does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
 			args = NameListToString(list_truncate(objname,
 												  list_length(objname) - 1));
 			break;
+		case OBJECT_EVENT_TRIGGER:
+			msg = gettext_noop("event trigger \"%s\" does not exist, skipping");
+			name = NameListToString(objname);
+			break;
 		case OBJECT_RULE:
 			msg = gettext_noop("rule \"%s\" for relation \"%s\" does not exist, skipping");
 			name = strVal(llast(objname));
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index 4ea2848..502e34b 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -32,7 +32,6 @@
 #include "miscadmin.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
-#include "utils/evtcache.h"
 #include "utils/fmgroids.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
@@ -49,23 +48,6 @@ static void AlterEventTriggerOwner_internal(Relation rel,
 											Oid newOwnerId);
 
 /*
- * Check permission: command triggers are only available for superusers. Raise
- * an exception when requirements are not fullfilled.
- *
- * It's not clear how to accept that database owners be able to create command
- * triggers, a superuser could run a command that fires a trigger's procedure
- * written by the database owner and now running with superuser privileges.
- */
-static void
-CheckEventTriggerPrivileges()
-{
-	if (!superuser())
-		ereport(ERROR,
-				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				 (errmsg("must be superuser to use command triggers"))));
-}
-
-/*
  * Insert Command Trigger Tuple
  *
  * Insert the new pg_event_trigger row, and return the OID assigned to the new
@@ -111,7 +93,7 @@ InsertEventTriggerTuple(char *trigname, TrigEvent event, Oid evtOwner,
 		{
 			TrigEventCommand cmd = lfirst_int(lc);
 			char *cmdstr = command_to_string(cmd);
-			if (cmd == E_UNKNOWN || cmdstr == NULL)
+			if (cmd == ETC_UNKNOWN || cmdstr == NULL)
 				elog(ERROR, "Unknown command %d", cmd);
 			tags[i++] = PointerGetDatum(cstring_to_text(cmdstr));
 		}
@@ -158,7 +140,16 @@ CreateEventTrigger(CreateEventTrigStmt *stmt, const char *queryString)
 	Oid			funcrettype;
 	Oid			evtowner = GetUserId();
 
-	CheckEventTriggerPrivileges();
+	/*
+	 * It would be nice to allow database owners or even regular users to do
+	 * this, but there are obvious privilege escalation risks which would have
+	 * to somehow be plugged first.
+	 */
+	if (!superuser())
+		ereport(ERROR,
+			(errmsg("permission denied to create event trigger \"%s\"",
+                   stmt->trigname),
+            errhint("Must be superuser to create an event trigger.")));
 
 	/*
 	 * Find and validate the trigger function.
@@ -171,7 +162,7 @@ CreateEventTrigger(CreateEventTrigStmt *stmt, const char *queryString)
 	if (funcrettype != EVTTRIGGEROID)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-				 errmsg("function \"%s\" must return type \"command_trigger\"",
+				 errmsg("function \"%s\" must return type \"event_trigger\"",
 						NameListToString(stmt->funcname))));
 
 	/*
@@ -214,7 +205,7 @@ RemoveEventTriggerById(Oid trigOid)
 }
 
 /*
- * ALTER EVENT TRIGGER foo ON COMMAND ... ENABLE|DISABLE|ENABLE ALWAYS|REPLICA
+ * ALTER EVENT TRIGGER foo ENABLE|DISABLE|ENABLE ALWAYS|REPLICA
  */
 void
 AlterEventTrigger(AlterEventTrigStmt *stmt)
@@ -224,15 +215,18 @@ AlterEventTrigger(AlterEventTrigStmt *stmt)
 	Form_pg_event_trigger evtForm;
 	char        tgenabled = stmt->tgenabled;
 
-	CheckEventTriggerPrivileges();
-
 	tgrel = heap_open(EventTriggerRelationId, RowExclusiveLock);
 
-	tup = SearchSysCacheCopy1(EVENTTRIGGERNAME, CStringGetDatum(stmt->trigname));
+	tup = SearchSysCacheCopy1(EVENTTRIGGERNAME,
+							  CStringGetDatum(stmt->trigname));
 	if (!HeapTupleIsValid(tup))
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
-				 errmsg("event trigger \"%s\" does not exist", stmt->trigname)));
+				 errmsg("event trigger \"%s\" does not exist",
+					stmt->trigname)));
+    if (!pg_event_trigger_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+        aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EVENT_TRIGGER,
+                       stmt->trigname);
 
 	/* tuple is a copy, so we can modify it below */
 	evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
@@ -248,7 +242,7 @@ AlterEventTrigger(AlterEventTrigStmt *stmt)
 
 
 /*
- * Rename command trigger
+ * Rename event trigger
  */
 void
 RenameEventTrigger(const char *trigname, const char *newname)
@@ -257,8 +251,6 @@ RenameEventTrigger(const char *trigname, const char *newname)
 	Relation	rel;
 	Form_pg_event_trigger evtForm;
 
-	CheckEventTriggerPrivileges();
-
 	rel = heap_open(EventTriggerRelationId, RowExclusiveLock);
 
 	/* newname must be available */
@@ -273,6 +265,9 @@ RenameEventTrigger(const char *trigname, const char *newname)
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("event trigger \"%s\" does not exist", trigname)));
+    if (!pg_event_trigger_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+        aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EVENT_TRIGGER,
+                       trigname);
 
 	evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
 
@@ -344,22 +339,31 @@ AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
 {
 	Form_pg_event_trigger form;
 
-	CheckEventTriggerPrivileges();
-
 	form = (Form_pg_event_trigger) GETSTRUCT(tup);
 
-	if (form->evtowner != newOwnerId)
-	{
-		form->evtowner = newOwnerId;
+	if (form->evtowner == newOwnerId)
+		return;
 
-		simple_heap_update(rel, &tup->t_self, tup);
-		CatalogUpdateIndexes(rel, tup);
+    if (!pg_event_trigger_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+        aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EVENT_TRIGGER,
+                       NameStr(form->evtname));
 
-		/* Update owner dependency reference */
-		changeDependencyOnOwner(EventTriggerRelationId,
-								HeapTupleGetOid(tup),
-								newOwnerId);
-	}
+	/* New owner must be a superuser */
+	if (!superuser_arg(newOwnerId))
+		ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				 errmsg("permission denied to change owner of event trigger \"%s\"",
+					NameStr(form->evtname)),
+				 errhint("The owner of an event trigger must be a superuser.")));
+
+	form->evtowner = newOwnerId;
+	simple_heap_update(rel, &tup->t_self, tup);
+	CatalogUpdateIndexes(rel, tup);
+
+	/* Update owner dependency reference */
+	changeDependencyOnOwner(EventTriggerRelationId,
+							HeapTupleGetOid(tup),
+							newOwnerId);
 }
 
 /*
@@ -382,9 +386,9 @@ get_event_trigger_oid(const char *trigname, bool missing_ok)
 }
 
 /*
- * Functions to execute the command triggers.
+ * Functions to execute the event triggers.
  *
- * We call the functions that matches the command triggers definitions in
+ * We call the functions that matches the event triggers definitions in
  * alphabetical order, and give them those arguments:
  *
  *   toplevel command tag, text
@@ -394,7 +398,7 @@ get_event_trigger_oid(const char *trigname, bool missing_ok)
  *   objectname, text
  *
  * Those are passed down as special "context" magic variables and need specific
- * support in each PL that wants to support command triggers. All core PL do.
+ * support in each PL that wants to support event triggers. All core PL do.
  */
 
 static void
@@ -409,17 +413,27 @@ call_event_trigger_procedure(EventContext ev_ctx, TrigEvent tev,
 	fmgr_info(proc, &flinfo);
 
 	/*
-	 * Prepare the command trigger function context from the Command Context.
+	 * Prepare the event trigger function context from the Command Context.
 	 * We prepare a dedicated Node here so as not to publish internal data.
 	 */
-	trigdata.type		= T_EventTriggerData;
-	trigdata.toplevel	= ev_ctx->toplevel;
-	trigdata.tag		= ev_ctx->tag;
-	trigdata.objectId	= ev_ctx->objectId;
+	trigdata.type = T_EventTriggerData;
+	trigdata.event = pstrdup(event_to_string(tev));
+	trigdata.toplevel = ev_ctx->toplevel;
+	trigdata.tag = ev_ctx->tag;
+	trigdata.objectId = ev_ctx->objectId;
 	trigdata.schemaname = ev_ctx->schemaname;
 	trigdata.objectname = ev_ctx->objectname;
-	trigdata.parsetree	= ev_ctx->parsetree;
-	trigdata.when       = pstrdup(event_to_string(tev));
+	trigdata.parsetree = ev_ctx->parsetree;
+
+	if (ev_ctx->operation == NULL)
+		trigdata.operation = NULL;
+	else
+		trigdata.operation = pstrdup(ev_ctx->operation);
+
+	if (ev_ctx->objecttype == -1)
+		trigdata.objecttype = NULL;
+	else
+		trigdata.objecttype = pstrdup(objecttype_to_string(ev_ctx->objecttype));
 
 	/*
 	 * Call the function, passing no arguments but setting a context.
@@ -436,599 +450,55 @@ call_event_trigger_procedure(EventContext ev_ctx, TrigEvent tev,
 
 /*
  * Routine to call to setup a EventContextData evt.
+ *
+ * The fields 'objecttype' must be set before calling other entry points. The
+ * fields 'operation', 'objectId', 'objectname' and 'schemaname' might be set
+ * to interesting values.
  */
 void
 InitEventContext(EventContext evt, const Node *parsetree)
 {
-	evt->command	= E_UNKNOWN;
-	evt->toplevel	= NULL;
-	evt->tag		= (char *) CreateCommandTag((Node *)parsetree);
-	evt->parsetree  = (Node *)parsetree;
-	evt->objectId   = InvalidOid;
+	evt->command = ETC_UNSET;
+	evt->toplevel = NULL;
+	evt->tag = (char *) CreateCommandTag((Node *)parsetree);
+	evt->parsetree = (Node *)parsetree;
+	evt->operation = NULL;
+	evt->objecttype = -1;
+	evt->objectId = InvalidOid;
 	evt->objectname = NULL;
 	evt->schemaname = NULL;
 
-	/*
-	 * Fill in the event command, which is an enum constant to match against
-	 * what's stored into catalogs. As we are storing that on disk, we need the
-	 * enum values to be stable, see src/include/catalog/pg_event_trigger.h for
-	 * details.
-	 */
-	switch (nodeTag(parsetree))
-	{
-		case T_CreateSchemaStmt:
-			evt->command = E_CreateSchema;
-			break;
-
-		case T_CreateStmt:
-			evt->command = E_CreateTable;
-			break;
-
-		case T_CreateForeignTableStmt:
-			evt->command = E_CreateForeignTable;
-			break;
-
-		case T_CreateExtensionStmt:
-			evt->command = E_CreateExtension;
-			break;
-
-		case T_AlterExtensionStmt:
-		case T_AlterExtensionContentsStmt:
-			evt->command = E_AlterExtension;
-			break;
-
-		case T_CreateFdwStmt:
-			evt->command = E_CreateForeignDataWrapper;
-			break;
-
-		case T_AlterFdwStmt:
-			evt->command = E_AlterForeignDataWrapper;
-			break;
-
-		case T_CreateForeignServerStmt:
-			evt->command = E_CreateServer;
-			break;
-
-		case T_AlterForeignServerStmt:
-			evt->command = E_AlterServer;
-			break;
-
-		case T_CreateUserMappingStmt:
-			evt->command = E_CreateUserMapping;
-			break;
-
-		case T_AlterUserMappingStmt:
-			evt->command = E_AlterUserMapping;
-			break;
-
-		case T_DropUserMappingStmt:
-			evt->command = E_DropUserMapping;
-			break;
-
-		case T_DropStmt:
-			switch (((DropStmt *) parsetree)->removeType)
-			{
-				case OBJECT_AGGREGATE:
-					evt->command = E_DropAggregate;
-					break;
-				case OBJECT_CAST:
-					evt->command = E_DropCast;
-					break;
-				case OBJECT_COLLATION:
-					evt->command = E_DropCollation;
-					break;
-				case OBJECT_CONVERSION:
-					evt->command = E_DropConversion;
-					break;
-				case OBJECT_DOMAIN:
-					evt->command = E_DropDomain;
-					break;
-				case OBJECT_EXTENSION:
-					evt->command = E_DropExtension;
-					break;
-				case OBJECT_FDW:
-					evt->command = E_DropForeignDataWrapper;
-					break;
-				case OBJECT_FOREIGN_SERVER:
-					evt->command = E_DropServer;
-					break;
-				case OBJECT_FOREIGN_TABLE:
-					evt->command = E_DropForeignTable;
-					break;
-				case OBJECT_FUNCTION:
-					evt->command = E_DropFunction;
-					break;
-				case OBJECT_INDEX:
-					evt->command = E_DropIndex;
-					break;
-				case OBJECT_LANGUAGE:
-					evt->command = E_DropLanguage;
-					break;
-				case OBJECT_OPCLASS:
-					evt->command = E_DropOperatorClass;
-					break;
-				case OBJECT_OPERATOR:
-					evt->command = E_DropOperator;
-					break;
-				case OBJECT_OPFAMILY:
-					evt->command = E_DropOperatorFamily;
-					break;
-				case OBJECT_SCHEMA:
-					evt->command = E_DropSchema;
-					break;
-				case OBJECT_SEQUENCE:
-					evt->command = E_DropSequence;
-					break;
-				case OBJECT_TABLE:
-					evt->command = E_DropTable;
-					break;
-				case OBJECT_TRIGGER:
-					evt->command = E_DropTrigger;
-					break;
-				case OBJECT_TSCONFIGURATION:
-					evt->command = E_DropTextSearchConfiguration;
-					break;
-				case OBJECT_TSDICTIONARY:
-					evt->command = E_DropTextSearchDictionary;
-					break;
-				case OBJECT_TSPARSER:
-					evt->command = E_DropTextSearchParser;
-					break;
-				case OBJECT_TSTEMPLATE:
-					evt->command = E_DropTextSearchTemplate;
-					break;
-				case OBJECT_TYPE:
-					evt->command = E_DropType;
-					break;
-				case OBJECT_VIEW:
-					evt->command = E_DropView;
-					break;
-				case OBJECT_ROLE:
-				case OBJECT_EVENT_TRIGGER:
-				case OBJECT_ATTRIBUTE:
-				case OBJECT_COLUMN:
-				case OBJECT_CONSTRAINT:
-				case OBJECT_DATABASE:
-				case OBJECT_LARGEOBJECT:
-				case OBJECT_RULE:
-				case OBJECT_TABLESPACE:
-					/* no support for specific command triggers */
-					break;
-			}
-			break;
-
-		case T_RenameStmt:
-			switch (((RenameStmt *) parsetree)->renameType)
-			{
-				case OBJECT_ATTRIBUTE:
-					evt->command = E_AlterType;
-					break;
-				case OBJECT_AGGREGATE:
-					evt->command = E_AlterAggregate;
-					break;
-				case OBJECT_CAST:
-					evt->command = E_AlterCast;
-					break;
-				case OBJECT_COLLATION:
-					evt->command = E_AlterCollation;
-					break;
-				case OBJECT_COLUMN:
-					evt->command = E_AlterTable;
-					break;
-				case OBJECT_CONVERSION:
-					evt->command = E_AlterConversion;
-					break;
-				case OBJECT_DOMAIN:
-					evt->command = E_AlterDomain;
-					break;
-				case OBJECT_EXTENSION:
-					evt->command = E_AlterExtension;
-					break;
-				case OBJECT_FDW:
-					evt->command = E_AlterForeignDataWrapper;
-					break;
-				case OBJECT_FOREIGN_SERVER:
-					evt->command = E_AlterServer;
-					break;
-				case OBJECT_FOREIGN_TABLE:
-					evt->command = E_AlterForeignTable;
-					break;
-				case OBJECT_FUNCTION:
-					evt->command = E_AlterFunction;
-					break;
-				case OBJECT_INDEX:
-					evt->command = E_AlterIndex;
-					break;
-				case OBJECT_LANGUAGE:
-					evt->command = E_AlterLanguage;
-					break;
-				case OBJECT_OPCLASS:
-					evt->command = E_AlterOperatorClass;
-					break;
-				case OBJECT_OPERATOR:
-					evt->command = E_AlterOperator;
-					break;
-				case OBJECT_OPFAMILY:
-					evt->command = E_AlterOperatorFamily;
-					break;
-				case OBJECT_SCHEMA:
-					evt->command = E_AlterSchema;
-					break;
-				case OBJECT_SEQUENCE:
-					evt->command = E_AlterSequence;
-					break;
-				case OBJECT_TABLE:
-					evt->command = E_AlterTable;
-					break;
-				case OBJECT_TRIGGER:
-					evt->command = E_AlterTrigger;
-					break;
-				case OBJECT_TSCONFIGURATION:
-					evt->command = E_AlterTextSearchConfiguration;
-					break;
-				case OBJECT_TSDICTIONARY:
-					evt->command = E_AlterTextSearchDictionary;
-					break;
-				case OBJECT_TSPARSER:
-					evt->command = E_AlterTextSearchParser;
-					break;
-				case OBJECT_TSTEMPLATE:
-					evt->command = E_AlterTextSearchTemplate;
-					break;
-				case OBJECT_TYPE:
-					evt->command = E_AlterType;
-					break;
-				case OBJECT_VIEW:
-					evt->command = E_AlterView;
-					break;
-				case OBJECT_ROLE:
-				case OBJECT_EVENT_TRIGGER:
-				case OBJECT_CONSTRAINT:
-				case OBJECT_DATABASE:
-				case OBJECT_LARGEOBJECT:
-				case OBJECT_RULE:
-				case OBJECT_TABLESPACE:
-					/* no support for specific command triggers */
-					break;
-			}
-			break;
-
-		case T_AlterObjectSchemaStmt:
-			switch (((AlterObjectSchemaStmt *) parsetree)->objectType)
-			{
-				case OBJECT_AGGREGATE:
-					evt->command = E_AlterAggregate;
-					break;
-				case OBJECT_CAST:
-					evt->command = E_AlterCast;
-					break;
-				case OBJECT_COLLATION:
-					evt->command = E_AlterCollation;
-					break;
-				case OBJECT_CONVERSION:
-					evt->command = E_AlterConversion;
-					break;
-				case OBJECT_DOMAIN:
-					evt->command = E_AlterDomain;
-					break;
-				case OBJECT_EXTENSION:
-					evt->command = E_AlterExtension;
-					break;
-				case OBJECT_FDW:
-					evt->command = E_AlterForeignDataWrapper;
-					break;
-				case OBJECT_FOREIGN_SERVER:
-					evt->command = E_AlterServer;
-					break;
-				case OBJECT_FOREIGN_TABLE:
-					evt->command = E_AlterForeignTable;
-					break;
-				case OBJECT_FUNCTION:
-					evt->command = E_AlterFunction;
-					break;
-				case OBJECT_INDEX:
-					evt->command = E_AlterIndex;
-					break;
-				case OBJECT_LANGUAGE:
-					evt->command = E_AlterLanguage;
-					break;
-				case OBJECT_OPCLASS:
-					evt->command = E_AlterOperatorClass;
-					break;
-				case OBJECT_OPERATOR:
-					evt->command = E_AlterOperator;
-					break;
-				case OBJECT_OPFAMILY:
-					evt->command = E_AlterOperatorFamily;
-					break;
-				case OBJECT_SCHEMA:
-					evt->command = E_AlterSchema;
-					break;
-				case OBJECT_SEQUENCE:
-					evt->command = E_AlterSequence;
-					break;
-				case OBJECT_TABLE:
-					evt->command = E_AlterTable;
-					break;
-				case OBJECT_TRIGGER:
-					evt->command = E_AlterTrigger;
-					break;
-				case OBJECT_TSCONFIGURATION:
-					evt->command = E_AlterTextSearchConfiguration;
-					break;
-				case OBJECT_TSDICTIONARY:
-					evt->command = E_AlterTextSearchDictionary;
-					break;
-				case OBJECT_TSPARSER:
-					evt->command = E_AlterTextSearchParser;
-					break;
-				case OBJECT_TSTEMPLATE:
-					evt->command = E_AlterTextSearchTemplate;
-					break;
-				case OBJECT_TYPE:
-					evt->command = E_AlterType;
-					break;
-				case OBJECT_VIEW:
-					evt->command = E_AlterView;
-					break;
-				case OBJECT_ROLE:
-				case OBJECT_EVENT_TRIGGER:
-				case OBJECT_ATTRIBUTE:
-				case OBJECT_COLUMN:
-				case OBJECT_CONSTRAINT:
-				case OBJECT_DATABASE:
-				case OBJECT_LARGEOBJECT:
-				case OBJECT_RULE:
-				case OBJECT_TABLESPACE:
-					/* no support for specific command triggers */
-					break;
-			}
-			break;
-
-		case T_AlterOwnerStmt:
-			switch (((AlterOwnerStmt *) parsetree)->objectType)
-			{
-				case OBJECT_AGGREGATE:
-					evt->command = E_AlterAggregate;
-					break;
-				case OBJECT_CAST:
-					evt->command = E_AlterCast;
-					break;
-				case OBJECT_COLLATION:
-					evt->command = E_AlterCollation;
-					break;
-				case OBJECT_CONVERSION:
-					evt->command = E_AlterConversion;
-					break;
-				case OBJECT_DOMAIN:
-					evt->command = E_AlterDomain;
-					break;
-				case OBJECT_EXTENSION:
-					evt->command = E_AlterExtension;
-					break;
-				case OBJECT_FDW:
-					evt->command = E_AlterForeignDataWrapper;
-					break;
-				case OBJECT_FOREIGN_SERVER:
-					evt->command = E_AlterServer;
-					break;
-				case OBJECT_FOREIGN_TABLE:
-					evt->command = E_AlterForeignTable;
-					break;
-				case OBJECT_FUNCTION:
-					evt->command = E_AlterFunction;
-					break;
-				case OBJECT_INDEX:
-					evt->command = E_AlterIndex;
-					break;
-				case OBJECT_LANGUAGE:
-					evt->command = E_AlterLanguage;
-					break;
-				case OBJECT_OPCLASS:
-					evt->command = E_AlterOperatorClass;
-					break;
-				case OBJECT_OPERATOR:
-					evt->command = E_AlterOperator;
-					break;
-				case OBJECT_OPFAMILY:
-					evt->command = E_AlterOperatorFamily;
-					break;
-				case OBJECT_SCHEMA:
-					evt->command = E_AlterSchema;
-					break;
-				case OBJECT_SEQUENCE:
-					evt->command = E_AlterSequence;
-					break;
-				case OBJECT_TABLE:
-					evt->command = E_AlterTable;
-					break;
-				case OBJECT_TRIGGER:
-					evt->command = E_AlterTrigger;
-					break;
-				case OBJECT_TSCONFIGURATION:
-					evt->command = E_AlterTextSearchConfiguration;
-					break;
-				case OBJECT_TSDICTIONARY:
-					evt->command = E_AlterTextSearchDictionary;
-					break;
-				case OBJECT_TSPARSER:
-					evt->command = E_AlterTextSearchParser;
-					break;
-				case OBJECT_TSTEMPLATE:
-					evt->command = E_AlterTextSearchTemplate;
-					break;
-				case OBJECT_TYPE:
-					evt->command = E_AlterType;
-					break;
-				case OBJECT_VIEW:
-					evt->command = E_AlterView;
-					break;
-				case OBJECT_ROLE:
-				case OBJECT_EVENT_TRIGGER:
-				case OBJECT_ATTRIBUTE:
-				case OBJECT_COLUMN:
-				case OBJECT_CONSTRAINT:
-				case OBJECT_DATABASE:
-				case OBJECT_LARGEOBJECT:
-				case OBJECT_RULE:
-				case OBJECT_TABLESPACE:
-					/* no support for specific command triggers */
-					break;
-			}
-			break;
-
-		case T_AlterTableStmt:
-			evt->command = E_AlterTable;
-			break;
-
-		case T_AlterDomainStmt:
-			evt->command = E_AlterDomain;
-			break;
-
-		case T_DefineStmt:
-			switch (((DefineStmt *) parsetree)->kind)
-			{
-				case OBJECT_AGGREGATE:
-					evt->command = E_CreateAggregate;
-					break;
-				case OBJECT_OPERATOR:
-					evt->command = E_CreateOperator;
-					break;
-				case OBJECT_TYPE:
-					evt->command = E_CreateType;
-					break;
-				case OBJECT_TSPARSER:
-					evt->command = E_CreateTextSearchParser;
-					break;
-				case OBJECT_TSDICTIONARY:
-					evt->command = E_CreateTextSearchDictionary;;
-					break;
-				case OBJECT_TSTEMPLATE:
-					evt->command = E_CreateTextSearchTemplate;
-					break;
-				case OBJECT_TSCONFIGURATION:
-					evt->command = E_CreateTextSearchConfiguration;
-					break;
-				case OBJECT_COLLATION:
-					evt->command = E_CreateCollation;
-					break;
-				default:
-					elog(ERROR, "unrecognized define stmt type: %d",
-						 (int) ((DefineStmt *) parsetree)->kind);
-					break;
-			}
-			break;
-
-		case T_CompositeTypeStmt:		/* CREATE TYPE (composite) */
-		case T_CreateEnumStmt:	/* CREATE TYPE AS ENUM */
-		case T_CreateRangeStmt:	/* CREATE TYPE AS RANGE */
-			evt->command = E_CreateType;
-			break;
-
-		case T_AlterEnumStmt:	/* ALTER TYPE (enum) */
-			evt->command = E_AlterType;
-			break;
-
-		case T_ViewStmt:		/* CREATE VIEW */
-			evt->command = E_CreateView;
-			break;
-
-		case T_CreateFunctionStmt:		/* CREATE FUNCTION */
-			evt->command = E_CreateFunction;
-			break;
-
-		case T_AlterFunctionStmt:		/* ALTER FUNCTION */
-			evt->command = E_AlterFunction;
-			break;
-
-		case T_IndexStmt:		/* CREATE INDEX */
-			evt->command = E_CreateIndex;
-			break;
-
-		case T_CreateSeqStmt:
-			evt->command = E_CreateSequence;
-			break;
-
-		case T_AlterSeqStmt:
-			evt->command = E_AlterSequence;
-			break;
-
-		case T_LoadStmt:
-			evt->command = E_Load;
-			break;
-
-		case T_ClusterStmt:
-			evt->command = E_Cluster;
-			break;
-
-		case T_VacuumStmt:
-			evt->command = E_Vacuum;
-			break;
-
-		case T_CreateTableAsStmt:
-			evt->command = E_CreateTableAs;
-			break;
-
-		case T_CreateTrigStmt:
-			evt->command = E_CreateTrigger;
-			break;
-
-		case T_CreateDomainStmt:
-			evt->command = E_CreateDomain;
-			break;
-
-		case T_ReindexStmt:
-			evt->command = E_Reindex;
-			break;
-
-		case T_CreateConversionStmt:
-			evt->command = E_CreateConversion;
-			break;
-
-		case T_CreateCastStmt:
-			evt->command = E_CreateCast;
-			break;
-
-		case T_CreateOpClassStmt:
-			evt->command = E_CreateOperatorClass;
-			break;
-
-		case T_CreateOpFamilyStmt:
-			evt->command = E_CreateOperatorFamily;
-			break;
-
-		case T_AlterOpFamilyStmt:
-			evt->command = E_AlterOperatorFamily;
-			break;
-
-		case T_AlterTSDictionaryStmt:
-			evt->command = E_AlterTextSearchDictionary;
-			break;
-
-		case T_AlterTSConfigurationStmt:
-			evt->command = E_AlterTextSearchConfiguration;
-			break;
-
-		default:
-			/* reaching that part of the code only means that we are not
-			 * supporting command triggers for the given command, which still
-			 * needs to execute.
-			 */
-			break;
-	}
+	/* guess the ongoing operation from the command tag */
+	if (strncmp(evt->tag, "CREATE ", 7) == 0)
+		evt->operation = pstrdup("CREATE");
+	else if (strncmp(evt->tag, "DROP ", 5) == 0)
+		evt->operation = pstrdup("DROP");
+	else if (strncmp(evt->tag, "ALTER ", 6) == 0)
+		evt->operation = pstrdup("ALTER");
 }
 
 /*
- * InitEventContext() must have been called first. When
- * CommandFiresTriggersForEvent() returns false, the EventContext structure
- * needs not be initialized further.
+ * InitEventContext() must have been called first, then the event context field
+ * 'objectype' must have been "manually" for command tags supporting several
+ * kinds of object, such as T_DropStmt, T_RenameStmt, T_AlterObjectSchemaStmt,
+ * T_AlterOwnerStmt or T_DefineStmt.
+ *
+ * When CommandFiresTriggersForEvent() returns false, the EventContext
+ * structure needs not be initialized further.
  */
 bool
 CommandFiresTriggersForEvent(EventContext ev_ctx, TrigEvent tev)
 {
 	EventCommandTriggers *triggers;
 
-	if (ev_ctx == NULL || ev_ctx->command == E_UNKNOWN)
+	if (ev_ctx == NULL)
+		return false;
+
+	if (ev_ctx->command == ETC_UNSET)
+		ev_ctx->command = get_command_from_nodetag(nodeTag(ev_ctx->parsetree),
+												   ev_ctx->objecttype, true);
+
+	if (ev_ctx->command == ETC_UNKNOWN)
 		return false;
 
 	triggers = get_event_triggers(tev, ev_ctx->command);
@@ -1037,7 +507,7 @@ CommandFiresTriggersForEvent(EventContext ev_ctx, TrigEvent tev)
 }
 
 /*
- * Actually run command triggers of a specific command. We first run ANY
+ * Actually run event triggers for a specific command. We first run ANY
  * command triggers.
  */
 void
@@ -1046,7 +516,14 @@ ExecEventTriggers(EventContext ev_ctx, TrigEvent tev)
 	EventCommandTriggers *triggers;
 	ListCell *lc;
 
-	if (ev_ctx == NULL || ev_ctx->command == E_UNKNOWN)
+	if (ev_ctx == NULL)
+		return;
+
+	if (ev_ctx->command == ETC_UNSET)
+		ev_ctx->command = get_command_from_nodetag(nodeTag(ev_ctx->parsetree),
+												   ev_ctx->objecttype, true);
+
+	if (ev_ctx->command == ETC_UNKNOWN)
 		return;
 
 	triggers = get_event_triggers(tev, ev_ctx->command);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index ec5c8f8..f3ab8e9 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -214,7 +214,7 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
 		CreateUserStmt CreateUserMappingStmt CreateRoleStmt
 		CreatedbStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt DoStmt
 		DropGroupStmt DropOpClassStmt DropOpFamilyStmt DropPLangStmt DropStmt
-		DropAssertStmt DropTrigStmt DropEventTrigStmt DropRuleStmt DropCastStmt
+		DropAssertStmt DropTrigStmt DropRuleStmt DropCastStmt
 		DropRoleStmt DropUserStmt DropdbStmt DropTableSpaceStmt DropFdwStmt
 		DropForeignServerStmt DropUserMappingStmt ExplainStmt FetchStmt
 		GrantStmt GrantRoleStmt IndexStmt InsertStmt ListenStmt LoadStmt
@@ -755,7 +755,6 @@ stmt :
 			| DropStmt
 			| DropTableSpaceStmt
 			| DropTrigStmt
-			| DropEventTrigStmt
 			| DropRoleStmt
 			| DropUserStmt
 			| DropUserMappingStmt
@@ -4368,7 +4367,7 @@ trigger_command:
 			SCONST
 				{
 					TrigEventCommand cmdtag = parse_event_tag($1, true);
-					if (cmdtag == E_UNKNOWN)
+					if (cmdtag == ETC_UNKNOWN)
 						ereport(ERROR,
 								(errcode(ERRCODE_SYNTAX_ERROR),
 								 errmsg("unrecognized command \"%s\"", $1),
@@ -4378,27 +4377,6 @@ trigger_command:
 		;
 
 
-DropEventTrigStmt:
-			DROP EVENT TRIGGER name opt_drop_behavior
-				{
-					DropStmt *n = makeNode(DropStmt);
-					n->removeType = OBJECT_EVENT_TRIGGER;
-					n->objects = list_make1(list_make1(makeString($4)));
-					n->behavior = $5;
-					n->missing_ok = false;
-					$$ = (Node *) n;
-				}
-			| DROP EVENT TRIGGER IF_P EXISTS name opt_drop_behavior
-				{
-					DropStmt *n = makeNode(DropStmt);
-					n->removeType = OBJECT_EVENT_TRIGGER;
-					n->objects = list_make1(list_make1(makeString($6)));
-					n->behavior = $7;
-					n->missing_ok = true;
-					$$ = (Node *) n;
-				}
-		;
-
 AlterEventTrigStmt:
 			ALTER EVENT TRIGGER name enable_trigger
 				{
@@ -5002,6 +4980,7 @@ drop_type:	TABLE									{ $$ = OBJECT_TABLE; }
 			| VIEW									{ $$ = OBJECT_VIEW; }
 			| INDEX									{ $$ = OBJECT_INDEX; }
 			| FOREIGN TABLE							{ $$ = OBJECT_FOREIGN_TABLE; }
+			| EVENT TRIGGER 						{ $$ = OBJECT_EVENT_TRIGGER; }
 			| TYPE_P								{ $$ = OBJECT_TYPE; }
 			| DOMAIN_P								{ $$ = OBJECT_DOMAIN; }
 			| COLLATION								{ $$ = OBJECT_COLLATION; }
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 29eec11..4e1a8c0 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -63,6 +63,7 @@
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
 
+
 /* Hook for plugins to get control in ProcessUtility() */
 ProcessUtility_hook_type ProcessUtility_hook = NULL;
 
@@ -355,12 +356,7 @@ standard_ProcessUtility(Node *parsetree,
 		completionTag[0] = '\0';
 
 	/* Event Trigger support for command_start */
-	InitEventContext(&evt, (Node *)parsetree);
-
-	if (CommandFiresTriggersForEvent(&evt, E_CommandStart))
-	{
-		ExecEventTriggers(&evt, E_CommandStart);
-	}
+	InitEventContext(&evt, parsetree);
 
 	switch (nodeTag(parsetree))
 	{
@@ -513,6 +509,7 @@ standard_ProcessUtility(Node *parsetree,
 			 * relation and attribute manipulation
 			 */
 		case T_CreateSchemaStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			CreateSchemaCommand((CreateSchemaStmt *) parsetree,
 								queryString);
 			break;
@@ -525,6 +522,9 @@ standard_ProcessUtility(Node *parsetree,
 				Oid			relOid = InvalidOid;
 				CreateStmt *stmt = (CreateStmt *) parsetree;
 
+				/* possibly run event triggers */
+				ExecEventTriggers(&evt, EVT_CommandStart);
+
 				/* Run parse analysis ... */
 				stmts = transformCreateStmt(stmt, queryString);
 
@@ -589,59 +589,75 @@ standard_ProcessUtility(Node *parsetree,
 
 		case T_CreateTableSpaceStmt:
 			PreventTransactionChain(isTopLevel, "CREATE TABLESPACE");
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			CreateTableSpace((CreateTableSpaceStmt *) parsetree);
 			break;
 
 		case T_DropTableSpaceStmt:
 			PreventTransactionChain(isTopLevel, "DROP TABLESPACE");
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			DropTableSpace((DropTableSpaceStmt *) parsetree);
 			break;
 
 		case T_AlterTableSpaceOptionsStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			AlterTableSpaceOptions((AlterTableSpaceOptionsStmt *) parsetree);
 			break;
 
 		case T_CreateExtensionStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			CreateExtension((CreateExtensionStmt *) parsetree);
 			break;
 
 		case T_AlterExtensionStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			ExecAlterExtensionStmt((AlterExtensionStmt *) parsetree);
 			break;
 
 		case T_AlterExtensionContentsStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			ExecAlterExtensionContentsStmt((AlterExtensionContentsStmt *) parsetree);
 			break;
 
 		case T_CreateFdwStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
 			break;
 
 		case T_AlterFdwStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
 			break;
 
 		case T_CreateForeignServerStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			CreateForeignServer((CreateForeignServerStmt *) parsetree);
 			break;
 
 		case T_AlterForeignServerStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			AlterForeignServer((AlterForeignServerStmt *) parsetree);
 			break;
 
 		case T_CreateUserMappingStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			CreateUserMapping((CreateUserMappingStmt *) parsetree);
 			break;
 
 		case T_AlterUserMappingStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			AlterUserMapping((AlterUserMappingStmt *) parsetree);
 			break;
 
 		case T_DropUserMappingStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			RemoveUserMapping((DropUserMappingStmt *) parsetree);
 			break;
 
 		case T_DropStmt:
+			evt.objecttype = ((DropStmt *) parsetree)->removeType;
+			ExecEventTriggers(&evt, EVT_CommandStart);
+
 			switch (((DropStmt *) parsetree)->removeType)
 			{
 				case OBJECT_INDEX:
@@ -705,14 +721,20 @@ standard_ProcessUtility(Node *parsetree,
 			 * schema
 			 */
 		case T_RenameStmt:
+			evt.objecttype = ((RenameStmt *) parsetree)->renameType;
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			ExecRenameStmt((RenameStmt *) parsetree);
 			break;
 
 		case T_AlterObjectSchemaStmt:
+			evt.objecttype = ((AlterObjectSchemaStmt *) parsetree)->objectType;
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree);
 			break;
 
 		case T_AlterOwnerStmt:
+			evt.objecttype = ((AlterOwnerStmt *) parsetree)->objectType;
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
 			break;
 
@@ -724,6 +746,9 @@ standard_ProcessUtility(Node *parsetree,
 				ListCell   *l;
 				LOCKMODE	lockmode;
 
+				/* run command_start event triggers, if any */
+				ExecEventTriggers(&evt, EVT_CommandStart);
+
 				/*
 				 * Figure out lock mode, and acquire lock.	This also does
 				 * basic permissions checks, so that we won't wait for a lock
@@ -775,6 +800,9 @@ standard_ProcessUtility(Node *parsetree,
 			{
 				AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree;
 
+				/* run command_start event triggers, if any */
+				ExecEventTriggers(&evt, EVT_CommandStart);
+
 				/*
 				 * Some or all of these functions are recursive to cover
 				 * inherited things, so permission checks are done there.
@@ -839,6 +867,9 @@ standard_ProcessUtility(Node *parsetree,
 			{
 				DefineStmt *stmt = (DefineStmt *) parsetree;
 
+				evt.objecttype = stmt->kind;
+				ExecEventTriggers(&evt, EVT_CommandStart);
+
 				switch (stmt->kind)
 				{
 					case OBJECT_AGGREGATE:
@@ -885,15 +916,18 @@ standard_ProcessUtility(Node *parsetree,
 			{
 				CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
 
+				ExecEventTriggers(&evt, EVT_CommandStart);
 				DefineCompositeType(stmt->typevar, stmt->coldeflist);
 			}
 			break;
 
 		case T_CreateEnumStmt:	/* CREATE TYPE AS ENUM */
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			DefineEnum((CreateEnumStmt *) parsetree);
 			break;
 
 		case T_CreateRangeStmt:	/* CREATE TYPE AS RANGE */
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			DefineRange((CreateRangeStmt *) parsetree);
 			break;
 
@@ -905,18 +939,22 @@ standard_ProcessUtility(Node *parsetree,
 			 * defining pg_enum entries go away.
 			 */
 			PreventTransactionChain(isTopLevel, "ALTER TYPE ... ADD");
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			AlterEnum((AlterEnumStmt *) parsetree);
 			break;
 
 		case T_ViewStmt:		/* CREATE VIEW */
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			DefineView((ViewStmt *) parsetree, queryString);
 			break;
 
 		case T_CreateFunctionStmt:		/* CREATE FUNCTION */
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			CreateFunction((CreateFunctionStmt *) parsetree, queryString);
 			break;
 
 		case T_AlterFunctionStmt:		/* ALTER FUNCTION */
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			AlterFunction((AlterFunctionStmt *) parsetree);
 			break;
 
@@ -924,6 +962,8 @@ standard_ProcessUtility(Node *parsetree,
 			{
 				IndexStmt  *stmt = (IndexStmt *) parsetree;
 
+				ExecEventTriggers(&evt, EVT_CommandStart);
+
 				if (stmt->concurrent)
 					PreventTransactionChain(isTopLevel,
 											"CREATE INDEX CONCURRENTLY");
@@ -958,14 +998,17 @@ standard_ProcessUtility(Node *parsetree,
 			break;
 
 		case T_RuleStmt:		/* CREATE RULE */
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			DefineRule((RuleStmt *) parsetree, queryString);
 			break;
 
 		case T_CreateSeqStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			DefineSequence((CreateSeqStmt *) parsetree);
 			break;
 
 		case T_AlterSeqStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			AlterSequence((AlterSeqStmt *) parsetree);
 			break;
 
@@ -1032,6 +1075,8 @@ standard_ProcessUtility(Node *parsetree,
 			{
 				LoadStmt   *stmt = (LoadStmt *) parsetree;
 
+				ExecEventTriggers(&evt, EVT_CommandStart);
+
 				closeAllVfds(); /* probably not necessary... */
 				/* Allowed names are restricted if you're not superuser */
 				load_file(stmt->filename, !superuser());
@@ -1040,12 +1085,14 @@ standard_ProcessUtility(Node *parsetree,
 
 		case T_ClusterStmt:
 			/* we choose to allow this during "read only" transactions */
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			PreventCommandDuringRecovery("CLUSTER");
 			cluster((ClusterStmt *) parsetree, isTopLevel);
 			break;
 
 		case T_VacuumStmt:
 			/* we choose to allow this during "read only" transactions */
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			PreventCommandDuringRecovery("VACUUM");
 			vacuum((VacuumStmt *) parsetree, InvalidOid, true, NULL, false,
 				   isTopLevel);
@@ -1056,6 +1103,7 @@ standard_ProcessUtility(Node *parsetree,
 			break;
 
 		case T_CreateTableAsStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			ExecCreateTableAs((CreateTableAsStmt *) parsetree,
 							  queryString, params, completionTag);
 			break;
@@ -1079,6 +1127,7 @@ standard_ProcessUtility(Node *parsetree,
 			break;
 
 		case T_CreateTrigStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			(void) CreateTrigger((CreateTrigStmt *) parsetree, queryString,
 								 InvalidOid, InvalidOid, false);
 			break;
@@ -1092,6 +1141,7 @@ standard_ProcessUtility(Node *parsetree,
 			break;
 
 		case T_CreatePLangStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			CreateProceduralLanguage((CreatePLangStmt *) parsetree);
 			break;
 
@@ -1099,6 +1149,7 @@ standard_ProcessUtility(Node *parsetree,
 			 * ******************************** DOMAIN statements ****
 			 */
 		case T_CreateDomainStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			DefineDomain((CreateDomainStmt *) parsetree);
 			break;
 
@@ -1164,6 +1215,8 @@ standard_ProcessUtility(Node *parsetree,
 			{
 				ReindexStmt *stmt = (ReindexStmt *) parsetree;
 
+				ExecEventTriggers(&evt, EVT_CommandStart);
+
 				/* we choose to allow this during "read only" transactions */
 				PreventCommandDuringRecovery("REINDEX");
 				switch (stmt->kind)
@@ -1197,30 +1250,37 @@ standard_ProcessUtility(Node *parsetree,
 			break;
 
 		case T_CreateConversionStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			CreateConversionCommand((CreateConversionStmt *) parsetree);
 			break;
 
 		case T_CreateCastStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			CreateCast((CreateCastStmt *) parsetree);
 			break;
 
 		case T_CreateOpClassStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			DefineOpClass((CreateOpClassStmt *) parsetree);
 			break;
 
 		case T_CreateOpFamilyStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			DefineOpFamily((CreateOpFamilyStmt *) parsetree);
 			break;
 
 		case T_AlterOpFamilyStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			AlterOpFamily((AlterOpFamilyStmt *) parsetree);
 			break;
 
 		case T_AlterTSDictionaryStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			AlterTSDictionary((AlterTSDictionaryStmt *) parsetree);
 			break;
 
 		case T_AlterTSConfigurationStmt:
+			ExecEventTriggers(&evt, EVT_CommandStart);
 			AlterTSConfiguration((AlterTSConfigurationStmt *) parsetree);
 			break;
 
diff --git a/src/backend/utils/adt/pseudotypes.c b/src/backend/utils/adt/pseudotypes.c
index d7770b8..8590f3c 100644
--- a/src/backend/utils/adt/pseudotypes.c
+++ b/src/backend/utils/adt/pseudotypes.c
@@ -293,6 +293,33 @@ trigger_out(PG_FUNCTION_ARGS)
 
 
 /*
+ * event_trigger_in	- input routine for pseudo-type event_trigger.
+ */
+Datum
+event_trigger_in(PG_FUNCTION_ARGS)
+{
+	ereport(ERROR,
+			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			 errmsg("cannot accept a value of type event_trigger")));
+
+	PG_RETURN_VOID();			/* keep compiler quiet */
+}
+
+/*
+ * event_trigger_out - output routine for pseudo-type event_trigger.
+ */
+Datum
+event_trigger_out(PG_FUNCTION_ARGS)
+{
+	ereport(ERROR,
+			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			 errmsg("cannot display a value of type event_trigger")));
+
+	PG_RETURN_VOID();			/* keep compiler quiet */
+}
+
+
+/*
  * language_handler_in		- input routine for pseudo-type LANGUAGE_HANDLER.
  */
 Datum
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 17b62b6..ec93149 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -39,11 +39,9 @@
 #include "nodes/nodeFuncs.h"
 #include "optimizer/clauses.h"
 #include "optimizer/tlist.h"
-#include "parser/analyze.h"
 #include "parser/keywords.h"
 #include "parser/parse_func.h"
 #include "parser/parse_oper.h"
-#include "parser/parse_type.h"
 #include "parser/parser.h"
 #include "parser/parsetree.h"
 #include "rewrite/rewriteHandler.h"
@@ -261,6 +259,7 @@ static char *flatten_reloptions(Oid relid);
 
 #define only_marker(rte)  ((rte)->inh ? "" : "ONLY ")
 
+
 /* ----------
  * get_ruledef			- Do it all and return a text
  *				  that could be used as a statement
diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c
index 65bc6be..bced1e0 100644
--- a/src/backend/utils/cache/evtcache.c
+++ b/src/backend/utils/cache/evtcache.c
@@ -18,6 +18,7 @@
 
 #include "access/heapam.h"
 #include "catalog/catalog.h"
+#include "catalog/pg_collation.h"
 #include "catalog/dependency.h"
 #include "catalog/heap.h"
 #include "catalog/index.h"
@@ -28,9 +29,11 @@
 #include "catalog/pg_type.h"
 #include "commands/event_trigger.h"
 #include "commands/trigger.h"
+#include "nodes/parsenodes.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/evtcache.h"
+#include "utils/formatting.h"
 #include "utils/hsearch.h"
 #include "utils/inval.h"
 #include "utils/memutils.h"
@@ -39,6 +42,962 @@
 #include "utils/syscache.h"
 
 /*
+ * EventTriggerCommandTags
+ *
+ * This array provides meta data allowing to parse and rewrite command tags
+ * from the command and catalogs to the internal integers we use to have fast
+ * lookups.
+ *
+ * Lookups have to be fast because they are done for each and every DDL as soon
+ * as some Event Triggers are defined.
+ */
+typedef struct
+{
+	TrigEventCommand	 command; /* internal command value */
+	char			 	*tag;	  /* command tag */
+	NodeTag				 node;	  /* internal parser node tag */
+	ObjectType			 type;	  /* internal object type */
+} EventTriggerCommandTagsType;
+
+/*
+ * Hash table to cache the content of EventTriggerCommandTags, which is
+ * searched by command tag when building the EventTriggerProcsCache, and by
+ * NodeTag and ObjectType from ProcessUtility.
+ *
+ * In both cases we want to avoid to have to scan the whole array each time, so
+ * we cache a dedicated hash table in the session's memory.
+ */
+static HTAB *EventTriggerCommandTagsCache = NULL;
+static HTAB *EventTriggerCommandNodeCache = NULL;
+
+/* entry for the Tags cache (key is NameData of NAMEDATALEN) */
+typedef struct
+{
+	NameData			tag;
+	TrigEventCommand	command;
+} EventTriggerCommandTagsEntry;
+
+/* key and entry for the Node cache */
+typedef struct
+{
+	NodeTag				 node;	  /* internal parser node tag */
+	ObjectType			 type;	  /* internal object type */
+} EventTriggerCommandNodeKey;
+
+typedef struct
+{
+	EventTriggerCommandNodeKey key; /* lookup key, must be first */
+	TrigEventCommand	 command;	/* internal command value */
+} EventTriggerCommandNodeEntry;
+
+static EventTriggerCommandTagsType EventTriggerCommandTags[] =
+{
+	{
+		ETC_CreateAggregate,
+		"CREATE AGGREGATE",
+		T_DefineStmt,
+		OBJECT_AGGREGATE
+	},
+	{
+		ETC_CreateCast,
+		"CREATE CAST",
+		T_CreateCastStmt,
+		-1
+	},
+	{
+		ETC_CreateCollation,
+		"CREATE COLLATION",
+		T_DefineStmt,
+		OBJECT_COLLATION
+	},
+	{
+		ETC_CreateConversion,
+		"CREATE CONVERSION",
+		T_CreateConversionStmt,
+		-1
+	},
+	{
+		ETC_CreateDomain,
+		"CREATE DOMAIN",
+		T_CreateDomainStmt,
+		-1
+	},
+	{
+		ETC_CreateExtension,
+		"CREATE EXTENSION",
+		T_CreateExtensionStmt,
+		-1
+	},
+	{
+		ETC_CreateForeignDataWrapper,
+		"CREATE FOREIGN DATA WRAPPER",
+		T_CreateFdwStmt,
+		-1
+	},
+	{
+		ETC_CreateForeignTable,
+		"CREATE FOREIGN TABLE",
+		T_CreateForeignTableStmt,
+		-1
+	},
+	{
+		ETC_CreateFunction,
+		"CREATE FUNCTION",
+		T_CreateFunctionStmt,
+		-1
+	},
+	{
+		ETC_CreateIndex,
+		"CREATE INDEX",
+		T_IndexStmt,
+		-1
+	},
+	{
+		ETC_CreateLanguage,
+		"CREATE LANGUAGE",
+		T_CreatePLangStmt,
+		-1
+	},
+	{
+		ETC_CreateOperator,
+		"CREATE OPERATOR",
+		T_DefineStmt,
+		OBJECT_OPERATOR
+	},
+	{
+		ETC_CreateOperatorClass,
+		"CREATE OPERATOR CLASS",
+		T_CreateOpClassStmt,
+		-1
+	},
+	{
+		ETC_CreateOperatorFamily,
+		"CREATE OPERATOR FAMILY",
+		T_CreateOpFamilyStmt,
+		-1
+	},
+	{
+		ETC_CreateRule,
+		"CREATE RULE",
+		T_RuleStmt,
+		-1
+	},
+	{
+		ETC_CreateSchema,
+		"CREATE SCHEMA",
+		T_CreateSchemaStmt,
+		-1
+	},
+	{
+		ETC_CreateSequence,
+		"CREATE SEQUENCE",
+		T_CreateSeqStmt,
+		-1
+	},
+	{
+		ETC_CreateServer,
+		"CREATE SERVER",
+		T_CreateForeignServerStmt,
+		-1
+	},
+	{
+		ETC_CreateTable,
+		"CREATE TABLE",
+		T_CreateStmt,
+		-1
+	},
+	{
+		ETC_CreateTableAs,
+		"CREATE TABLE AS",
+		T_CreateTableAsStmt,
+		-1
+	},
+	{
+		ETC_SelectInto,
+		"SELECT INTO",
+		T_CreateTableAsStmt,
+		-1
+	},
+	{
+		ETC_CreateTextSearchParser,
+		"CREATE TEXT SEARCH PARSER",
+		T_DefineStmt,
+		OBJECT_TSPARSER
+	},
+	{
+		ETC_CreateTextSearchConfiguration,
+		"CREATE TEXT SEARCH CONFIGURATION",
+		T_DefineStmt,
+		OBJECT_TSCONFIGURATION
+	},
+	{
+		ETC_CreateTextSearchDictionary,
+		"CREATE TEXT SEARCH DICTIONARY",
+		T_DefineStmt,
+		OBJECT_TSDICTIONARY
+	},
+	{
+		ETC_CreateTextSearchTemplate,
+		"CREATE TEXT SEARCH TEMPLATE",
+		T_DefineStmt,
+		OBJECT_TSTEMPLATE
+	},
+	{
+		ETC_CreateTrigger,
+		"CREATE TRIGGER",
+		T_CreateTrigStmt,
+		-1
+	},
+	{
+		ETC_CreateType,
+		"CREATE TYPE",
+		T_DefineStmt,
+		OBJECT_TYPE
+	},
+	{
+		ETC_CreateType,
+		"CREATE TYPE",
+		T_CompositeTypeStmt,
+		-1
+	},
+	{
+		ETC_CreateType,
+		"CREATE TYPE",
+		T_CreateEnumStmt,
+		-1
+	},
+	{
+		ETC_CreateType,
+		"CREATE TYPE",
+		T_CreateRangeStmt,
+		-1
+	},
+	{
+		ETC_CreateUserMapping,
+		"CREATE USER MAPPING",
+		T_CreateUserMappingStmt,
+		-1
+	},
+	{
+		ETC_CreateView,
+		"CREATE VIEW",
+		T_ViewStmt,
+		-1
+	},
+	{
+		ETC_AlterTable,
+		"ALTER TABLE",
+		T_AlterTableStmt,
+		-1
+	},
+	{
+		ETC_DropAggregate,
+		"DROP AGGREGATE",
+		T_DropStmt,
+		OBJECT_AGGREGATE
+	},
+	{
+		ETC_DropCast,
+		"DROP CAST",
+		T_DropStmt,
+		OBJECT_CAST
+	},
+	{
+		ETC_DropCollation,
+		"DROP COLLATION",
+		T_DropStmt,
+		OBJECT_COLLATION
+	},
+	{
+		ETC_DropConversion,
+		"DROP CONVERSION",
+		T_DropStmt,
+		OBJECT_CONVERSION
+	},
+	{
+		ETC_DropDomain,
+		"DROP DOMAIN",
+		T_DropStmt,
+		OBJECT_DOMAIN
+	},
+	{
+		ETC_DropExtension,
+		"DROP EXTENSION",
+		T_DropStmt,
+		OBJECT_EXTENSION
+	},
+	{
+		ETC_DropForeignDataWrapper,
+		"DROP FOREIGN DATA WRAPPER",
+		T_DropStmt,
+		OBJECT_FDW
+	},
+	{
+		ETC_DropForeignTable,
+		"DROP FOREIGN TABLE",
+		T_DropStmt,
+		OBJECT_FOREIGN_TABLE
+	},
+	{
+		ETC_DropFunction,
+		"DROP FUNCTION",
+		T_DropStmt,
+		OBJECT_FUNCTION
+	},
+	{
+		ETC_DropIndex,
+		"DROP INDEX",
+		T_DropStmt,
+		OBJECT_INDEX
+	},
+	{
+		ETC_DropLanguage,
+		"DROP LANGUAGE",
+		T_DropStmt,
+		OBJECT_LANGUAGE
+	},
+	{
+		ETC_DropOperator,
+		"DROP OPERATOR",
+		T_DropStmt,
+		OBJECT_OPERATOR
+	},
+	{
+		ETC_DropOperatorClass,
+		"DROP OPERATOR CLASS",
+		T_DropStmt,
+		OBJECT_OPCLASS
+	},
+	{
+		ETC_DropOperatorFamily,
+		"DROP OPERATOR FAMILY",
+		T_DropStmt,
+		OBJECT_OPFAMILY
+	},
+	{
+		ETC_DropRule,
+		"DROP RULE",
+		T_DropStmt,
+		OBJECT_RULE
+	},
+	{
+		ETC_DropSchema,
+		"DROP SCHEMA",
+		T_DropStmt,
+		OBJECT_SCHEMA
+	},
+	{
+		ETC_DropSequence,
+		"DROP SEQUENCE",
+		T_DropStmt,
+		OBJECT_SEQUENCE
+	},
+	{
+		ETC_DropServer,
+		"DROP SERVER",
+		T_DropStmt,
+		OBJECT_FOREIGN_SERVER
+	},
+	{
+		ETC_DropTable,
+		"DROP TABLE",
+		T_DropStmt,
+		OBJECT_TABLE
+	},
+	{
+		ETC_DropTextSearchParser,
+		"DROP TEXT SEARCH PARSER",
+		T_DropStmt,
+		OBJECT_TSPARSER
+	},
+	{
+		ETC_DropTextSearchConfiguration,
+		"DROP TEXT SEARCH CONFIGURATION",
+		T_DropStmt,
+		OBJECT_TSCONFIGURATION
+	},
+	{
+		ETC_DropTextSearchDictionary,
+		"DROP TEXT SEARCH DICTIONARY",
+		T_DropStmt,
+		OBJECT_TSDICTIONARY
+	},
+	{
+		ETC_DropTextSearchTemplate,
+		"DROP TEXT SEARCH TEMPLATE",
+		T_DropStmt,
+		OBJECT_TSTEMPLATE
+	},
+	{
+		ETC_DropTrigger,
+		"DROP TRIGGER",
+		T_DropStmt,
+		OBJECT_TRIGGER
+	},
+	{
+		ETC_DropType,
+		"DROP TYPE",
+		T_DropStmt,
+		OBJECT_TYPE
+	},
+	{
+		ETC_DropUserMapping,
+		"DROP USER MAPPING",
+		T_DropUserMappingStmt,
+		-1
+	},
+	{
+		ETC_DropView,
+		"DROP VIEW",
+		T_DropStmt,
+		OBJECT_VIEW
+	},
+	{
+		ETC_Vacuum,
+		"VACUUM",
+		T_VacuumStmt,
+		-1
+	},
+	{
+		ETC_Cluster,
+		"CLUSTER",
+		T_ClusterStmt,
+		-1
+	},
+	{
+		ETC_Load,
+		"LOAD",
+		T_LoadStmt,
+		-1
+	},
+	{
+		ETC_Reindex,
+		"REINDEX",
+		T_ReindexStmt,
+		-1
+	},
+	{
+		ETC_AlterSequence,
+		"ALTER SEQUENCE",
+		T_AlterSeqStmt,
+		-1
+	},
+	{
+		ETC_AlterUserMapping,
+		"ALTER USER MAPPING",
+		T_CreateUserMappingStmt,
+		-1
+	},
+	{
+		ETC_AlterFunction,
+		"ALTER FUNCTION",
+		T_AlterFunctionStmt,
+		-1
+	},
+	{
+		ETC_AlterDomain,
+		"ALTER DOMAIN",
+		T_AlterDomainStmt,
+		-1
+	},
+	/* ALTER <OBJECT> name RENAME TO */
+	{
+		ETC_AlterAggregate,
+		"ALTER AGGREGATE",
+		T_RenameStmt,
+		OBJECT_AGGREGATE
+	},
+	{
+		ETC_AlterType,
+		"ALTER TYPE",
+		T_RenameStmt,
+		OBJECT_ATTRIBUTE
+	},
+	{
+		ETC_AlterCast,
+		"ALTER CAST",
+		T_RenameStmt,
+		OBJECT_CAST
+	},
+	{
+		ETC_AlterCollation,
+		"ALTER COLLATION",
+		T_RenameStmt,
+		OBJECT_COLLATION
+	},
+	{
+		ETC_AlterTable,
+		"ALTER TABLE",
+		T_RenameStmt,
+		OBJECT_COLUMN
+	},
+	{
+		ETC_AlterTable,
+		"ALTER TABLE",
+		T_RenameStmt,
+		OBJECT_CONSTRAINT
+	},
+	{
+		ETC_AlterConversion,
+		"ALTER CONVERSION",
+		T_RenameStmt,
+		OBJECT_CONVERSION
+	},
+	{
+		ETC_AlterDomain,
+		"ALTER DOMAIN",
+		OBJECT_DOMAIN,
+		T_RenameStmt
+	},
+	{
+		ETC_AlterExtension,
+		"ALTER EXTENSION",
+		T_RenameStmt,
+		OBJECT_EXTENSION
+	},
+	{
+		ETC_AlterForeignDataWrapper,
+		"ALTER FOREIGN DATA WRAPPER",
+		OBJECT_FDW,
+		T_RenameStmt
+	},
+	{
+		ETC_AlterServer,
+		"ALTER SERVER",
+		T_RenameStmt,
+		OBJECT_FOREIGN_SERVER
+	},
+	{
+		ETC_AlterForeignTable,
+		"ALTER FOREIGN TABLE",
+		T_RenameStmt,
+		OBJECT_FOREIGN_TABLE
+	},
+	{
+		ETC_AlterFunction,
+		"ALTER FUNCTION",
+		T_RenameStmt,
+		OBJECT_FUNCTION
+	},
+	{
+		ETC_AlterIndex,
+		"ALTER INDEX",
+		T_RenameStmt,
+		OBJECT_INDEX
+	},
+	{
+		ETC_AlterLanguage,
+		"ALTER LANGUAGE",
+		T_RenameStmt,
+		OBJECT_LANGUAGE
+	},
+	{
+		ETC_AlterOperator,
+		"ALTER OPERATOR",
+		T_RenameStmt,
+		OBJECT_OPERATOR
+	},
+	{
+		ETC_AlterOperatorClass,
+		"ALTER OPERATOR CLASS",
+		T_RenameStmt,
+		OBJECT_OPCLASS
+	},
+	{
+		ETC_AlterOperatorFamily,
+		"ALTER OPERATOR FAMILY",
+		T_RenameStmt,
+		OBJECT_OPFAMILY
+	},
+	{
+		ETC_AlterRule,
+		"ALTER RULE",
+		T_RenameStmt,
+		OBJECT_RULE
+	},
+	{
+		ETC_AlterSchema,
+		"ALTER SCHEMA",
+		T_RenameStmt,
+		OBJECT_SCHEMA
+	},
+	{
+		ETC_AlterSequence,
+		"ALTER SEQUENCE",
+		T_RenameStmt,
+		OBJECT_SEQUENCE
+	},
+	{
+		ETC_AlterTable,
+		"ALTER TABLE",
+		T_RenameStmt,
+		OBJECT_TABLE
+	},
+	{
+		ETC_AlterTrigger,
+		"ALTER TRIGGER",
+		T_RenameStmt,
+		OBJECT_TRIGGER
+	},
+	{
+		ETC_AlterTextSearchParser,
+		"ALTER TEXT SEARCH PARSER",
+		T_RenameStmt,
+		OBJECT_TSPARSER
+	},
+	{
+		ETC_AlterTextSearchConfiguration,
+		"ALTER TEXT SEARCH CONFIGURATION",
+		T_RenameStmt,
+		OBJECT_TSCONFIGURATION
+	},
+	{
+		ETC_AlterTextSearchDictionary,
+		"ALTER TEXT SEARCH DICTIONARY",
+		T_RenameStmt,
+		OBJECT_TSDICTIONARY
+	},
+	{
+		ETC_AlterTextSearchTemplate,
+		"ALTER TEXT SEARCH TEMPLATE",
+		T_RenameStmt,
+		OBJECT_TSTEMPLATE
+	},
+	{
+		ETC_AlterType,
+		"ALTER TYPE",
+		T_RenameStmt,
+		OBJECT_TYPE
+	},
+	{
+		ETC_AlterView,
+		"ALTER VIEW",
+		T_RenameStmt,
+		OBJECT_VIEW
+	},
+	/* ALTER <OBJECT> name SET SCHEMA */
+	{
+		ETC_AlterAggregate,
+		"ALTER AGGREGATE",
+		T_AlterObjectSchemaStmt,
+		OBJECT_AGGREGATE
+	},
+	{
+		ETC_AlterCast,
+		"ALTER CAST",
+		T_AlterObjectSchemaStmt,
+		OBJECT_CAST
+	},
+	{
+		ETC_AlterCollation,
+		"ALTER COLLATION",
+		T_AlterObjectSchemaStmt,
+		OBJECT_COLLATION
+	},
+	{
+		ETC_AlterConversion,
+		"ALTER CONVERSION",
+		T_AlterObjectSchemaStmt,
+		OBJECT_CONVERSION
+	},
+	{
+		ETC_AlterDomain,
+		"ALTER DOMAIN",
+		T_AlterObjectSchemaStmt,
+		OBJECT_DOMAIN
+	},
+	{
+		ETC_AlterExtension,
+		"ALTER EXTENSION",
+		T_AlterObjectSchemaStmt,
+		OBJECT_EXTENSION
+	},
+	{
+		ETC_AlterForeignDataWrapper,
+		"ALTER FOREIGN DATA WRAPPER",
+		T_AlterObjectSchemaStmt,
+		OBJECT_FDW
+	},
+	{
+		ETC_AlterForeignTable,
+		"ALTER FOREIGN TABLE",
+		T_AlterObjectSchemaStmt,
+		OBJECT_FOREIGN_TABLE
+	},
+	{
+		ETC_AlterFunction,
+		"ALTER FUNCTION",
+		T_AlterObjectSchemaStmt,
+		OBJECT_FUNCTION
+	},
+	{
+		ETC_AlterIndex,
+		"ALTER CAST",
+		T_AlterObjectSchemaStmt,
+		OBJECT_INDEX
+	},
+	{
+		ETC_AlterLanguage,
+		"ALTER LANGUAGE",
+		T_AlterObjectSchemaStmt,
+		OBJECT_LANGUAGE
+	},
+	{
+		ETC_AlterOperator,
+		"ALTER OPERATOR",
+		T_AlterObjectSchemaStmt,
+		OBJECT_OPERATOR
+	},
+	{
+		ETC_AlterOperatorClass,
+		"ALTER OPERATOR CLASS",
+		T_AlterObjectSchemaStmt,
+		OBJECT_OPCLASS
+	},
+	{
+		ETC_AlterOperatorFamily,
+		"ALTER OPERATOR FAMILY",
+		T_AlterObjectSchemaStmt,
+		OBJECT_OPFAMILY
+	},
+	{
+		ETC_AlterSchema,
+		"ALTER SCHEMA",
+		T_AlterObjectSchemaStmt,
+		OBJECT_SCHEMA
+	},
+	{
+		ETC_AlterSequence,
+		"ALTER SEQUENCE",
+		T_AlterObjectSchemaStmt,
+		OBJECT_SEQUENCE
+	},
+	{
+		ETC_AlterServer,
+		"ALTER SERVER",
+		T_AlterObjectSchemaStmt,
+		OBJECT_FOREIGN_SERVER
+	},
+	{
+		ETC_AlterTable,
+		"ALTER TABLE",
+		T_AlterObjectSchemaStmt,
+		OBJECT_TABLE
+	},
+	{
+		ETC_AlterTextSearchParser,
+		"ALTER TEXT SEARCH PARSER",
+		T_AlterObjectSchemaStmt,
+		OBJECT_TSPARSER
+	},
+	{
+		ETC_AlterTextSearchConfiguration,
+		"ALTER TEXT SEARCH CONFIGURATION",
+		T_AlterObjectSchemaStmt,
+		OBJECT_TSCONFIGURATION
+	},
+	{
+		ETC_AlterTextSearchDictionary,
+		"ALTER TEXT SEARCH DICTIONARY",
+		T_AlterObjectSchemaStmt,
+		OBJECT_TSDICTIONARY
+	},
+	{
+		ETC_AlterTextSearchTemplate,
+		"ALTER TEXT SEARCH TEMPLATE",
+		T_AlterObjectSchemaStmt,
+		OBJECT_TSTEMPLATE
+	},
+	{
+		ETC_AlterTrigger,
+		"ALTER TRIGGER",
+		T_AlterObjectSchemaStmt,
+		OBJECT_TRIGGER
+	},
+	{
+		ETC_AlterType,
+		"ALTER TYPE",
+		T_AlterEnumStmt,
+		-1
+	},
+	{
+		ETC_AlterType,
+		"ALTER TYPE",
+		T_AlterObjectSchemaStmt,
+		OBJECT_ATTRIBUTE
+	},
+	{
+		ETC_AlterType,
+		"ALTER TYPE",
+		T_AlterObjectSchemaStmt,
+		OBJECT_TYPE
+	},
+	{
+		ETC_AlterView,
+		"ALTER VIEW",
+		T_AlterObjectSchemaStmt,
+		OBJECT_VIEW
+	},
+	{
+		ETC_AlterTextSearchDictionary,
+		"ALTER TEXT SEARCH DICTIONARY",
+		T_AlterTSDictionaryStmt,
+		-1
+	},
+	/* ALTER <OBJECT> name OWNER TO */
+	{
+		ETC_AlterAggregate,
+		"ALTER AGGREGATE",
+		T_AlterOwnerStmt,
+		OBJECT_AGGREGATE
+	},
+	{
+		ETC_AlterCast,
+		"ALTER CAST",
+		T_AlterOwnerStmt,
+		OBJECT_CAST
+	},
+	{
+		ETC_AlterCollation,
+		"ALTER COLLATION",
+		T_AlterOwnerStmt,
+		OBJECT_COLLATION
+	},
+	{
+		ETC_AlterConversion,
+		"ALTER CONVERSION",
+		T_AlterOwnerStmt,
+		OBJECT_CONVERSION
+	},
+	{
+		ETC_AlterDomain,
+		"ALTER DOMAIN",
+		T_AlterOwnerStmt,
+		OBJECT_DOMAIN
+	},
+	{
+		ETC_AlterExtension,
+		"ALTER EXTENSION",
+		T_AlterOwnerStmt,
+		OBJECT_EXTENSION
+	},
+	{
+		ETC_AlterForeignDataWrapper,
+		"ALTER FOREIGN DATA WRAPPER",
+		T_AlterOwnerStmt,
+		OBJECT_FDW
+	},
+	{
+		ETC_AlterForeignTable,
+		"ALTER FOREIGN TABLE",
+		T_AlterOwnerStmt,
+		OBJECT_FOREIGN_TABLE
+	},
+	{
+		ETC_AlterFunction,
+		"ALTER FUNCTION",
+		T_AlterOwnerStmt,
+		OBJECT_FUNCTION
+	},
+	{
+		ETC_AlterIndex,
+		"ALTER CAST",
+		T_AlterOwnerStmt,
+		OBJECT_INDEX
+	},
+	{
+		ETC_AlterLanguage,
+		"command_start",
+		T_AlterOwnerStmt,
+		OBJECT_LANGUAGE
+	},
+	{
+		ETC_AlterOperator,
+		"ALTER OPERATOR",
+		T_AlterOwnerStmt,
+		OBJECT_OPERATOR
+	},
+	{
+		ETC_AlterOperatorClass,
+		"ALTER OPERATOR CLASS",
+		T_AlterOwnerStmt,
+		OBJECT_OPCLASS
+	},
+	{
+		ETC_AlterOperatorFamily,
+		"ALTER OPERATOR FAMILY",
+		T_AlterOwnerStmt,
+		OBJECT_OPFAMILY
+	},
+	{
+		ETC_AlterSchema,
+		"ALTER SCHEMA",
+		T_AlterOwnerStmt,
+		OBJECT_SCHEMA
+	},
+	{
+		ETC_AlterSequence,
+		"ALTER SEQUENCE",
+		T_AlterOwnerStmt,
+		OBJECT_SEQUENCE
+	},
+	{
+		ETC_AlterServer,
+		"ALTER SERVER",
+		T_AlterOwnerStmt,
+		OBJECT_FOREIGN_SERVER
+	},
+	{
+		ETC_AlterTextSearchParser,
+		"ALTER TEXT SEARCH PARSER",
+		T_AlterOwnerStmt,
+		OBJECT_TSPARSER
+	},
+	{
+		ETC_AlterTextSearchConfiguration,
+		"ALTER TEXT SEARCH CONFIGURATION",
+		T_AlterOwnerStmt,
+		OBJECT_TSCONFIGURATION
+	},
+	{
+		ETC_AlterTextSearchDictionary,
+		"ALTER TEXT SEARCH DICTIONARY",
+		T_AlterOwnerStmt,
+		OBJECT_TSDICTIONARY
+	},
+	{
+		ETC_AlterTextSearchTemplate,
+		"ALTER TEXT SEARCH TEMPLATE",
+		T_AlterOwnerStmt,
+		OBJECT_TSTEMPLATE
+	},
+	{
+		ETC_AlterTrigger,
+		"ALTER TRIGGER",
+		T_AlterOwnerStmt,
+		OBJECT_TRIGGER
+	},
+	{
+		ETC_AlterType,
+		"ALTER TYPE",
+		T_AlterOwnerStmt,
+		OBJECT_ATTRIBUTE
+	},
+	{
+		ETC_AlterType,
+		"ALTER TYPE",
+		T_AlterOwnerStmt,
+		OBJECT_TYPE
+	},
+	{
+		ETC_AlterView,
+		"ALTER VIEW",
+		T_AlterOwnerStmt,
+		OBJECT_VIEW
+	}
+};
+
+/*
  * Cache the event triggers in a format that's suitable to finding which
  * function to call at "hook" points in the code. The catalogs are not helpful
  * at search time, because we can't both edit a single catalog entry per each
@@ -48,47 +1007,47 @@
  * This cache is indexed by Event id then Event Command id (see
  * pg_event_trigger.h). It's containing a list of function oid.
  */
-static HTAB *EventCommandTriggerCache = NULL;
+static HTAB *EventTriggerProcsCache = NULL;
 
 /* event and command form the lookup key, and must appear first */
 typedef struct
 {
 	TrigEvent			event;
 	TrigEventCommand	command;
-} EventCommandTriggerCacheKey;
+} EventTriggerProcsCacheKey;
 
 
 /* entry for command event trigger lookup hashtable */
 typedef struct
 {
-	EventCommandTriggerCacheKey key; /* lookup key, must be first */
+	EventTriggerProcsCacheKey key; /* lookup key, must be first */
 	List *names;					 /* list of names of the triggers to call */
 	List *procs;					 /* list of triggers to call */
-} EventCommandTriggerCacheEntry;
+} EventTriggerProcsCacheEntry;
 
 /*
- * Add a new function to EventCommandTriggerCache for given command and event,
+ * Add a new function to EventTriggerProcsCache for given command and event,
  * creating a new hash table entry when necessary.
  *
  * Returns the new hash entry value.
  */
-static EventCommandTriggerCacheEntry *
+static EventTriggerProcsCacheEntry *
 add_funcall_to_command_event(TrigEvent event,
 							 TrigEventCommand command,
 							 NameData evtname,
 							 Oid proc)
 {
 	bool found;
-	EventCommandTriggerCacheKey key;
-	EventCommandTriggerCacheEntry *hresult;
+	EventTriggerProcsCacheKey key;
+	EventTriggerProcsCacheEntry *hresult;
 	MemoryContext old = MemoryContextSwitchTo(CacheMemoryContext);
 
 	memset(&key, 0, sizeof(key));
 	key.event = event;
 	key.command = command;
 
-	hresult = (EventCommandTriggerCacheEntry *)
-		hash_search(EventCommandTriggerCache, (void *)&key, HASH_ENTER, &found);
+	hresult = (EventTriggerProcsCacheEntry *)
+		hash_search(EventTriggerProcsCache, (void *)&key, HASH_ENTER, &found);
 
 	if (found)
 	{
@@ -113,10 +1072,10 @@ add_funcall_to_command_event(TrigEvent event,
  * The idea is that the code to fetch the list of functions to process gets as
  * simple as the following:
  *
- *  foreach(cell, EventCommandTriggerCache[TrigEventCommand][TrigEvent])
+ *  foreach(cell, EventTriggerProcsCache[TrigEventCommand][TrigEvent])
  */
 static void
-BuildEventTriggerCache()
+BuildEventTriggerCache(void)
 {
 	HASHCTL		info;
 	Relation	rel, irel;
@@ -125,13 +1084,13 @@ BuildEventTriggerCache()
 
 	/* build the new hash table */
 	MemSet(&info, 0, sizeof(info));
-	info.keysize = sizeof(EventCommandTriggerCacheKey);
-	info.entrysize = sizeof(EventCommandTriggerCacheEntry);
+	info.keysize = sizeof(EventTriggerProcsCacheKey);
+	info.entrysize = sizeof(EventTriggerProcsCacheEntry);
 	info.hash = tag_hash;
 	info.hcxt = CacheMemoryContext;
 
 	/* Create the hash table holding our cache */
-	EventCommandTriggerCache =
+	EventTriggerProcsCache =
 		hash_create("Event Trigger Command Cache",
 					1024,
 					&info,
@@ -144,8 +1103,9 @@ BuildEventTriggerCache()
 	indexScan = index_beginscan(rel, irel, SnapshotNow, 0, 0);
 	index_rescan(indexScan, NULL, 0, NULL, 0);
 
-	/* we use a full indexscan to guarantee that we see event triggers ordered
-	 * by name, this way we only even have to append the trigger's function Oid
+	/*
+	 * We use a full indexscan to guarantee that we see event triggers ordered
+	 * by name. This way, we only even have to append the trigger's function Oid
 	 * to the target cache Oid list.
 	 */
 	while (HeapTupleIsValid(tuple = index_getnext(indexScan, ForwardScanDirection)))
@@ -190,7 +1150,7 @@ BuildEventTriggerCache()
 			/* event triggers created without WHEN clause are targetting all
 			 * commands (ANY command trigger)
 			 */
-			add_funcall_to_command_event(event, E_ANY, name, proc);
+			add_funcall_to_command_event(event, ETC_ANY, name, proc);
 		}
 		else
 		{
@@ -232,8 +1192,8 @@ static void
 InvalidateEvtTriggerCommandCacheCallback(Datum arg,
 										 int cacheid, uint32 hashvalue)
 {
-	hash_destroy(EventCommandTriggerCache);
-	EventCommandTriggerCache = NULL;
+	hash_destroy(EventTriggerProcsCache);
+	EventTriggerProcsCache = NULL;
 }
 
 /*
@@ -249,7 +1209,7 @@ InitEventTriggerCache(void)
 	if (!CacheMemoryContext)
 		CreateCacheMemoryContext();
 
-	EventCommandTriggerCache = NULL;
+	EventTriggerProcsCache = NULL;
 
 	/* Watch for invalidation events. */
 	CacheRegisterSyscacheCallback(EVENTTRIGGERNAME,
@@ -265,30 +1225,30 @@ get_event_triggers(TrigEvent event, TrigEventCommand command)
 {
 	EventCommandTriggers *triggers =
 		(EventCommandTriggers *) palloc(sizeof(EventCommandTriggers));
-	EventCommandTriggerCacheKey anykey, cmdkey;
-	EventCommandTriggerCacheEntry *any, *cmd;
+	EventTriggerProcsCacheKey anykey, cmdkey;
+	EventTriggerProcsCacheEntry *any, *cmd;
 
 	triggers->event = event;
 	triggers->command = command;
 	triggers->procs = NIL;
 
 	/* Find existing cache entry, if any. */
-	if (!EventCommandTriggerCache)
+	if (!EventTriggerProcsCache)
 		BuildEventTriggerCache();
 
 	/* ANY command triggers */
 	memset(&anykey, 0, sizeof(anykey));
 	anykey.event = event;
-	anykey.command = E_ANY;
-	any = (EventCommandTriggerCacheEntry *)
-		hash_search(EventCommandTriggerCache, (void *)&anykey, HASH_FIND, NULL);
+	anykey.command = ETC_ANY;
+	any = (EventTriggerProcsCacheEntry *)
+		hash_search(EventTriggerProcsCache, (void *)&anykey, HASH_FIND, NULL);
 
 	/* Specific command triggers */
 	memset(&cmdkey, 0, sizeof(cmdkey));
 	cmdkey.event = event;
 	cmdkey.command = command;
-	cmd = (EventCommandTriggerCacheEntry *)
-		hash_search(EventCommandTriggerCache, (void *)&cmdkey, HASH_FIND, NULL);
+	cmd = (EventTriggerProcsCacheEntry *)
+		hash_search(EventTriggerProcsCache, (void *)&cmdkey, HASH_FIND, NULL);
 
 	if (any == NULL && cmd == NULL)
 		return triggers;
@@ -327,7 +1287,8 @@ get_event_triggers(TrigEvent event, TrigEventCommand command)
 				lc_any_procs = lnext(lc_any_procs);
 			}
 
-			/* now append as many elements from CMD list named before next ANY
+			/*
+			 * now append as many elements from CMD list named before next ANY
 			 * entry
 			 */
 			do
@@ -352,3 +1313,253 @@ get_event_triggers(TrigEvent event, TrigEventCommand command)
 	}
 	return triggers;
 }
+
+char *
+event_to_string(TrigEvent event)
+{
+	switch (event)
+	{
+		case EVT_CommandStart:
+			return "command_start";
+	}
+	return NULL;
+}
+
+TrigEvent
+parse_event_name(char *event)
+{
+	if (pg_strcasecmp(event, "command_start") == 0)
+		return EVT_CommandStart;
+	else
+		ereport(ERROR,
+				(errcode(ERRCODE_SYNTAX_ERROR),
+				 errmsg("unrecognized event \"%s\"", event)));
+
+	/* make compiler happy */
+	return -1;
+}
+
+TrigEventCommand
+parse_event_tag(char *cmdtag, bool noerror)
+{
+	char *uctag;
+	NameData key;
+	EventTriggerCommandTagsEntry *entry;
+
+	if (EventTriggerCommandTagsCache == NULL)
+	{
+		int			index;
+		HASHCTL		info;
+		MemoryContext old = MemoryContextSwitchTo(CacheMemoryContext);
+
+		/* build the new hash table */
+		MemSet(&info, 0, sizeof(info));
+		info.keysize = NAMEDATALEN;
+		info.entrysize = sizeof(EventTriggerCommandTagsEntry);
+		info.hash = tag_hash;
+		info.hcxt = CacheMemoryContext;
+
+		/* Create the hash table holding our cache */
+		EventTriggerCommandTagsCache =
+			hash_create("Event Trigger Command Tags Cache",
+						1024,
+						&info,
+						HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+
+		for (index = 0; index < lengthof(EventTriggerCommandTags); index++)
+		{
+			bool found;
+			char *tag = EventTriggerCommandTags[index].tag;
+			NameData key;
+			EventTriggerCommandTagsEntry *hresult;
+
+			memset(&key, 0, NAMEDATALEN);
+			key = *(DatumGetName(DirectFunctionCall1(namein,
+													 CStringGetDatum(tag))));
+
+			hresult = (EventTriggerCommandTagsEntry *)
+				hash_search(EventTriggerCommandTagsCache,
+							(void *)&key, HASH_ENTER, &found);
+
+			hresult->command = EventTriggerCommandTags[index].command;
+		}
+		MemoryContextSwitchTo(old);
+	}
+
+	memset(&key, 0, NAMEDATALEN);
+	uctag = str_toupper(cmdtag, strlen(cmdtag), DEFAULT_COLLATION_OID);
+	key = *(DatumGetName(
+				DirectFunctionCall1(namein, CStringGetDatum(uctag))));
+
+	entry = (EventTriggerCommandTagsEntry *)
+		hash_search(EventTriggerCommandTagsCache,
+					(void *)&key, HASH_FIND, NULL);
+
+	if (entry == NULL)
+	{
+		if (!noerror)
+			ereport(ERROR,
+					(errcode(ERRCODE_SYNTAX_ERROR),
+					 errmsg("unrecognized command \"%s\"", cmdtag)));
+		return 	ETC_UNKNOWN;
+	}
+	return entry->command;
+}
+
+char *
+command_to_string(TrigEventCommand command)
+{
+	int			index;
+	for (index = 0; index < lengthof(EventTriggerCommandTags); index++)
+	{
+		if (command == EventTriggerCommandTags[index].command)
+			return EventTriggerCommandTags[index].tag;
+	}
+	return NULL;
+}
+
+/*
+ * Cache lookup support for ProcessUtility
+ */
+TrigEventCommand
+get_command_from_nodetag(NodeTag node, ObjectType type, bool noerror)
+{
+	EventTriggerCommandNodeKey key;
+	EventTriggerCommandNodeEntry *entry;
+
+	if (EventTriggerCommandNodeCache == NULL)
+	{
+		int			index;
+		HASHCTL		info;
+		MemoryContext old = MemoryContextSwitchTo(CacheMemoryContext);
+
+		/* build the new hash table */
+		MemSet(&info, 0, sizeof(info));
+		info.keysize = sizeof(EventTriggerCommandNodeKey);
+		info.entrysize = sizeof(EventTriggerCommandNodeEntry);
+		info.hash = tag_hash;
+		info.hcxt = CacheMemoryContext;
+
+		/* Create the hash table holding our cache */
+		EventTriggerCommandNodeCache =
+			hash_create("Event Trigger Command Node Cache",
+						1024,
+						&info,
+						HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+
+		for (index = 0; index < lengthof(EventTriggerCommandTags); index++)
+		{
+			bool found;
+			EventTriggerCommandNodeKey key;
+			EventTriggerCommandNodeEntry *hresult;
+
+			memset(&key, 0, sizeof(key));
+			key.node = EventTriggerCommandTags[index].node;
+			key.type = EventTriggerCommandTags[index].type;
+
+			hresult = (EventTriggerCommandNodeEntry *)
+				hash_search(EventTriggerCommandNodeCache,
+							(void *)&key, HASH_ENTER, &found);
+
+			hresult->command = EventTriggerCommandTags[index].command;
+		}
+		MemoryContextSwitchTo(old);
+	}
+
+	memset(&key, 0, sizeof(key));
+	key.node = node;
+	key.type = type;
+
+	entry = (EventTriggerCommandNodeEntry *)
+		hash_search(EventTriggerCommandNodeCache,
+					(void *)&key, HASH_FIND, NULL);
+
+	if (entry == NULL)
+	{
+		if (!noerror)
+			/* fixme: should not happen, use elog? */
+			ereport(ERROR,
+					(errcode(ERRCODE_SYNTAX_ERROR),
+					 errmsg("unrecognized node %d and object %d", node, type)));
+		return 	ETC_UNKNOWN;
+	}
+	return entry->command;
+}
+
+char *
+objecttype_to_string(ObjectType type)
+{
+	switch(type)
+	{
+		case OBJECT_AGGREGATE:
+			return "AGGREGATE";
+		case OBJECT_ATTRIBUTE:
+			return "ATTRIBUTE";
+		case OBJECT_CAST:
+			return "CAST";
+		case OBJECT_COLUMN:
+			return "COLUMN";
+		case OBJECT_CONSTRAINT:
+			return "CONSTRAINT";
+		case OBJECT_COLLATION:
+			return "COLLATION";
+		case OBJECT_CONVERSION:
+			return "CONVERSION";
+		case OBJECT_DATABASE:
+			return "DATABASE";
+		case OBJECT_DOMAIN:
+			return "DOMAIN";
+		case OBJECT_EVENT_TRIGGER:
+			return "EVENT TRIGGER";
+		case OBJECT_EXTENSION:
+			return "EXTENSION";
+		case OBJECT_FDW:
+			return "FDW";
+		case OBJECT_FOREIGN_SERVER:
+			return "FOREIGN SERVER";
+		case OBJECT_FOREIGN_TABLE:
+			return "FOREIGN TABLE";
+		case OBJECT_FUNCTION:
+			return "FUNCTION";
+		case OBJECT_INDEX:
+			return "INDEX";
+		case OBJECT_LANGUAGE:
+			return "LANGUAGE";
+		case OBJECT_LARGEOBJECT:
+			return "LARGE OBJECT";
+		case OBJECT_OPCLASS:
+			return "OPERATOR CLASS";
+		case OBJECT_OPERATOR:
+			return "OPERATOR";
+		case OBJECT_OPFAMILY:
+			return "OPERATOR FAMILY";
+		case OBJECT_ROLE:
+			return "ROLE";
+		case OBJECT_RULE:
+			return "RULE";
+		case OBJECT_SCHEMA:
+			return "SCHEMA";
+		case OBJECT_SEQUENCE:
+			return "SEQUENCE";
+		case OBJECT_TABLE:
+			return "TABLE";
+		case OBJECT_TABLESPACE:
+			return "TABLESPACE";
+		case OBJECT_TRIGGER:
+			return "TRIGGER";
+		case OBJECT_TSCONFIGURATION:
+			return "TEXT SEARCH CONFIGURATION";
+		case OBJECT_TSDICTIONARY:
+			return "TEXT SEARCH DICTIONARY";
+		case OBJECT_TSPARSER:
+			return "TEXT SEARCH PARSER";
+		case OBJECT_TSTEMPLATE:
+			return "TEXT SEARCH TEMPLATE";
+		case OBJECT_TYPE:
+			return "TYPE";
+		case OBJECT_VIEW:
+			return "VIEW";
+	}
+	/* silence compiler */
+	return NULL;
+}
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 993053c..611c8e3 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -100,7 +100,7 @@ getSchemaData(Archive *fout, int *numTablesPtr)
 	int			numForeignDataWrappers;
 	int			numForeignServers;
 	int			numDefaultACLs;
-	int			numEvtTriggers;
+	int			numEventTriggers;
 
 	if (g_verbose)
 		write_msg(NULL, "reading schemas\n");
@@ -242,8 +242,8 @@ getSchemaData(Archive *fout, int *numTablesPtr)
 	getTriggers(fout, tblinfo, numTables);
 
 	if (g_verbose)
-		write_msg(NULL, "reading command triggers\n");
-	getEvtTriggers(fout, &numEvtTriggers);
+		write_msg(NULL, "reading event triggers\n");
+	getEventTriggers(fout, &numEventTriggers);
 
 	*numTablesPtr = numTables;
 	return tblinfo;
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 75b7ff0..09ca6dd 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -187,7 +187,7 @@ static void dumpConversion(Archive *fout, ConvInfo *convinfo);
 static void dumpRule(Archive *fout, RuleInfo *rinfo);
 static void dumpAgg(Archive *fout, AggInfo *agginfo);
 static void dumpTrigger(Archive *fout, TriggerInfo *tginfo);
-static void dumpEvtTrigger(Archive *fout, EvtTriggerInfo *evtinfo);
+static void dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo);
 static void dumpTable(Archive *fout, TableInfo *tbinfo);
 static void dumpTableSchema(Archive *fout, TableInfo *tbinfo);
 static void dumpAttrDef(Archive *fout, AttrDefInfo *adinfo);
@@ -5299,52 +5299,54 @@ getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
 }
 
 /*
- * getEvtTriggers
- *	  get information about every command trigger on a dumpable table
+ * getEventTriggers
+ *	  get information about event triggers
  */
-EvtTriggerInfo *
-getEvtTriggers(Archive *fout, int *numEvtTriggers)
+EventTriggerInfo *
+getEventTriggers(Archive *fout, int *numEventTriggers)
 {
 	int			i;
 	PQExpBuffer query = createPQExpBuffer();
 	PGresult   *res;
-	EvtTriggerInfo *evtinfo;
+	EventTriggerInfo *evtinfo;
 	int			i_tableoid,
 				i_oid,
 				i_evtname,
 				i_evtevent,
-                i_evtowner,
+				i_evtowner,
 				i_evttags,
 				i_evtfname,
 				i_evtenabled;
 	int			ntups;
 
+	/* Before 9.3, there are no event triggers */
+	if (fout->remoteVersion < 90300)
+	{
+		*numEventTriggers = 0;
+		return NULL;
+	}
+
 	/* Make sure we are in proper schema */
 	selectSourceSchema(fout, "pg_catalog");
 
-	if (fout->remoteVersion >= 90200)
-	{
-		appendPQExpBuffer(query,
-						  "SELECT e.tableoid, e.oid, evtname, evtenabled, "
-						  "evtevent, (%s evtowner) AS evtowner, "
-						  "array_to_string(array("
-						  "select '''' || x || '''' "
-						  " from unnest(evttags) as t(x)), ', ') as evttags, "
-						  "n.nspname || '.' || p.proname as evtfname "
-						  "FROM pg_event_trigger e "
-						  "JOIN pg_proc p on e.evtfoid = p.oid "
-						  "JOIN pg_namespace n ON p.pronamespace = n.oid "
-						  "ORDER BY e.oid",
-						  username_subquery);
-	}
+	appendPQExpBuffer(query,
+					  "SELECT e.tableoid, e.oid, evtname, evtenabled, "
+					  "evtevent, (%s evtowner) AS evtowner, "
+					  "array_to_string(array("
+					  "select quote_literal(x) "
+					  " from unnest(evttags) as t(x)), ', ') as evttags, "
+					  "e.evtfoid::regproc as evtfname "
+					  "FROM pg_event_trigger e "
+					  "ORDER BY e.oid",
+					  username_subquery);
 
 	res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
 	ntups = PQntuples(res);
 
-	*numEvtTriggers = ntups;
+	*numEventTriggers = ntups;
 
-	evtinfo = (EvtTriggerInfo *) pg_malloc(ntups * sizeof(EvtTriggerInfo));
+	evtinfo = (EventTriggerInfo *) pg_malloc(ntups * sizeof(EventTriggerInfo));
 
 	i_tableoid = PQfnumber(res, "tableoid");
 	i_oid = PQfnumber(res, "oid");
@@ -7248,7 +7250,7 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
 			dumpTrigger(fout, (TriggerInfo *) dobj);
 			break;
 		case DO_EVENT_TRIGGER:
-			dumpEvtTrigger(fout, (EvtTriggerInfo *) dobj);
+			dumpEventTrigger(fout, (EventTriggerInfo *) dobj);
 			break;
 		case DO_CONSTRAINT:
 			dumpConstraint(fout, (ConstraintInfo *) dobj);
@@ -13743,7 +13745,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
 }
 
 static void
-dumpEvtTrigger(Archive *fout, EvtTriggerInfo *evtinfo)
+dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo)
 {
 	PQExpBuffer query;
 	PQExpBuffer labelq;
@@ -13754,19 +13756,19 @@ dumpEvtTrigger(Archive *fout, EvtTriggerInfo *evtinfo)
 	appendPQExpBuffer(query, "CREATE EVENT TRIGGER ");
 	appendPQExpBufferStr(query, fmtId(evtinfo->dobj.name));
 	appendPQExpBuffer(query, " ON ");
-	appendPQExpBufferStr(query, evtinfo->evtevent);
+	appendPQExpBufferStr(query, fmtId(evtinfo->evtevent));
 	appendPQExpBufferStr(query, " ");
 
 	if (strcmp("", evtinfo->evttags) != 0)
 	{
-		appendPQExpBufferStr(query, "when tag in (");
+		appendPQExpBufferStr(query, "\n         WHEN TAG IN (");
 		appendPQExpBufferStr(query, evtinfo->evttags);
 		appendPQExpBufferStr(query, ") ");
 	}
 
-	appendPQExpBuffer(query, "EXECUTE PROCEDURE ");
+	appendPQExpBuffer(query, "\n   EXECUTE PROCEDURE ");
 	appendPQExpBufferStr(query, evtinfo->evtfname);
-	appendPQExpBuffer(query, " ();\n");
+	appendPQExpBuffer(query, "();\n");
 
 	if (evtinfo->evtenabled != 'O')
 	{
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 758a1df..5793bca 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -363,7 +363,7 @@ typedef struct _evttriggerInfo
 	char	   *evtfname;
 	char		evttype;
 	char		evtenabled;
-} EvtTriggerInfo;
+} EventTriggerInfo;
 
 /*
  * struct ConstraintInfo is used for all constraint types.	However we
@@ -575,6 +575,6 @@ extern ForeignServerInfo *getForeignServers(Archive *fout,
 extern DefaultACLInfo *getDefaultACLs(Archive *fout, int *numDefaultACLs);
 extern void getExtensionMembership(Archive *fout, ExtensionInfo extinfo[],
 					   int numExtensions);
-extern EvtTriggerInfo *getEvtTriggers(Archive *fout, int *numEvtTriggers);
+extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers);
 
 #endif   /* PG_DUMP_H */
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index 6d4c2ba..5318e7a 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -24,8 +24,9 @@ static const char *modulename = gettext_noop("sorter");
  * Objects are sorted by priority levels, and within an equal priority level
  * by OID.	(This is a relatively crude hack to provide semi-reasonable
  * behavior for old databases without full dependency info.)  Note: collations,
- * extensions, text search, foreign-data, and default ACL objects can't really
- * happen here, so the rather bogus priorities for them don't matter.
+ * extensions, text search, foreign-data, event trigger, and default ACL
+ * objects can't really happen here, so the rather bogus priorities for them
+ * don't matter.
  *
  * NOTE: object-type priorities must match the section assignments made in
  * pg_dump.c; that is, PRE_DATA objects must sort before DO_PRE_DATA_BOUNDARY,
@@ -114,7 +115,7 @@ static const int newObjectTypePriority[] =
 	24,							/* DO_BLOB_DATA */
 	22,							/* DO_PRE_DATA_BOUNDARY */
 	25,							/* DO_POST_DATA_BOUNDARY */
-	30							/* DO_EVENT_TRIGGER */
+	32							/* DO_EVENT_TRIGGER */
 };
 
 static DumpId preDataBoundId;
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 7ae8049..939e88f 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -491,7 +491,7 @@ exec_command(const char *cmd,
 					success = listExtensions(pattern);
 				break;
 			case 'y':			/* Event Triggers */
-				success = listEvtTriggers(pattern, show_verbose);
+				success = listEventTriggers(pattern, show_verbose);
 				break;
 			default:
 				status = PSQL_CMD_UNKNOWN;
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 7e8c996..14c6fe3 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -2958,7 +2958,7 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
  * Describes Event Triggers.
  */
 bool
-listEvtTriggers(const char *pattern, bool verbose)
+listEventTriggers(const char *pattern, bool verbose)
 {
 	PQExpBufferData buf;
 	PGresult   *res;
@@ -2971,15 +2971,14 @@ listEvtTriggers(const char *pattern, bool verbose)
 					  "select evtname as \"%s\", "
 					  "evtevent as  \"%s\", "
 					  "pg_catalog.pg_get_userbyid(e.evtowner) AS \"%s\", "
-					  " case evtenabled when 'O' then 'enabled' "
+					  "case evtenabled when 'O' then 'enabled' "
 					  "  when 'R' then 'replica' "
 					  "  when 'A' then 'always' "
 					  "  when 'D' then 'disabled' end as  \"%s\", "
-					  "n.nspname || '.' || p.proname || '()' as \"%s\", "
-					  " array_to_string(array(select x "
+					  "e.evtfoid::regproc as \"%s\", "
+					  "array_to_string(array(select x "
 					  "      from unnest(evttags) as t(x)), ', ') as  \"%s\" "
-					  "FROM pg_event_trigger e JOIN pg_proc p on e.evtfoid = p.oid "
-					  "JOIN pg_namespace n ON p.pronamespace = n.oid ",
+					  "FROM pg_event_trigger e ",
 					  gettext_noop("Name"),
 					  gettext_noop("Event"),
 					  gettext_noop("Owner"),
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index f2bc794..eef7733 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -97,6 +97,6 @@ extern bool listExtensions(const char *pattern);
 extern bool listExtensionContents(const char *pattern);
 
 /* \dy */
-extern bool listEvtTriggers(const char *pattern, bool verbose);
+extern bool listEventTriggers(const char *pattern, bool verbose);
 
 #endif   /* DESCRIBE_H */
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 5807265..0843b65 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -229,7 +229,7 @@ slashUsage(unsigned short int pager)
 	fprintf(output, _("  \\dv[S+] [PATTERN]      list views\n"));
 	fprintf(output, _("  \\dE[S+] [PATTERN]      list foreign tables\n"));
 	fprintf(output, _("  \\dx[+]  [PATTERN]      list extensions\n"));
-	fprintf(output, _("  \\dy     [PATTERN]      list command triggers\n"));
+	fprintf(output, _("  \\dy     [PATTERN]      list event triggers\n"));
 	fprintf(output, _("  \\l[+]                  list all databases\n"));
 	fprintf(output, _("  \\sf[+] FUNCNAME        show a function's definition\n"));
 	fprintf(output, _("  \\z      [PATTERN]      same as \\dp\n"));
diff --git a/src/include/catalog/pg_event_trigger.h b/src/include/catalog/pg_event_trigger.h
index 153d48a..a6caaee 100644
--- a/src/include/catalog/pg_event_trigger.h
+++ b/src/include/catalog/pg_event_trigger.h
@@ -60,122 +60,4 @@ typedef FormData_pg_event_trigger *Form_pg_event_trigger;
 #define Anum_pg_event_trigger_evtenabled		5
 #define Anum_pg_event_trigger_evttags			6
 
-/*
- * Times at which an event trigger can be fired. These are the
- * possible values for pg_event_trigger.evtevent.
- *
- * As of now we only implement the command_start firing point, we intend on
- * adding more firing points later.
- */
-typedef enum TrigEvent
-{
-	E_CommandStart       = 1,
-} TrigEvent;
-
-/*
- * Supported commands
- */
-typedef enum TrigEventCommand
-{
-	E_UNKNOWN = 0,
-	E_ANY = 1,
-
-	E_AlterAggregate   = 100,
-	E_AlterCast,
-	E_AlterCollation,
-	E_AlterConversion,
-	E_AlterDomain,
-	E_AlterExtension,
-	E_AlterForeignDataWrapper,
-	E_AlterForeignTable,
-	E_AlterFunction,
-	E_AlterIndex,
-	E_AlterLanguage,
-	E_AlterOperator,
-	E_AlterOperatorClass,
-	E_AlterOperatorFamily,
-	E_AlterSchema,
-	E_AlterSequence,
-	E_AlterServer,
-	E_AlterTable,
-	E_AlterTextSearchParser,
-	E_AlterTextSearchConfiguration,
-	E_AlterTextSearchDictionary,
-	E_AlterTextSearchTemplate,
-	E_AlterTrigger,
-	E_AlterType,
-	E_AlterUserMapping,
-	E_AlterView,
-
-	E_Cluster = 300,
-	E_Load,
-	E_Reindex,
-	E_SelectInto,
-	E_Vacuum,
-
-	E_CreateAggregate = 400,
-	E_CreateCast,
-	E_CreateCollation,
-	E_CreateConversion,
-	E_CreateDomain,
-	E_CreateExtension,
-	E_CreateForeignDataWrapper,
-	E_CreateForeignTable,
-	E_CreateFunction,
-	E_CreateIndex,
-	E_CreateLanguage,
-	E_CreateOperator,
-	E_CreateOperatorClass,
-	E_CreateOperatorFamily,
-	E_CreateRule,
-	E_CreateSchema,
-	E_CreateSequence,
-	E_CreateServer,
-	E_CreateTable,
-	E_CreateTableAs,
-	E_CreateTextSearchParser,
-	E_CreateTextSearchConfiguration,
-	E_CreateTextSearchDictionary,
-	E_CreateTextSearchTemplate,
-	E_CreateTrigger,
-	E_CreateType,
-	E_CreateUserMapping,
-	E_CreateView,
-
-	E_DropAggregate = 600,
-	E_DropCast,
-	E_DropCollation,
-	E_DropConversion,
-	E_DropDomain,
-	E_DropExtension,
-	E_DropForeignDataWrapper,
-	E_DropForeignTable,
-	E_DropFunction,
-	E_DropIndex,
-	E_DropLanguage,
-	E_DropOperator,
-	E_DropOperatorClass,
-	E_DropOperatorFamily,
-	E_DropRule,
-	E_DropSchema,
-	E_DropSequence,
-	E_DropServer,
-	E_DropTable,
-	E_DropTextSearchParser,
-	E_DropTextSearchConfiguration,
-	E_DropTextSearchDictionary,
-	E_DropTextSearchTemplate,
-	E_DropTrigger,
-	E_DropType,
-	E_DropUserMapping,
-	E_DropView
-} TrigEventCommand;
-
-/* implemented in src/backend/catalog/pg_event_trigger.c */
-char * event_to_string(TrigEvent event);
-TrigEvent parse_event_name(char *event);
-
-char * command_to_string(TrigEventCommand command);
-TrigEventCommand parse_event_tag(char *command, bool noerror);
-
 #endif   /* PG_EVENT_TRIGGER_H */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 340de88..743f890 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3456,6 +3456,10 @@ DATA(insert OID = 2300 (  trigger_in		PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 2
 DESCR("I/O");
 DATA(insert OID = 2301 (  trigger_out		PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "2279" _null_ _null_ _null_ _null_ trigger_out _null_ _null_ _null_ ));
 DESCR("I/O");
+DATA(insert OID = 3594 (  event_trigger_in	PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 3838 "2275" _null_ _null_ _null_ _null_ event_trigger_in _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 3595 (  event_trigger_out	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "3838" _null_ _null_ _null_ _null_ event_trigger_out _null_ _null_ _null_ ));
+DESCR("I/O");
 DATA(insert OID = 2302 (  language_handler_in	PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 2280 "2275" _null_ _null_ _null_ _null_ language_handler_in _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2303 (  language_handler_out	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "2280" _null_ _null_ _null_ _null_ language_handler_out _null_ _null_ _null_ ));
@@ -4645,6 +4649,7 @@ DESCR("SP-GiST support for suffix tree over text");
 DATA(insert OID = 4031 (  spg_text_leaf_consistent	PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "2281 2281" _null_ _null_ _null_ _null_  spg_text_leaf_consistent _null_ _null_ _null_ ));
 DESCR("SP-GiST support for suffix tree over text");
 
+
 /*
  * Symbolic values for provolatile column: these indicate whether the result
  * of a function is dependent *only* on the values of its explicit arguments,
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 98c7dd5..86be998 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -650,7 +650,7 @@ DATA(insert OID = 2278 ( void			PGNSP PGUID  4 t p P f t \054 0 0 0 void_in void
 #define VOIDOID			2278
 DATA(insert OID = 2279 ( trigger		PGNSP PGUID  4 t p P f t \054 0 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
 #define TRIGGEROID		2279
-DATA(insert OID = 3838 ( event_trigger		PGNSP PGUID  4 t p P f t \054 0 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+DATA(insert OID = 3838 ( event_trigger		PGNSP PGUID  4 t p P f t \054 0 0 0 event_trigger_in event_trigger_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
 #define EVTTRIGGEROID		3838
 DATA(insert OID = 2280 ( language_handler	PGNSP PGUID  4 t p P f t \054 0 0 0 language_handler_in language_handler_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
 #define LANGUAGE_HANDLEROID		2280
diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h
index 5c4db5c..13be6bc 100644
--- a/src/include/commands/event_trigger.h
+++ b/src/include/commands/event_trigger.h
@@ -15,6 +15,7 @@
 
 #include "catalog/pg_event_trigger.h"
 #include "nodes/parsenodes.h"
+#include "utils/evtcache.h"
 
 /*
  * To be able to call user defined function on event triggers, the places in
@@ -30,6 +31,8 @@ typedef struct EventContextData
 	TrigEventCommand command;	/* For command triggers */
 	char		*toplevel;		/* TopLevel Command Tag */
 	char		*tag;			/* Command Tag */
+	char		*operation;		/* CREATE / ALTER / DROP, or NULL */
+	ObjectType	 objecttype;	/* TABLE, FUNCTION, CAST, etc, or NULL */
 	Oid			 objectId;		/* oid of the existing object, if any */
 	char		*schemaname;	/* schemaname or NULL if not relevant */
 	char		*objectname;	/* objectname */
@@ -48,9 +51,11 @@ typedef struct EventContextData *EventContext;
 typedef struct EventTriggerData
 {
 	NodeTag		 type;
-	char        *when;			/* Either BEFORE or AFTER */
+	char        *event;			/* command_start, etc */
 	char		*toplevel;		/* TopLevel Command Tag */
 	char		*tag;			/* Command Tag */
+	char		*operation;		/* CREATE / ALTER / DROP, or NULL */
+	char		*objecttype;	/* TABLE, FUNCTION, CAST, etc, or NULL */
 	Oid			 objectId;		/* oid of the existing object, if any */
 	char		*schemaname;	/* schemaname or NULL if not relevant */
 	char		*objectname;	/* objectname */
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 2d1cccb..5700e54 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -195,6 +195,7 @@ typedef enum AclObjectKind
 	ACL_KIND_TSCONFIGURATION,	/* pg_ts_config */
 	ACL_KIND_FDW,				/* pg_foreign_data_wrapper */
 	ACL_KIND_FOREIGN_SERVER,	/* pg_foreign_server */
+	ACL_KIND_EVENT_TRIGGER,		/* pg_event_trigger */
 	ACL_KIND_EXTENSION,			/* pg_extension */
 	MAX_ACL_KIND				/* MUST BE LAST */
 } AclObjectKind;
@@ -322,6 +323,7 @@ extern bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid);
 extern bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid);
 extern bool pg_foreign_data_wrapper_ownercheck(Oid srv_oid, Oid roleid);
 extern bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid);
+extern bool pg_event_trigger_ownercheck(Oid et_oid, Oid roleid);
 extern bool pg_extension_ownercheck(Oid ext_oid, Oid roleid);
 extern bool has_createrole_privilege(Oid roleid);
 
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 71563ad..8b9291c 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -532,6 +532,8 @@ extern Datum void_recv(PG_FUNCTION_ARGS);
 extern Datum void_send(PG_FUNCTION_ARGS);
 extern Datum trigger_in(PG_FUNCTION_ARGS);
 extern Datum trigger_out(PG_FUNCTION_ARGS);
+extern Datum event_trigger_in(PG_FUNCTION_ARGS);
+extern Datum event_trigger_out(PG_FUNCTION_ARGS);
 extern Datum language_handler_in(PG_FUNCTION_ARGS);
 extern Datum language_handler_out(PG_FUNCTION_ARGS);
 extern Datum fdw_handler_in(PG_FUNCTION_ARGS);
@@ -1013,7 +1015,6 @@ extern Datum pg_encoding_max_length_sql(PG_FUNCTION_ARGS);
 /* format_type.c */
 extern Datum format_type(PG_FUNCTION_ARGS);
 extern char *format_type_be(Oid type_oid);
-extern char *format_type_be_without_namespace(Oid type_oid);
 extern char *format_type_with_typemod(Oid type_oid, int32 typemod);
 extern Datum oidvectortypes(PG_FUNCTION_ARGS);
 extern int32 type_maximum_size(Oid type_oid, int32 typemod);
diff --git a/src/include/utils/evtcache.h b/src/include/utils/evtcache.h
index 51f6bec..ef84b90 100644
--- a/src/include/utils/evtcache.h
+++ b/src/include/utils/evtcache.h
@@ -15,6 +15,125 @@
 
 #include "catalog/pg_event_trigger.h"
 
+
+/*
+ * Times at which an event trigger can be fired. These are the
+ * possible values for pg_event_trigger.evtevent.
+ *
+ * As of now we only implement the command_start firing point, we intend on
+ * adding more firing points later.
+ */
+typedef enum TrigEvent
+{
+	EVT_CommandStart       = 1,
+} TrigEvent;
+
+/*
+ * Supported commands
+ *
+ * Those values are not going to disk, so can be shuffled around at will. We
+ * keep the number organized so that it's easier to debug, should it be needed.
+ *
+ * See also EventTriggerCommandTags in src/backend/utils/cache/evtcache.c
+ */
+typedef enum TrigEventCommand
+{
+	ETC_UNSET = -1,
+	ETC_UNKNOWN = 0,
+	ETC_ANY = 1,
+
+	ETC_AlterAggregate   = 100,
+	ETC_AlterCast,
+	ETC_AlterCollation,
+	ETC_AlterConversion,
+	ETC_AlterDomain,
+	ETC_AlterExtension,
+	ETC_AlterForeignDataWrapper,
+	ETC_AlterForeignTable,
+	ETC_AlterFunction,
+	ETC_AlterIndex,
+	ETC_AlterLanguage,
+	ETC_AlterOperator,
+	ETC_AlterOperatorClass,
+	ETC_AlterOperatorFamily,
+	ETC_AlterRule,
+	ETC_AlterSchema,
+	ETC_AlterSequence,
+	ETC_AlterServer,
+	ETC_AlterTable,
+	ETC_AlterTextSearchParser,
+	ETC_AlterTextSearchConfiguration,
+	ETC_AlterTextSearchDictionary,
+	ETC_AlterTextSearchTemplate,
+	ETC_AlterTrigger,
+	ETC_AlterType,
+	ETC_AlterUserMapping,
+	ETC_AlterView,
+
+	ETC_Cluster = 300,
+	ETC_Load,
+	ETC_Reindex,
+	ETC_SelectInto,
+	ETC_Vacuum,
+
+	ETC_CreateAggregate = 400,
+	ETC_CreateCast,
+	ETC_CreateCollation,
+	ETC_CreateConversion,
+	ETC_CreateDomain,
+	ETC_CreateExtension,
+	ETC_CreateForeignDataWrapper,
+	ETC_CreateForeignTable,
+	ETC_CreateFunction,
+	ETC_CreateIndex,
+	ETC_CreateLanguage,
+	ETC_CreateOperator,
+	ETC_CreateOperatorClass,
+	ETC_CreateOperatorFamily,
+	ETC_CreateRule,
+	ETC_CreateSchema,
+	ETC_CreateSequence,
+	ETC_CreateServer,
+	ETC_CreateTable,
+	ETC_CreateTableAs,
+	ETC_CreateTextSearchParser,
+	ETC_CreateTextSearchConfiguration,
+	ETC_CreateTextSearchDictionary,
+	ETC_CreateTextSearchTemplate,
+	ETC_CreateTrigger,
+	ETC_CreateType,
+	ETC_CreateUserMapping,
+	ETC_CreateView,
+
+	ETC_DropAggregate = 600,
+	ETC_DropCast,
+	ETC_DropCollation,
+	ETC_DropConversion,
+	ETC_DropDomain,
+	ETC_DropExtension,
+	ETC_DropForeignDataWrapper,
+	ETC_DropForeignTable,
+	ETC_DropFunction,
+	ETC_DropIndex,
+	ETC_DropLanguage,
+	ETC_DropOperator,
+	ETC_DropOperatorClass,
+	ETC_DropOperatorFamily,
+	ETC_DropRule,
+	ETC_DropSchema,
+	ETC_DropSequence,
+	ETC_DropServer,
+	ETC_DropTable,
+	ETC_DropTextSearchParser,
+	ETC_DropTextSearchConfiguration,
+	ETC_DropTextSearchDictionary,
+	ETC_DropTextSearchTemplate,
+	ETC_DropTrigger,
+	ETC_DropType,
+	ETC_DropUserMapping,
+	ETC_DropView
+} TrigEventCommand;
+
 /*
  * Event Triggers to fire for a given event and command, including ANY command
  * triggers.
@@ -30,5 +149,16 @@ void InitEventTriggerCache(void);
 EventCommandTriggers *get_event_triggers(TrigEvent event,
 										 TrigEventCommand command);
 
+char * event_to_string(TrigEvent event);
+TrigEvent parse_event_name(char *event);
+
+char * command_to_string(TrigEventCommand command);
+TrigEventCommand parse_event_tag(char *cmdtag, bool noerror);
+
+TrigEventCommand get_command_from_nodetag(NodeTag node,
+										  ObjectType type,
+										  bool noerror);
+
+char * objecttype_to_string(ObjectType type);
 
 #endif   /* EVTCACHE_H */
diff --git a/src/pl/plperl/expected/plperl_trigger.out b/src/pl/plperl/expected/plperl_trigger.out
index b61d47c..2d1ed56 100644
--- a/src/pl/plperl/expected/plperl_trigger.out
+++ b/src/pl/plperl/expected/plperl_trigger.out
@@ -309,10 +309,10 @@ $$ LANGUAGE plperl;
 SELECT direct_trigger();
 ERROR:  trigger functions can only be called as triggers
 CONTEXT:  compilation of PL/Perl function "direct_trigger"
--- test plperl command triggers
+-- test plperl event triggers
 create or replace function perlsnitch() returns event_trigger language plperl as $$
   elog(NOTICE, "perlsnitch: "
-               . $_TD->{when} . " "
+               . $_TD->{event} . " "
                . $_TD->{tag} . " "
                . $_TD->{schemaname} . " "
                . $_TD->{objectname});
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 5b456aa..374a81e 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -1571,7 +1571,7 @@ plperl_trigger_build_args(FunctionCallInfo fcinfo)
 }
 
 
-/* Set up the arguments for a command trigger call. */
+/* Set up the arguments for an event trigger call. */
 static SV  *
 plperl_event_trigger_build_args(FunctionCallInfo fcinfo)
 {
@@ -1584,7 +1584,7 @@ plperl_event_trigger_build_args(FunctionCallInfo fcinfo)
 
 	tdata = (EventTriggerData *) fcinfo->context;
 
-	hv_store_string(hv, "when", cstr2sv(tdata->when));
+	hv_store_string(hv, "event", cstr2sv(tdata->event));
 	hv_store_string(hv, "tag", cstr2sv(tdata->tag));
 
 	if (tdata->objectId == InvalidOid)
@@ -1594,8 +1594,14 @@ plperl_event_trigger_build_args(FunctionCallInfo fcinfo)
 			DirectFunctionCall1(oidout, ObjectIdGetDatum(tdata->objectId)));
 	hv_store_string(hv, "objectid", cstr2sv(objectid));
 
-	hv_store_string(hv, "objectname", cstr2sv(tdata->objectname == NULL ? "NULL" : tdata->objectname));
-	hv_store_string(hv, "schemaname", cstr2sv(tdata->schemaname == NULL ? "NULL" : tdata->schemaname));
+	hv_store_string(hv, "operation",
+					cstr2sv(tdata->operation == NULL ? "NULL" : tdata->operation));
+	hv_store_string(hv, "objecttype",
+					cstr2sv(tdata->objecttype == NULL ? "NULL" : tdata->objecttype));
+	hv_store_string(hv, "objectname",
+					cstr2sv(tdata->objectname == NULL ? "NULL" : tdata->objectname));
+	hv_store_string(hv, "schemaname",
+					cstr2sv(tdata->schemaname == NULL ? "NULL" : tdata->schemaname));
 
 	return newRV_noinc((SV *) hv);
 }
diff --git a/src/pl/plperl/sql/plperl_trigger.sql b/src/pl/plperl/sql/plperl_trigger.sql
index 9cc2408..75a9f11 100644
--- a/src/pl/plperl/sql/plperl_trigger.sql
+++ b/src/pl/plperl/sql/plperl_trigger.sql
@@ -170,10 +170,10 @@ $$ LANGUAGE plperl;
 
 SELECT direct_trigger();
 
--- test plperl command triggers
+-- test plperl event triggers
 create or replace function perlsnitch() returns event_trigger language plperl as $$
   elog(NOTICE, "perlsnitch: "
-               . $_TD->{when} . " "
+               . $_TD->{event} . " "
                . $_TD->{tag} . " "
                . $_TD->{schemaname} . " "
                . $_TD->{objectname});
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 77c5ed9..4fb1443 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -536,7 +536,7 @@ do_compile(FunctionCallInfo fcinfo,
 				if (rettypeid == VOIDOID ||
 					rettypeid == RECORDOID)
 					 /* okay */ ;
-				else if (rettypeid == TRIGGEROID)
+				else if (rettypeid == TRIGGEROID || rettypeid == EVTTRIGGEROID)
 					ereport(ERROR,
 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 							 errmsg("trigger functions can only be called as triggers")));
@@ -689,15 +689,15 @@ do_compile(FunctionCallInfo fcinfo,
 			if (procStruct->pronargs != 0)
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
-						 errmsg("command trigger functions cannot have declared arguments")));
+						 errmsg("event trigger functions cannot have declared arguments")));
 
 			/* Add the variable tg_when */
-			var = plpgsql_build_variable("tg_when", 0,
+			var = plpgsql_build_variable("tg_event", 0,
 										 plpgsql_build_datatype(TEXTOID,
 																-1,
 											   function->fn_input_collation),
 										 true);
-			function->tg_when_varno = var->dno;
+			function->tg_event_varno = var->dno;
 
 			/* Add the variable tg_tag */
 			var = plpgsql_build_variable("tg_tag", 0,
@@ -707,6 +707,22 @@ do_compile(FunctionCallInfo fcinfo,
 										 true);
 			function->tg_tag_varno = var->dno;
 
+			/* Add the variable tg_operation */
+			var = plpgsql_build_variable("tg_operation", 0,
+										 plpgsql_build_datatype(TEXTOID,
+																-1,
+											   function->fn_input_collation),
+										 true);
+			function->tg_operation_varno = var->dno;
+
+			/* Add the variable tg_objecttype */
+			var = plpgsql_build_variable("tg_objecttype", 0,
+										 plpgsql_build_datatype(TEXTOID,
+																-1,
+											   function->fn_input_collation),
+										 true);
+			function->tg_objecttype_varno = var->dno;
+
 			/* Add the variable tg_objectid */
 			var = plpgsql_build_variable("tg_objectid", 0,
 										 plpgsql_build_datatype(OIDOID,
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index fd59d75..a2cf506 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -773,8 +773,8 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
 	return rettup;
 }
 
-void plpgsql_exec_event_trigger(PLpgSQL_function *func,
-								EventTriggerData *trigdata)
+void
+plpgsql_exec_event_trigger(PLpgSQL_function *func, EventTriggerData *trigdata)
 {
 	PLpgSQL_execstate estate;
 	ErrorContextCallback plerrcontext;
@@ -805,8 +805,8 @@ void plpgsql_exec_event_trigger(PLpgSQL_function *func,
 	/*
 	 * Assign the special tg_ variables
 	 */
-	var = (PLpgSQL_var *) (estate.datums[func->tg_when_varno]);
-	var->value = CStringGetTextDatum(trigdata->when);
+	var = (PLpgSQL_var *) (estate.datums[func->tg_event_varno]);
+	var->value = CStringGetTextDatum(trigdata->event);
 	var->isnull = false;
 	var->freeval = true;
 
@@ -815,6 +815,30 @@ void plpgsql_exec_event_trigger(PLpgSQL_function *func,
 	var->isnull = false;
 	var->freeval = true;
 
+	var = (PLpgSQL_var *) (estate.datums[func->tg_operation_varno]);
+	if (trigdata->operation == NULL)
+	{
+		var->isnull = true;
+	}
+	else
+	{
+		var->value = CStringGetTextDatum(trigdata->operation);
+		var->isnull = false;
+	}
+	var->freeval = false;
+
+	var = (PLpgSQL_var *) (estate.datums[func->tg_objecttype_varno]);
+	if (trigdata->objecttype == NULL)
+	{
+		var->isnull = true;
+	}
+	else
+	{
+		var->value = CStringGetTextDatum(trigdata->objecttype);
+		var->isnull = false;
+	}
+	var->freeval = false;
+
 	var = (PLpgSQL_var *) (estate.datums[func->tg_objectid_varno]);
 	if (trigdata->objectId == InvalidOid)
 	{
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 57f556f..4e15ad8 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -721,6 +721,9 @@ typedef struct PLpgSQL_function
 	int			tg_argv_varno;
 
 	int			tg_tag_varno;
+	int			tg_event_varno;
+	int			tg_operation_varno;
+	int			tg_objecttype_varno;
 	int			tg_objectid_varno;
 	int			tg_schemaname_varno;
 	int			tg_objectname_varno;
diff --git a/src/pl/plpython/expected/plpython_trigger.out b/src/pl/plpython/expected/plpython_trigger.out
index f756462..5294dc7 100644
--- a/src/pl/plpython/expected/plpython_trigger.out
+++ b/src/pl/plpython/expected/plpython_trigger.out
@@ -610,10 +610,10 @@ SELECT * FROM composite_trigger_nested_test;
  ("(,t)","(1,f)",)
 (3 rows)
 
--- test plpython command triggers
+-- test plpython event triggers
 create or replace function pysnitch() returns event_trigger language plpythonu as $$
   plpy.notice("  pysnitch: %s %s %s.%s" %
-              (TD["when"], TD["tag"], TD["schemaname"], TD["objectname"]));
+              (TD["event"], TD["tag"], TD["schemaname"], TD["objectname"]));
 $$;
 create event trigger py_snitch on command_start execute procedure pysnitch();
 create or replace function foobar() returns int language sql as $$select 1;$$;
diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c
index 63682bf..7405893 100644
--- a/src/pl/plpython/plpy_exec.c
+++ b/src/pl/plpython/plpy_exec.c
@@ -348,8 +348,10 @@ PLy_exec_event_trigger(FunctionCallInfo fcinfo, PLyProcedure *proc)
 	PG_TRY();
 	{
 		/* build command trigger args */
-		PyObject   *pltwhen,
+		PyObject   *pltevent,
 			*plttag,
+			*pltoperation,
+			*pltobjecttype,
 			*pltschemaname,
 			*pltobjectname;
 		char	   *stroid;
@@ -358,14 +360,32 @@ PLy_exec_event_trigger(FunctionCallInfo fcinfo, PLyProcedure *proc)
 		if (!pltdata)
 			PLy_elog(ERROR, "could not create new dictionary while building command trigger arguments");
 
-		pltwhen = PyString_FromString(tdata->when);
-		PyDict_SetItemString(pltdata, "when", pltwhen);
-		Py_DECREF(pltwhen);
+		pltevent = PyString_FromString(tdata->event);
+		PyDict_SetItemString(pltdata, "event", pltevent);
+		Py_DECREF(pltevent);
 
 		plttag = PyString_FromString(tdata->tag);
 		PyDict_SetItemString(pltdata, "tag", plttag);
 		Py_DECREF(plttag);
 
+		if (tdata->operation == NULL)
+			PyDict_SetItemString(pltdata, "operation", Py_None);
+		else
+		{
+			pltoperation = PyString_FromString(tdata->operation);
+			PyDict_SetItemString(pltdata, "operation", pltoperation);
+			Py_DECREF(pltoperation);
+		}
+
+		if (tdata->objecttype == NULL)
+			PyDict_SetItemString(pltdata, "objecttype", Py_None);
+		else
+		{
+			pltobjecttype = PyString_FromString(tdata->objecttype);
+			PyDict_SetItemString(pltdata, "objecttype", pltobjecttype);
+			Py_DECREF(pltobjecttype);
+		}
+
 		if (tdata->objectId == InvalidOid)
 			PyDict_SetItemString(pltdata, "objectId", Py_None);
 		else
diff --git a/src/pl/plpython/sql/plpython_trigger.sql b/src/pl/plpython/sql/plpython_trigger.sql
index 7ec6e0b..aaa1731 100644
--- a/src/pl/plpython/sql/plpython_trigger.sql
+++ b/src/pl/plpython/sql/plpython_trigger.sql
@@ -388,10 +388,10 @@ INSERT INTO composite_trigger_nested_test VALUES (ROW(ROW(1, 'f'), NULL, 3));
 INSERT INTO composite_trigger_nested_test VALUES (ROW(ROW(NULL, 't'), ROW(1, 'f'), NULL));
 SELECT * FROM composite_trigger_nested_test;
 
--- test plpython command triggers
+-- test plpython event triggers
 create or replace function pysnitch() returns event_trigger language plpythonu as $$
   plpy.notice("  pysnitch: %s %s %s.%s" %
-              (TD["when"], TD["tag"], TD["schemaname"], TD["objectname"]));
+              (TD["event"], TD["tag"], TD["schemaname"], TD["objectname"]));
 $$;
 
 create event trigger py_snitch on command_start execute procedure pysnitch();
diff --git a/src/pl/tcl/expected/pltcl_setup.out b/src/pl/tcl/expected/pltcl_setup.out
index 9b9c157..cfe124c 100644
--- a/src/pl/tcl/expected/pltcl_setup.out
+++ b/src/pl/tcl/expected/pltcl_setup.out
@@ -519,9 +519,9 @@ select tcl_date_week(2001,10,24);
  42
 (1 row)
 
--- test pltcl command triggers
+-- test pltcl event triggers
 create or replace function tclsnitch() returns event_trigger language pltcl as $$
-  elog NOTICE " tclsnitch: $TG_when $TG_tag $TG_schemaname $TG_objectname"
+  elog NOTICE " tclsnitch: $TG_event $TG_tag $TG_schemaname $TG_objectname"
 $$;
 create event trigger tcl_snitch on command_start execute procedure tclsnitch();
 create or replace function foobar() returns int language sql as $$select 1;$$;
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 7df6467..3ee32f7 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -1166,7 +1166,7 @@ pltcl_event_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
 	Tcl_DStringAppendElement(&tcl_cmd, prodesc->internal_proname);
 	PG_TRY();
 	{
-		Tcl_DStringAppendElement(&tcl_cmd, tdata->when);
+		Tcl_DStringAppendElement(&tcl_cmd, tdata->event);
 		Tcl_DStringAppendElement(&tcl_cmd, tdata->tag);
 
 		if (tdata->objectId == InvalidOid)
@@ -1177,6 +1177,8 @@ pltcl_event_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
 		Tcl_DStringAppendElement(&tcl_cmd, stroid);
 		pfree(stroid);
 
+		Tcl_DStringAppendElement(&tcl_cmd, tdata->operation);
+		Tcl_DStringAppendElement(&tcl_cmd, tdata->objecttype);
 		Tcl_DStringAppendElement(&tcl_cmd, tdata->schemaname);
 		Tcl_DStringAppendElement(&tcl_cmd, tdata->objectname);
 	}
@@ -1488,7 +1490,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid,
 		{
 			/* event trigger procedure has fixed args */
 			strcpy(proc_internal_args,
-				   "TG_when TG_tag TG_objectid TG_schemaname TG_objectname");
+				   "TG_event TG_tag TG_objectid TG_operation TG_objecttype TG_schemaname TG_objectname");
 		}
 
 		/************************************************************
diff --git a/src/pl/tcl/sql/pltcl_setup.sql b/src/pl/tcl/sql/pltcl_setup.sql
index 864e23b..2cb4839 100644
--- a/src/pl/tcl/sql/pltcl_setup.sql
+++ b/src/pl/tcl/sql/pltcl_setup.sql
@@ -560,9 +560,9 @@ $$ language pltcl immutable;
 select tcl_date_week(2010,1,24);
 select tcl_date_week(2001,10,24);
 
--- test pltcl command triggers
+-- test pltcl event triggers
 create or replace function tclsnitch() returns event_trigger language pltcl as $$
-  elog NOTICE " tclsnitch: $TG_when $TG_tag $TG_schemaname $TG_objectname"
+  elog NOTICE " tclsnitch: $TG_event $TG_tag $TG_schemaname $TG_objectname"
 $$;
 
 create event trigger tcl_snitch on command_start execute procedure tclsnitch();
diff --git a/src/test/regress/expected/event_triggers.out b/src/test/regress/expected/event_triggers.out
index 415605b..687d1c2 100644
--- a/src/test/regress/expected/event_triggers.out
+++ b/src/test/regress/expected/event_triggers.out
@@ -7,12 +7,9 @@ create or replace function snitch()
 as $$
 begin
   -- can't output tg_objectid here that would break pg_regress
-  raise notice 'snitch: % % %.%', tg_when, tg_tag, tg_schemaname, tg_objectname;
+  raise notice 'snitch: % % [% - %]', tg_event, tg_tag, tg_operation, tg_objecttype;
 end;
 $$;
---
--- TODO: REASSIGN OWNED and DROP OWNED
---
 create event trigger any_t on command_start
    execute procedure snitch();
 create event trigger foo_t on command_start
@@ -62,212 +59,216 @@ alter event trigger foo_t disable;
 alter event trigger foo_t enable;
 alter event trigger foo_t rename to snitch;
 create schema cmd;
-NOTICE:  snitch: command_start CREATE SCHEMA <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE SCHEMA <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE SCHEMA [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE SCHEMA [CREATE - <NULL>]
 create schema cmd2;
-NOTICE:  snitch: command_start CREATE SCHEMA <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE SCHEMA <NULL>.<NULL>
-create role regbob;
-alter event trigger snitch owner to regbob;
+NOTICE:  snitch: command_start CREATE SCHEMA [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE SCHEMA [CREATE - <NULL>]
+create role regression_bob;
+alter event trigger snitch owner to regression_bob;
+ERROR:  permission denied to change owner of event trigger "snitch"
+HINT:  The owner of an event trigger must be a superuser.
+alter role regression_bob superuser;
+alter event trigger snitch owner to regression_bob;
 create table cmd.foo(id bigserial primary key);
-NOTICE:  snitch: command_start CREATE TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE INDEX <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE TABLE [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE TABLE [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE SEQUENCE [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE SEQUENCE [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE INDEX [CREATE - <NULL>]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
 create view cmd.v as select * from cmd.foo;
-NOTICE:  snitch: command_start CREATE VIEW <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE VIEW <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE VIEW [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE VIEW [CREATE - <NULL>]
 alter table cmd.foo add column t text;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 create table cmd.bar as select 1;
-NOTICE:  snitch: command_start CREATE TABLE AS <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE TABLE AS <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE TABLE AS [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE TABLE AS [CREATE - <NULL>]
 drop table cmd.bar;
-NOTICE:  snitch: command_start DROP TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start DROP TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP TABLE [DROP - TABLE]
+NOTICE:  snitch: command_start DROP TABLE [DROP - TABLE]
 select 1 into cmd.bar;
-NOTICE:  snitch: command_start SELECT INTO <NULL>.<NULL>
-NOTICE:  snitch: command_start SELECT INTO <NULL>.<NULL>
+NOTICE:  snitch: command_start SELECT INTO [<NULL> - <NULL>]
+NOTICE:  snitch: command_start SELECT INTO [<NULL> - <NULL>]
 drop table cmd.bar;
-NOTICE:  snitch: command_start DROP TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start DROP TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP TABLE [DROP - TABLE]
+NOTICE:  snitch: command_start DROP TABLE [DROP - TABLE]
 create table test9 (id int, stuff text);
-NOTICE:  snitch: command_start CREATE TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE TABLE [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE TABLE [CREATE - <NULL>]
 alter table test9 rename to test;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - TABLE]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - TABLE]
 alter table test set schema cmd;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - TABLE]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - TABLE]
 alter table cmd.test rename column stuff to things;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - COLUMN]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - COLUMN]
 alter table cmd.test add column alpha text;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test alter column alpha set data type varchar(300);
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test alter column alpha set default 'test';
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test alter column alpha drop default;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test alter column alpha set statistics 78;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test alter column alpha set storage plain;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test alter column alpha set not null;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test alter column alpha drop not null;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test alter column alpha set (n_distinct = -0.78);
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test alter column alpha reset (n_distinct);
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test drop column alpha;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test add check (id > 2) not valid;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test add check (id < 800000);
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test set without cluster;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test set with oids;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 alter table cmd.test set without oids;
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TABLE [ALTER - <NULL>]
 create sequence test_seq_;
-NOTICE:  snitch: command_start CREATE SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE SEQUENCE <NULL>.<NULL>
-alter sequence test_seq_ owner to regbob;
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE SEQUENCE [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE SEQUENCE [CREATE - <NULL>]
+alter sequence test_seq_ owner to regression_bob;
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
 alter sequence test_seq_ rename to test_seq;
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - SEQUENCE]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - SEQUENCE]
 alter sequence test_seq set schema cmd;
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - SEQUENCE]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - SEQUENCE]
 alter sequence cmd.test_seq start with 3;
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
 alter sequence cmd.test_seq restart with 4;
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
 alter sequence cmd.test_seq minvalue 3;
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
 alter sequence cmd.test_seq no minvalue;
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
 alter sequence cmd.test_seq maxvalue 900000;
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
 alter sequence cmd.test_seq no maxvalue;
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
 alter sequence cmd.test_seq cache 876;
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
 alter sequence cmd.test_seq cycle;
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
 alter sequence cmd.test_seq no cycle;
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SEQUENCE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER SEQUENCE [ALTER - <NULL>]
 create view view_test as select id, things from cmd.test;
-NOTICE:  snitch: command_start CREATE VIEW <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE VIEW <NULL>.<NULL>
-alter view view_test owner to regbob;
-NOTICE:  snitch: command_start ALTER VIEW <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER VIEW <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE VIEW [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE VIEW [CREATE - <NULL>]
+alter view view_test owner to regression_bob;
+NOTICE:  snitch: command_start ALTER VIEW [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER VIEW [ALTER - <NULL>]
 alter view view_test rename to view_test2;
-NOTICE:  snitch: command_start ALTER VIEW <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER VIEW <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER VIEW [ALTER - VIEW]
+NOTICE:  snitch: command_start ALTER VIEW [ALTER - VIEW]
 alter view view_test2 set schema cmd;
-NOTICE:  snitch: command_start ALTER VIEW <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER VIEW <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER VIEW [ALTER - VIEW]
+NOTICE:  snitch: command_start ALTER VIEW [ALTER - VIEW]
 alter view cmd.view_test2 alter column id set default 9;
-NOTICE:  snitch: command_start ALTER VIEW <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER VIEW <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER VIEW [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER VIEW [ALTER - <NULL>]
 alter view cmd.view_test2 alter column id drop default;
-NOTICE:  snitch: command_start ALTER VIEW <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER VIEW <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER VIEW [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER VIEW [ALTER - <NULL>]
 cluster cmd.foo using foo_pkey;
-NOTICE:  snitch: command_start CLUSTER <NULL>.<NULL>
+NOTICE:  snitch: command_start CLUSTER [<NULL> - <NULL>]
 vacuum cmd.foo;
-NOTICE:  snitch: command_start VACUUM <NULL>.<NULL>
-NOTICE:  snitch: command_start VACUUM <NULL>.<NULL>
+NOTICE:  snitch: command_start VACUUM [<NULL> - <NULL>]
+NOTICE:  snitch: command_start VACUUM [<NULL> - <NULL>]
 vacuum;
-NOTICE:  snitch: command_start VACUUM <NULL>.<NULL>
-NOTICE:  snitch: command_start VACUUM <NULL>.<NULL>
+NOTICE:  snitch: command_start VACUUM [<NULL> - <NULL>]
+NOTICE:  snitch: command_start VACUUM [<NULL> - <NULL>]
 reindex table cmd.foo;
-NOTICE:  snitch: command_start REINDEX <NULL>.<NULL>
-NOTICE:  snitch: command_start REINDEX <NULL>.<NULL>
+NOTICE:  snitch: command_start REINDEX [<NULL> - <NULL>]
+NOTICE:  snitch: command_start REINDEX [<NULL> - <NULL>]
 set session_replication_role to replica;
 create table cmd.bar();
-NOTICE:  snitch: command_start CREATE TABLE <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE TABLE <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE TABLE [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE TABLE [CREATE - <NULL>]
 reset session_replication_role;
 create index idx_foo on cmd.foo(t);
-NOTICE:  snitch: command_start CREATE INDEX <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE INDEX [CREATE - <NULL>]
 reindex index cmd.idx_foo;
-NOTICE:  snitch: command_start REINDEX <NULL>.<NULL>
-NOTICE:  snitch: command_start REINDEX <NULL>.<NULL>
+NOTICE:  snitch: command_start REINDEX [<NULL> - <NULL>]
+NOTICE:  snitch: command_start REINDEX [<NULL> - <NULL>]
 drop index cmd.idx_foo;
-NOTICE:  snitch: command_start DROP INDEX <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP INDEX [DROP - INDEX]
 create function fun(int) returns text language sql
 as $$ select t from cmd.foo where id = $1; $$;
-NOTICE:  snitch: command_start CREATE FUNCTION <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE FUNCTION <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE FUNCTION [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE FUNCTION [CREATE - <NULL>]
 alter function fun(int) strict;
-NOTICE:  snitch: command_start ALTER FUNCTION <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER FUNCTION <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER FUNCTION [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER FUNCTION [ALTER - <NULL>]
 alter function fun(int) rename to notfun;
-NOTICE:  snitch: command_start ALTER FUNCTION <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER FUNCTION <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER FUNCTION [ALTER - FUNCTION]
+NOTICE:  snitch: command_start ALTER FUNCTION [ALTER - FUNCTION]
 alter function notfun(int) set schema cmd;
-NOTICE:  snitch: command_start ALTER FUNCTION <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER FUNCTION <NULL>.<NULL>
-alter function cmd.notfun(int) owner to regbob;
-NOTICE:  snitch: command_start ALTER FUNCTION <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER FUNCTION <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER FUNCTION [ALTER - FUNCTION]
+NOTICE:  snitch: command_start ALTER FUNCTION [ALTER - FUNCTION]
+alter function cmd.notfun(int) owner to regression_bob;
+NOTICE:  snitch: command_start ALTER FUNCTION [ALTER - FUNCTION]
+NOTICE:  snitch: command_start ALTER FUNCTION [ALTER - FUNCTION]
 alter function cmd.notfun(int) cost 77;
-NOTICE:  snitch: command_start ALTER FUNCTION <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER FUNCTION <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER FUNCTION [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER FUNCTION [ALTER - <NULL>]
 drop function cmd.notfun(int);
-NOTICE:  snitch: command_start DROP FUNCTION <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP FUNCTION [DROP - FUNCTION]
 create function cmd.plus1(int) returns bigint language sql
 as $$ select $1::bigint + 1; $$;
-NOTICE:  snitch: command_start CREATE FUNCTION <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE FUNCTION <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE FUNCTION [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE FUNCTION [CREATE - <NULL>]
 create operator cmd.+!(procedure = cmd.plus1, leftarg = int);
-NOTICE:  snitch: command_start CREATE OPERATOR <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE OPERATOR <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE OPERATOR [CREATE - OPERATOR]
+NOTICE:  snitch: command_start CREATE OPERATOR [CREATE - OPERATOR]
 alter operator cmd.+!(int, NONE) set schema public;
-NOTICE:  snitch: command_start ALTER OPERATOR <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER OPERATOR <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER OPERATOR [ALTER - OPERATOR]
+NOTICE:  snitch: command_start ALTER OPERATOR [ALTER - OPERATOR]
 drop operator public.+!(int, NONE);
-NOTICE:  snitch: command_start DROP OPERATOR <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP OPERATOR [DROP - OPERATOR]
 create aggregate cmd.avg (float8)
 (
     sfunc = float8_accum,
@@ -275,130 +276,130 @@ create aggregate cmd.avg (float8)
     finalfunc = float8_avg,
     initcond = '{0,0,0}'
 );
-NOTICE:  snitch: command_start CREATE AGGREGATE <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE AGGREGATE <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE AGGREGATE [CREATE - AGGREGATE]
+NOTICE:  snitch: command_start CREATE AGGREGATE [CREATE - AGGREGATE]
 alter aggregate cmd.avg(float8) set schema public;
-NOTICE:  snitch: command_start ALTER AGGREGATE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER AGGREGATE [ALTER - AGGREGATE]
 drop aggregate public.avg(float8);
-NOTICE:  snitch: command_start DROP AGGREGATE <NULL>.<NULL>
-NOTICE:  snitch: command_start DROP AGGREGATE <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP AGGREGATE [DROP - AGGREGATE]
+NOTICE:  snitch: command_start DROP AGGREGATE [DROP - AGGREGATE]
 create collation cmd.french (LOCALE = 'fr_FR');
-NOTICE:  snitch: command_start CREATE COLLATION <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE COLLATION <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE COLLATION [CREATE - COLLATION]
+NOTICE:  snitch: command_start CREATE COLLATION [CREATE - COLLATION]
 alter collation cmd.french rename to francais;
-NOTICE:  snitch: command_start ALTER COLLATION <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER COLLATION <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER COLLATION [ALTER - COLLATION]
+NOTICE:  snitch: command_start ALTER COLLATION [ALTER - COLLATION]
 create type cmd.compfoo AS (f1 int, f2 text);
-NOTICE:  snitch: command_start CREATE TYPE <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE TYPE <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE TYPE [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE TYPE [CREATE - <NULL>]
 alter type cmd.compfoo add attribute f3 text;
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - <NULL>]
 create type cmd.type_test AS (a integer, b integer, c text);
-NOTICE:  snitch: command_start CREATE TYPE <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE TYPE <NULL>.<NULL>
-alter type cmd.type_test owner to regbob;
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE TYPE [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE TYPE [CREATE - <NULL>]
+alter type cmd.type_test owner to regression_bob;
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - TYPE]
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - TYPE]
 alter type cmd.type_test rename to type_test2;
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - TYPE]
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - TYPE]
 alter type cmd.type_test2 set schema public;
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - TYPE]
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - TYPE]
 alter type public.type_test2 rename attribute a to z;
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - ATTRIBUTE]
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - ATTRIBUTE]
 alter type public.type_test2 add attribute alpha text;
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - <NULL>]
 alter type public.type_test2 alter attribute alpha set data type char(90);
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - <NULL>]
 alter type public.type_test2 drop attribute alpha;
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - <NULL>]
 drop type cmd.compfoo;
-NOTICE:  snitch: command_start DROP TYPE <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP TYPE [DROP - TYPE]
 drop type public.type_test2;
-NOTICE:  snitch: command_start DROP TYPE <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP TYPE [DROP - TYPE]
 create type cmd.bug_status as enum ('new', 'open', 'closed');
-NOTICE:  snitch: command_start CREATE TYPE <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE TYPE <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE TYPE [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE TYPE [CREATE - <NULL>]
 alter type cmd.bug_status add value 'wontfix';
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TYPE <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER TYPE [ALTER - <NULL>]
 create domain cmd.us_postal_code as text check(value ~ '^\d{5}$' or value ~ '^\d{5}-\d{4}$');
-NOTICE:  snitch: command_start CREATE DOMAIN <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE DOMAIN <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE DOMAIN [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE DOMAIN [CREATE - <NULL>]
 alter domain cmd.us_postal_code set not null;
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - <NULL>]
 alter domain cmd.us_postal_code set default 90210;
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - <NULL>]
 alter domain cmd.us_postal_code drop default;
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - <NULL>]
 alter domain cmd.us_postal_code drop not null;
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - <NULL>]
 alter domain cmd.us_postal_code add constraint dummy_constraint check (value ~ '^\d{8}$');
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - <NULL>]
 alter domain cmd.us_postal_code drop constraint dummy_constraint;
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
-alter domain cmd.us_postal_code owner to regbob;
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - <NULL>]
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - <NULL>]
+alter domain cmd.us_postal_code owner to regression_bob;
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - DOMAIN]
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - DOMAIN]
 alter domain cmd.us_postal_code set schema cmd2;
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER DOMAIN <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - DOMAIN]
+NOTICE:  snitch: command_start ALTER DOMAIN [ALTER - DOMAIN]
 drop domain cmd2.us_postal_code;
-NOTICE:  snitch: command_start DROP DOMAIN <NULL>.<NULL>
-NOTICE:  snitch: command_start DROP DOMAIN <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP DOMAIN [DROP - DOMAIN]
+NOTICE:  snitch: command_start DROP DOMAIN [DROP - DOMAIN]
 create function cmd.trigfunc() returns trigger language plpgsql as
 $$ begin raise notice 'trigfunc';  end;$$;
-NOTICE:  snitch: command_start CREATE FUNCTION <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE FUNCTION <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE FUNCTION [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE FUNCTION [CREATE - <NULL>]
 create trigger footg before update on cmd.foo for each row execute procedure cmd.trigfunc();
-NOTICE:  snitch: command_start CREATE TRIGGER <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE TRIGGER <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE TRIGGER [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE TRIGGER [CREATE - <NULL>]
 alter trigger footg on cmd.foo rename to foo_trigger;
-NOTICE:  snitch: command_start ALTER TRIGGER <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER TRIGGER <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TRIGGER [ALTER - TRIGGER]
+NOTICE:  snitch: command_start ALTER TRIGGER [ALTER - TRIGGER]
 drop trigger foo_trigger on cmd.foo;
-NOTICE:  snitch: command_start DROP TRIGGER <NULL>.<NULL>
-NOTICE:  snitch: command_start DROP TRIGGER <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP TRIGGER [DROP - TRIGGER]
+NOTICE:  snitch: command_start DROP TRIGGER [DROP - TRIGGER]
 create conversion test for 'utf8' to 'sjis' from utf8_to_sjis;
-NOTICE:  snitch: command_start CREATE CONVERSION <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE CONVERSION [CREATE - <NULL>]
 create default conversion test2 for 'utf8' to 'sjis' from utf8_to_sjis;
-NOTICE:  snitch: command_start CREATE CONVERSION <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE CONVERSION [CREATE - <NULL>]
 alter conversion test2 rename to test3;
-NOTICE:  snitch: command_start ALTER CONVERSION <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER CONVERSION <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER CONVERSION [ALTER - CONVERSION]
+NOTICE:  snitch: command_start ALTER CONVERSION [ALTER - CONVERSION]
 drop conversion test3;
-NOTICE:  snitch: command_start DROP CONVERSION <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP CONVERSION [DROP - CONVERSION]
 drop conversion test;
-NOTICE:  snitch: command_start DROP CONVERSION <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP CONVERSION [DROP - CONVERSION]
 create operator class test_op_class
    for type anyenum using hash as
    operator 1  =,
    function 1  hashenum(anyenum);
-NOTICE:  snitch: command_start CREATE OPERATOR CLASS <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE OPERATOR CLASS <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE OPERATOR CLASS [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE OPERATOR CLASS [CREATE - <NULL>]
 create text search configuration test (parser = "default");
-NOTICE:  snitch: command_start CREATE TEXT SEARCH CONFIGURATION <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE TEXT SEARCH CONFIGURATION <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE TEXT SEARCH CONFIGURATION [CREATE - TEXT SEARCH CONFIGURATION]
+NOTICE:  snitch: command_start CREATE TEXT SEARCH CONFIGURATION [CREATE - TEXT SEARCH CONFIGURATION]
 create text search dictionary test_stem (
    template = snowball,
    language = 'english', stopwords = 'english'
 );
-NOTICE:  snitch: command_start CREATE TEXT SEARCH DICTIONARY <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE TEXT SEARCH DICTIONARY <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE TEXT SEARCH DICTIONARY [CREATE - TEXT SEARCH DICTIONARY]
+NOTICE:  snitch: command_start CREATE TEXT SEARCH DICTIONARY [CREATE - TEXT SEARCH DICTIONARY]
 alter text search dictionary test_stem (StopWords = dutch );
-NOTICE:  snitch: command_start ALTER TEXT SEARCH DICTIONARY <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER TEXT SEARCH DICTIONARY [ALTER - <NULL>]
 create text search parser test_parser (
   start = prsd_start,
   gettoken = prsd_nexttoken,
@@ -406,38 +407,38 @@ create text search parser test_parser (
   lextypes = prsd_lextype,
   headline = prsd_headline
 );
-NOTICE:  snitch: command_start CREATE TEXT SEARCH PARSER <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE TEXT SEARCH PARSER <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE TEXT SEARCH PARSER [CREATE - TEXT SEARCH PARSER]
+NOTICE:  snitch: command_start CREATE TEXT SEARCH PARSER [CREATE - TEXT SEARCH PARSER]
 create text search template test_template (
   init = dsimple_init,
   lexize = dsimple_lexize
 );
-NOTICE:  snitch: command_start CREATE TEXT SEARCH TEMPLATE <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE TEXT SEARCH TEMPLATE <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE TEXT SEARCH TEMPLATE [CREATE - TEXT SEARCH TEMPLATE]
+NOTICE:  snitch: command_start CREATE TEXT SEARCH TEMPLATE [CREATE - TEXT SEARCH TEMPLATE]
 drop text search configuration test;
-NOTICE:  snitch: command_start DROP TEXT SEARCH CONFIGURATION <NULL>.<NULL>
-NOTICE:  snitch: command_start DROP TEXT SEARCH CONFIGURATION <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP TEXT SEARCH CONFIGURATION [DROP - TEXT SEARCH CONFIGURATION]
+NOTICE:  snitch: command_start DROP TEXT SEARCH CONFIGURATION [DROP - TEXT SEARCH CONFIGURATION]
 drop text search dictionary test_stem;
-NOTICE:  snitch: command_start DROP TEXT SEARCH DICTIONARY <NULL>.<NULL>
-NOTICE:  snitch: command_start DROP TEXT SEARCH DICTIONARY <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP TEXT SEARCH DICTIONARY [DROP - TEXT SEARCH DICTIONARY]
+NOTICE:  snitch: command_start DROP TEXT SEARCH DICTIONARY [DROP - TEXT SEARCH DICTIONARY]
 drop text search parser test_parser;
-NOTICE:  snitch: command_start DROP TEXT SEARCH PARSER <NULL>.<NULL>
-NOTICE:  snitch: command_start DROP TEXT SEARCH PARSER <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP TEXT SEARCH PARSER [DROP - TEXT SEARCH PARSER]
+NOTICE:  snitch: command_start DROP TEXT SEARCH PARSER [DROP - TEXT SEARCH PARSER]
 drop text search template test_template;
-NOTICE:  snitch: command_start DROP TEXT SEARCH TEMPLATE <NULL>.<NULL>
-NOTICE:  snitch: command_start DROP TEXT SEARCH TEMPLATE <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP TEXT SEARCH TEMPLATE [DROP - TEXT SEARCH TEMPLATE]
+NOTICE:  snitch: command_start DROP TEXT SEARCH TEMPLATE [DROP - TEXT SEARCH TEMPLATE]
 create function cmd.testcast(text) returns int4  language plpgsql as $$begin return 4::int4;end;$$;
-NOTICE:  snitch: command_start CREATE FUNCTION <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE FUNCTION <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE FUNCTION [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE FUNCTION [CREATE - <NULL>]
 create cast (text as int4) with function cmd.testcast(text) as assignment;
-NOTICE:  snitch: command_start CREATE CAST <NULL>.<NULL>
-NOTICE:  snitch: command_start CREATE CAST <NULL>.<NULL>
+NOTICE:  snitch: command_start CREATE CAST [CREATE - <NULL>]
+NOTICE:  snitch: command_start CREATE CAST [CREATE - <NULL>]
 alter schema cmd rename to cmd1;
-NOTICE:  snitch: command_start ALTER SCHEMA <NULL>.<NULL>
-NOTICE:  snitch: command_start ALTER SCHEMA <NULL>.<NULL>
+NOTICE:  snitch: command_start ALTER SCHEMA [ALTER - SCHEMA]
+NOTICE:  snitch: command_start ALTER SCHEMA [ALTER - SCHEMA]
 drop schema cmd1 cascade;
-NOTICE:  snitch: command_start DROP SCHEMA <NULL>.<NULL>
-NOTICE:  snitch: command_start DROP SCHEMA <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP SCHEMA [DROP - SCHEMA]
+NOTICE:  snitch: command_start DROP SCHEMA [DROP - SCHEMA]
 NOTICE:  drop cascades to 12 other objects
 DETAIL:  drop cascades to table cmd1.foo
 drop cascades to view cmd1.v
@@ -452,15 +453,17 @@ drop cascades to function cmd1.trigfunc()
 drop cascades to function cmd1.testcast(text)
 drop cascades to cast from text to integer
 drop schema cmd2 cascade;
-NOTICE:  snitch: command_start DROP SCHEMA <NULL>.<NULL>
-NOTICE:  snitch: command_start DROP SCHEMA <NULL>.<NULL>
+NOTICE:  snitch: command_start DROP SCHEMA [DROP - SCHEMA]
+NOTICE:  snitch: command_start DROP SCHEMA [DROP - SCHEMA]
 -- fail because owning event trigger snitch
-drop role regbob;
-ERROR:  role "regbob" cannot be dropped because some objects depend on it
+drop role regression_bob;
+ERROR:  role "regression_bob" cannot be dropped because some objects depend on it
 DETAIL:  owner of event trigger snitch
 drop event trigger any_t;
-drop event trigger snitch;
-drop role regbob;
+drop event trigger if exists snitch;
+drop event trigger if exists snitch;
+NOTICE:  event trigger "snitch" does not exist, skipping
+drop role regression_bob;
 create table onerow(id integer);
 create or replace function insert_one_row()
  returns event_trigger
diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out
index 0dac40f..70eab92 100644
--- a/src/test/regress/expected/type_sanity.out
+++ b/src/test/regress/expected/type_sanity.out
@@ -134,11 +134,10 @@ WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
     (p1.typelem != 0 AND p1.typlen < 0) AND NOT
     (p2.prorettype = p1.oid AND NOT p2.proretset)
 ORDER BY 1;
- oid  |    typname    | oid  |  proname   
-------+---------------+------+------------
- 1790 | refcursor     |   46 | textin
- 3838 | event_trigger | 2300 | trigger_in
-(2 rows)
+ oid  |  typname  | oid | proname 
+------+-----------+-----+---------
+ 1790 | refcursor |  46 | textin
+(1 row)
 
 -- Varlena array types will point to array_in
 -- Exception as of 8.1: int2vector and oidvector have their own I/O routines
@@ -178,11 +177,10 @@ WHERE p1.typoutput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
       (p2.oid = 'array_out'::regproc AND
        p1.typelem != 0 AND p1.typlen = -1)))
 ORDER BY 1;
- oid  |    typname    | oid  |   proname   
-------+---------------+------+-------------
- 1790 | refcursor     |   47 | textout
- 3838 | event_trigger | 2301 | trigger_out
-(2 rows)
+ oid  |  typname  | oid | proname 
+------+-----------+-----+---------
+ 1790 | refcursor |  47 | textout
+(1 row)
 
 SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
diff --git a/src/test/regress/sql/event_triggers.sql b/src/test/regress/sql/event_triggers.sql
index cf25ee7..9ca1a28 100644
--- a/src/test/regress/sql/event_triggers.sql
+++ b/src/test/regress/sql/event_triggers.sql
@@ -7,14 +7,10 @@ create or replace function snitch()
 as $$
 begin
   -- can't output tg_objectid here that would break pg_regress
-  raise notice 'snitch: % % %.%', tg_when, tg_tag, tg_schemaname, tg_objectname;
+  raise notice 'snitch: % % [% - %]', tg_event, tg_tag, tg_operation, tg_objecttype;
 end;
 $$;
 
---
--- TODO: REASSIGN OWNED and DROP OWNED
---
-
 create event trigger any_t on command_start
    execute procedure snitch();
 
@@ -68,9 +64,11 @@ alter event trigger foo_t rename to snitch;
 
 create schema cmd;
 create schema cmd2;
-create role regbob;
 
-alter event trigger snitch owner to regbob;
+create role regression_bob;
+alter event trigger snitch owner to regression_bob;
+alter role regression_bob superuser;
+alter event trigger snitch owner to regression_bob;
 
 create table cmd.foo(id bigserial primary key);
 create view cmd.v as select * from cmd.foo;
@@ -103,7 +101,7 @@ alter table cmd.test set with oids;
 alter table cmd.test set without oids;
 
 create sequence test_seq_;
-alter sequence test_seq_ owner to regbob;
+alter sequence test_seq_ owner to regression_bob;
 alter sequence test_seq_ rename to test_seq;
 alter sequence test_seq set schema cmd;
 alter sequence cmd.test_seq start with 3;
@@ -117,7 +115,7 @@ alter sequence cmd.test_seq cycle;
 alter sequence cmd.test_seq no cycle;
 
 create view view_test as select id, things from cmd.test;
-alter view view_test owner to regbob;
+alter view view_test owner to regression_bob;
 alter view view_test rename to view_test2;
 alter view view_test2 set schema cmd;
 alter view cmd.view_test2 alter column id set default 9;
@@ -142,7 +140,7 @@ as $$ select t from cmd.foo where id = $1; $$;
 alter function fun(int) strict;
 alter function fun(int) rename to notfun;
 alter function notfun(int) set schema cmd;
-alter function cmd.notfun(int) owner to regbob;
+alter function cmd.notfun(int) owner to regression_bob;
 alter function cmd.notfun(int) cost 77;
 drop function cmd.notfun(int);
 
@@ -170,7 +168,7 @@ create type cmd.compfoo AS (f1 int, f2 text);
 alter type cmd.compfoo add attribute f3 text;
 
 create type cmd.type_test AS (a integer, b integer, c text);
-alter type cmd.type_test owner to regbob;
+alter type cmd.type_test owner to regression_bob;
 alter type cmd.type_test rename to type_test2;
 alter type cmd.type_test2 set schema public;
 alter type public.type_test2 rename attribute a to z;
@@ -191,7 +189,7 @@ alter domain cmd.us_postal_code drop default;
 alter domain cmd.us_postal_code drop not null;
 alter domain cmd.us_postal_code add constraint dummy_constraint check (value ~ '^\d{8}$');
 alter domain cmd.us_postal_code drop constraint dummy_constraint;
-alter domain cmd.us_postal_code owner to regbob;
+alter domain cmd.us_postal_code owner to regression_bob;
 alter domain cmd.us_postal_code set schema cmd2;
 drop domain cmd2.us_postal_code;
 
@@ -248,11 +246,12 @@ drop schema cmd1 cascade;
 drop schema cmd2 cascade;
 
 -- fail because owning event trigger snitch
-drop role regbob;
+drop role regression_bob;
 
 drop event trigger any_t;
-drop event trigger snitch;
-drop role regbob;
+drop event trigger if exists snitch;
+drop event trigger if exists snitch;
+drop role regression_bob;
 
 create table onerow(id integer);