From 2504a2ff914fe7cbe971a2ca6a9bc36aa9e62698 Mon Sep 17 00:00:00 2001
From: Wang Wei <wangw.fnst@fujitsu.com>
Date: Mon, 24 Apr 2023 17:02:30 +0800
Subject: [PATCH 2/8] Enhance the event trigger to support DDL deparsing

1) ALTER TABLE can have multiple subcommands which might include DROP COLUMN
command and ALTER TYPE referring the drop column in USING expression. As the
dropped column cannot be accessed after the execution of DROP COLUMN, a special
trigger is added to handle this case before the drop column is executed.

2) For CREATE TABLE AS, to avoid the need to ensure all the objects referenced
in the subquery also exists in subscriber, deprase the CREATE TABLE AS into a
simple CREATE TABLE(without subquery) command and WAL log it after creating the
table and before writing data into the table and replicate the incoming writes
later as normal INSERTs. This approach works for all kind of commands(e.g.
CRAETE TABLE AS [SELECT][EXECUTE][VALUES]).

To achieve this, introduce a new type of event trigger "table_init_write".
which would be fired for CREATE TABLE/CREATE TABLE AS/SELECT INTO after
creating the table and before any other modification. we deparse the command in
the table_init_write event trigger and WAL log the deparsed json string. The
walsender will send the string to subscriber. And incoming INSERTs will also be
replicated.
---
 doc/src/sgml/event-trigger.sgml      | 133 +++++++++-
 src/backend/commands/createas.c      |  10 +
 src/backend/commands/ddldeparse.c    |  37 ++-
 src/backend/commands/event_trigger.c | 350 +++++++++++++++++++++++----
 src/backend/commands/tablecmds.c     |  10 +-
 src/backend/tcop/utility.c           |   3 +
 src/backend/utils/cache/evtcache.c   |   2 +
 src/include/commands/event_trigger.h |  50 +++-
 src/include/tcop/deparse_utility.h   |  12 +-
 src/include/utils/evtcache.h         |   3 +-
 10 files changed, 542 insertions(+), 68 deletions(-)

diff --git a/doc/src/sgml/event-trigger.sgml b/doc/src/sgml/event-trigger.sgml
index 3b6a5361b3..a349433819 100644
--- a/doc/src/sgml/event-trigger.sgml
+++ b/doc/src/sgml/event-trigger.sgml
@@ -30,7 +30,8 @@
      supported events are
      <literal>ddl_command_start</literal>,
      <literal>ddl_command_end</literal>,
-     <literal>table_rewrite</literal>
+     <literal>table_rewrite</literal>,
+     <literal>table_init_write</literal>
      and <literal>sql_drop</literal>.
      Support for additional events may be added in future releases.
    </para>
@@ -82,16 +83,22 @@
     the <literal>table_rewrite</literal> event is not triggered by them.
    </para>
 
+   <para>
+    The <literal>table_init_write</literal> event occurs just after the creation of
+    table while execution of <literal>CREATE TABLE AS</literal> and
+    <literal>SELECT INTO</literal> commands.
+   </para>
+
    <para>
      Event triggers (like other functions) cannot be executed in an aborted
      transaction.  Thus, if a DDL command fails with an error, any associated
      <literal>ddl_command_end</literal> triggers will not be executed.  Conversely,
      if a <literal>ddl_command_start</literal> trigger fails with an error, no
      further event triggers will fire, and no attempt will be made to execute
-     the command itself.  Similarly, if a <literal>ddl_command_end</literal> trigger
-     fails with an error, the effects of the DDL statement will be rolled
-     back, just as they would be in any other case where the containing
-     transaction aborts.
+     the command itself.  Similarly, if a <literal>ddl_command_end</literal> or
+     <literal>table_init_write</literal> trigger fails with an error, the effects
+     of the DDL statement will be rolled back, just as they would be in any other
+     case where the containing transaction aborts.
    </para>
 
    <para>
@@ -138,6 +145,7 @@
       <colspec colname="col4" colwidth="1*"/>
       <colspec colname="col5" colwidth="1*"/>
       <colspec colname="col6" colwidth="1*"/>
+      <colspec colname="col7" colwidth="1*"/>
       <thead>
        <row>
         <entry>Command Tag</entry>
@@ -145,6 +153,7 @@
         <entry><literal>ddl_&zwsp;command_&zwsp;end</literal></entry>
         <entry><literal>sql_&zwsp;drop</literal></entry>
         <entry><literal>table_&zwsp;rewrite</literal></entry>
+        <entry><literal>table_&zwsp;init_&zwsp;write</literal></entry>
         <entry>Notes</entry>
        </row>
       </thead>
@@ -155,6 +164,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -163,6 +173,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -171,6 +182,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -179,6 +191,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -187,6 +200,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -195,6 +209,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -203,6 +218,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -211,6 +227,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -219,6 +236,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -227,6 +245,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -235,6 +254,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -243,6 +263,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>X</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -251,6 +272,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -259,6 +281,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -267,6 +290,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -275,6 +299,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -283,6 +308,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -291,6 +317,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -299,6 +326,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -307,6 +335,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -315,6 +344,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -323,6 +353,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -331,6 +362,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -339,6 +371,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -347,6 +380,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -355,6 +389,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -363,6 +398,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -371,6 +407,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -379,6 +416,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -387,6 +425,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -395,6 +434,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>X</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -403,6 +443,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -411,6 +452,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -419,6 +461,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left">Only for local objects</entry>
        </row>
        <row>
@@ -427,6 +470,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -435,6 +479,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -443,6 +488,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -451,6 +497,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -459,6 +506,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -467,6 +515,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -475,6 +524,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -483,6 +533,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -491,6 +542,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -499,6 +551,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -507,6 +560,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -515,6 +569,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -523,6 +578,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -531,6 +587,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -539,6 +596,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -547,6 +605,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -555,6 +614,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -563,6 +623,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -571,6 +632,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -579,6 +641,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -587,6 +650,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -595,6 +659,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -603,6 +668,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -611,6 +677,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -619,6 +686,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -627,6 +695,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -635,6 +704,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -643,6 +713,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -651,6 +722,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -659,6 +731,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -667,6 +740,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -675,6 +749,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -683,6 +758,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -691,6 +767,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -699,6 +776,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -707,6 +785,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -715,6 +794,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -723,6 +803,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -731,6 +812,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -739,6 +821,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -747,6 +830,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -755,6 +839,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -763,6 +848,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -771,6 +857,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -779,6 +866,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -787,6 +875,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -795,6 +884,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -803,6 +893,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -811,6 +902,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -819,6 +911,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -827,6 +920,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -835,6 +929,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -843,6 +938,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -851,6 +947,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -859,6 +956,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -867,6 +965,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -875,6 +974,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -883,6 +983,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -891,6 +992,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -899,6 +1001,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -907,6 +1010,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -915,6 +1019,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -923,6 +1028,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -931,6 +1037,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -939,6 +1046,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -947,6 +1055,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -955,6 +1064,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -963,6 +1073,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -971,6 +1082,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -979,6 +1091,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -987,6 +1100,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -995,6 +1109,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left">Only for local objects</entry>
        </row>
        <row>
@@ -1003,6 +1118,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -1011,6 +1127,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left"></entry>
        </row>
        <row>
@@ -1019,6 +1136,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left">Only for local objects</entry>
        </row>
        <row>
@@ -1027,6 +1145,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
         <entry align="left">Only for local objects</entry>
        </row>
        <row>
@@ -1035,6 +1154,7 @@
         <entry align="center"><literal>X</literal></entry>
         <entry align="center"><literal>-</literal></entry>
         <entry align="center"><literal>-</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
         <entry align="left"></entry>
        </row>
       </tbody>
@@ -1118,7 +1238,8 @@ typedef struct EventTriggerData
        <para>
         Describes the event for which the function is called, one of
         <literal>"ddl_command_start"</literal>, <literal>"ddl_command_end"</literal>,
-        <literal>"sql_drop"</literal>, <literal>"table_rewrite"</literal>.
+        <literal>"sql_drop"</literal>, <literal>"table_rewrite"</literal>,
+        <literal>"table_init_write"</literal>.
         See <xref linkend="event-trigger-definition"/> for the meaning of these
         events.
        </para>
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index e91920ca14..a7b22cb5db 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -34,6 +34,7 @@
 #include "catalog/namespace.h"
 #include "catalog/toasting.h"
 #include "commands/createas.h"
+#include "commands/event_trigger.h"
 #include "commands/matview.h"
 #include "commands/prepare.h"
 #include "commands/tablecmds.h"
@@ -143,6 +144,15 @@ create_ctas_internal(List *attrList, IntoClause *into)
 		StoreViewQuery(intoRelationAddr.objectId, query, false);
 		CommandCounterIncrement();
 	}
+	else
+	{
+		/*
+		 * Fire the trigger for table_init_write after creating the table so
+		 * that we can access the catalog info about the newly created table
+		 * in the trigger function.
+		 */
+		EventTriggerTableInitWrite((Node *) create, intoRelationAddr);
+	}
 
 	return intoRelationAddr;
 }
diff --git a/src/backend/commands/ddldeparse.c b/src/backend/commands/ddldeparse.c
index 3eeaeee716..6a001acf41 100644
--- a/src/backend/commands/ddldeparse.c
+++ b/src/backend/commands/ddldeparse.c
@@ -1761,6 +1761,26 @@ deparse_CreateStmt(Oid objectId, Node *parsetree)
 	return ret;
 }
 
+/*
+ * Deparse CREATE TABLE AS command.
+ *
+ * deparse_CreateStmt do the actual work as we deparse the final CreateStmt for
+ * CREATE TABLE AS command.
+ */
+static ObjTree *
+deparse_CreateTableAsStmt(CollectedCommand *cmd)
+{
+	Oid			objectId;
+	Node	   *parsetree;
+
+	Assert(cmd->type == SCT_CreateTableAs);
+
+	parsetree = cmd->d.ctas.real_create;
+	objectId = cmd->d.ctas.address.objectId;
+
+	return deparse_CreateStmt(objectId, parsetree);
+}
+
 /*
  * Deparse all the collected subcommands and return an ObjTree representing the
  * alter command.
@@ -2188,20 +2208,8 @@ deparse_AlterRelation(CollectedCommand *cmd)
 					 */
 					tmp_obj2 = new_objtree("USING %{expression}s");
 					if (def->raw_default)
-					{
-						Datum		deparsed;
-						char	   *defexpr;
-						List	   *exprs = NIL;
-
-						exprs = lappend(exprs, def->cooked_default);
-						defexpr = nodeToString(def->cooked_default);
-						deparsed = DirectFunctionCall2(pg_get_expr,
-													   CStringGetTextDatum(defexpr),
-													   RelationGetRelid(rel));
-
 						append_string_object(tmp_obj2, "expression",
-											 TextDatumGetCString(deparsed));
-					}
+											 sub->usingexpr);
 					else
 						append_not_present(tmp_obj2);
 
@@ -2933,6 +2941,9 @@ deparse_utility_command(CollectedCommand *cmd)
 		case SCT_AlterTable:
 			tree = deparse_AlterRelation(cmd);
 			break;
+		case SCT_CreateTableAs:
+			tree = deparse_CreateTableAsStmt(cmd);
+			break;
 		default:
 			elog(ERROR, "unexpected deparse node type %d", cmd->type);
 	}
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index 4d48e490ed..8561c6fad0 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -36,6 +36,7 @@
 #include "lib/ilist.h"
 #include "miscadmin.h"
 #include "parser/parse_func.h"
+#include "parser/parser.h"
 #include "pgstat.h"
 #include "tcop/ddldeparse.h"
 #include "tcop/deparse_utility.h"
@@ -49,45 +50,7 @@
 #include "utils/rel.h"
 #include "utils/syscache.h"
 
-typedef struct EventTriggerQueryState
-{
-	/* memory context for this state's objects */
-	MemoryContext cxt;
-
-	/* sql_drop */
-	slist_head	SQLDropList;
-	bool		in_sql_drop;
-
-	/* table_rewrite */
-	Oid			table_rewrite_oid;	/* InvalidOid, or set for table_rewrite
-									 * event */
-	int			table_rewrite_reason;	/* AT_REWRITE reason */
-
-	/* Support for command collection */
-	bool		commandCollectionInhibited;
-	CollectedCommand *currentCommand;
-	List	   *commandList;	/* list of CollectedCommand; see
-								 * deparse_utility.h */
-	struct EventTriggerQueryState *previous;
-} EventTriggerQueryState;
-
-static EventTriggerQueryState *currentEventTriggerState = NULL;
-
-/* Support for dropped objects */
-typedef struct SQLDropObject
-{
-	ObjectAddress address;
-	const char *schemaname;
-	const char *objname;
-	const char *objidentity;
-	const char *objecttype;
-	List	   *addrnames;
-	List	   *addrargs;
-	bool		original;
-	bool		normal;
-	bool		istemp;
-	slist_node	next;
-} SQLDropObject;
+EventTriggerQueryState *currentEventTriggerState = NULL;
 
 static void AlterEventTriggerOwner_internal(Relation rel,
 											HeapTuple tup,
@@ -131,7 +94,8 @@ CreateEventTrigger(CreateEventTrigStmt *stmt)
 	if (strcmp(stmt->eventname, "ddl_command_start") != 0 &&
 		strcmp(stmt->eventname, "ddl_command_end") != 0 &&
 		strcmp(stmt->eventname, "sql_drop") != 0 &&
-		strcmp(stmt->eventname, "table_rewrite") != 0)
+		strcmp(stmt->eventname, "table_rewrite") != 0 &&
+		strcmp(stmt->eventname, "table_init_write") != 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("unrecognized event name \"%s\"",
@@ -157,7 +121,8 @@ CreateEventTrigger(CreateEventTrigStmt *stmt)
 	/* Validate tag list, if any. */
 	if ((strcmp(stmt->eventname, "ddl_command_start") == 0 ||
 		 strcmp(stmt->eventname, "ddl_command_end") == 0 ||
-		 strcmp(stmt->eventname, "sql_drop") == 0)
+		 strcmp(stmt->eventname, "sql_drop") == 0 ||
+		 strcmp(stmt->eventname, "table_init_write") == 0)
 		&& tags != NULL)
 		validate_ddl_tags("tag", tags);
 	else if (strcmp(stmt->eventname, "table_rewrite") == 0
@@ -583,7 +548,8 @@ EventTriggerCommonSetup(Node *parsetree,
 		dbgtag = CreateCommandTag(parsetree);
 		if (event == EVT_DDLCommandStart ||
 			event == EVT_DDLCommandEnd ||
-			event == EVT_SQLDrop)
+			event == EVT_SQLDrop ||
+			event == EVT_TableInitWrite)
 		{
 			if (!command_tag_event_trigger_ok(dbgtag))
 				elog(ERROR, "unexpected command tag \"%s\"", GetCommandTagName(dbgtag));
@@ -866,6 +832,153 @@ EventTriggerTableRewrite(Node *parsetree, Oid tableOid, int reason)
 	CommandCounterIncrement();
 }
 
+/*
+ * EventTriggerTableInitWriteStart
+ *     Prepare to receive data on an CREATE TABLE AS/SELECT INTO command about
+ *     to be executed.
+ */
+void
+EventTriggerTableInitWriteStart(Node *parsetree)
+{
+	MemoryContext oldcxt;
+	CollectedCommand *command;
+	CreateTableAsStmt *stmt = (CreateTableAsStmt *)parsetree;
+
+	/* ignore if event trigger context not set, or collection disabled */
+	if (!currentEventTriggerState ||
+		currentEventTriggerState->commandCollectionInhibited)
+		return;
+
+	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
+
+	command = palloc(sizeof(CollectedCommand));
+
+	command->type = (stmt->objtype == OBJECT_TABLE) ? SCT_CreateTableAs : SCT_Simple;
+	command->in_extension = creating_extension;
+	command->d.ctas.address = InvalidObjectAddress;
+	command->d.ctas.real_create = NULL;
+	command->parsetree = copyObject(parsetree);
+
+	command->parent = currentEventTriggerState->currentCommand;
+	currentEventTriggerState->currentCommand = command;
+
+	MemoryContextSwitchTo(oldcxt);
+}
+
+/*
+ * EventTriggerTableInitWriteEnd
+ *		Finish up saving an CREATE TABLE AS/SELECT INTO command.
+ *
+ * FIXME this API isn't considering the possibility that an xact/subxact is
+ * aborted partway through.  Probably it's best to add an
+ * AtEOSubXact_EventTriggers() to fix this.
+ */
+void
+EventTriggerTableInitWriteEnd(ObjectAddress address)
+{
+	CollectedCommand *parent;
+	CreateTableAsStmt *stmt;
+
+	/* ignore if event trigger context not set, or collection disabled */
+	if (!currentEventTriggerState ||
+		currentEventTriggerState->commandCollectionInhibited)
+		return;
+
+	Assert(currentEventTriggerState->currentCommand != NULL);
+
+	stmt =  (CreateTableAsStmt *)currentEventTriggerState->currentCommand->parsetree;
+
+	if (stmt->objtype == OBJECT_TABLE)
+	{
+		MemoryContext oldcxt;
+
+		parent = currentEventTriggerState->currentCommand->parent;
+
+		oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
+
+		currentEventTriggerState->commandList =
+			lappend(currentEventTriggerState->commandList,
+					currentEventTriggerState->currentCommand);
+
+		MemoryContextSwitchTo(oldcxt);
+
+		currentEventTriggerState->currentCommand = parent;
+	}
+	else
+	{
+		MemoryContext oldcxt;
+
+		oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
+
+		currentEventTriggerState->currentCommand->d.simple.address = address;
+		currentEventTriggerState->commandList =
+			lappend(currentEventTriggerState->commandList,
+					currentEventTriggerState->currentCommand);
+
+		MemoryContextSwitchTo(oldcxt);
+	}
+}
+
+/*
+ * Fire table_init_rewrite triggers.
+ */
+void
+EventTriggerTableInitWrite(Node *real_create, ObjectAddress address)
+{
+	List	   *runlist;
+	EventTriggerData trigdata;
+	CollectedCommand *command;
+	MemoryContext oldcxt;
+
+	/*
+	 * See EventTriggerDDLCommandStart for a discussion about why event
+	 * triggers are disabled in single user mode.
+	 */
+	if (!IsUnderPostmaster)
+		return;
+
+	/*
+	 * Also do nothing if our state isn't set up, which it won't be if there
+	 * weren't any relevant event triggers at the start of the current DDL
+	 * command.  This test might therefore seem optional, but it's
+	 * *necessary*, because EventTriggerCommonSetup might find triggers that
+	 * didn't exist at the time the command started.
+	 */
+	if (!currentEventTriggerState)
+		return;
+
+	/* Do nothing if no command was collected. */
+	if (!currentEventTriggerState->currentCommand)
+		return;
+
+	command = currentEventTriggerState->currentCommand;
+
+	/* Set the real CreateTable statment and object address */
+	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
+	command->d.ctas.address = address;
+	command->d.ctas.real_create = copyObject(real_create);
+	MemoryContextSwitchTo(oldcxt);
+
+	runlist = EventTriggerCommonSetup(command->parsetree,
+									  EVT_TableInitWrite,
+									  "table_init_write",
+									  &trigdata);
+	if (runlist == NIL)
+		return;
+
+	/* Run the triggers. */
+	EventTriggerInvoke(runlist, &trigdata);
+
+	/* Cleanup. */
+	list_free(runlist);
+
+	/*
+	 * Make sure anything the event triggers did will be visible to the main
+	 * command.
+	 */
+	CommandCounterIncrement();
+}
+
 /*
  * Invoke each event trigger in a list of event triggers.
  */
@@ -1147,7 +1260,8 @@ trackDroppedObjectsNeeded(void)
 	 */
 	return (EventCacheLookup(EVT_SQLDrop) != NIL) ||
 		(EventCacheLookup(EVT_TableRewrite) != NIL) ||
-		(EventCacheLookup(EVT_DDLCommandEnd) != NIL);
+		(EventCacheLookup(EVT_DDLCommandEnd) != NIL) ||
+		(EventCacheLookup(EVT_TableInitWrite) != NIL);
 }
 
 /*
@@ -1538,6 +1652,7 @@ EventTriggerAlterTableStart(Node *parsetree)
 
 	command->d.alterTable.classId = RelationRelationId;
 	command->d.alterTable.objectId = InvalidOid;
+	command->d.alterTable.rewrite = false;
 	command->d.alterTable.subcmds = NIL;
 	command->parsetree = copyObject(parsetree);
 
@@ -1571,7 +1686,7 @@ EventTriggerAlterTableRelid(Oid objectId)
  * internally, so that's all that this code needs to handle at the moment.
  */
 void
-EventTriggerCollectAlterTableSubcmd(Node *subcmd, ObjectAddress address)
+EventTriggerCollectAlterTableSubcmd(Node *subcmd, ObjectAddress address, bool rewrite)
 {
 	MemoryContext oldcxt;
 	CollectedATSubcmd *newsub;
@@ -1591,12 +1706,156 @@ EventTriggerCollectAlterTableSubcmd(Node *subcmd, ObjectAddress address)
 	newsub->address = address;
 	newsub->parsetree = copyObject(subcmd);
 
+	currentEventTriggerState->currentCommand->d.alterTable.rewrite |= rewrite;
+	currentEventTriggerState->currentCommand->d.alterTable.subcmds =
+		lappend(currentEventTriggerState->currentCommand->d.alterTable.subcmds, newsub);
+
+	MemoryContextSwitchTo(oldcxt);
+}
+
+/*
+ * EventTriggerAlterTypeStart
+ *		Save data about a single part of an ALTER TYPE.
+ *
+ * ALTER TABLE can have multiple subcommands which might include DROP COLUMN
+ * command and ALTER TYPE referring the drop column in USING expression.
+ * As the dropped column cannot be accessed after the execution of DROP COLUMN,
+ * a special trigger is required to handle this case before the drop column is
+ * executed.
+ */
+void
+EventTriggerAlterTypeStart(AlterTableCmd *subcmd, Relation rel)
+{
+	MemoryContext oldcxt;
+	CollectedATSubcmd *newsub;
+	ColumnDef  *def;
+	Relation	attrelation;
+	HeapTuple	heapTup;
+	Form_pg_attribute attTup;
+	AttrNumber	attnum;
+	ObjectAddress address;
+
+	/* ignore if event trigger context not set, or collection disabled */
+	if (!currentEventTriggerState ||
+		currentEventTriggerState->commandCollectionInhibited)
+		return;
+
+	Assert(IsA(subcmd, AlterTableCmd));
+	Assert(subcmd->subtype == AT_AlterColumnType);
+	Assert(currentEventTriggerState->currentCommand != NULL);
+	Assert(OidIsValid(currentEventTriggerState->currentCommand->d.alterTable.objectId));
+
+	def = (ColumnDef *) subcmd->def;
+	Assert(IsA(def, ColumnDef));
+
+	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
+
+	newsub = palloc(sizeof(CollectedATSubcmd));
+	newsub->parsetree = (Node *)copyObject(subcmd);
+
+	attrelation = table_open(AttributeRelationId, RowExclusiveLock);
+
+	/* Look up the target column */
+	heapTup = SearchSysCacheCopyAttName(RelationGetRelid(rel), subcmd->name);
+	if (!HeapTupleIsValid(heapTup)) /* shouldn't happen */
+		ereport(ERROR,
+				errcode(ERRCODE_UNDEFINED_COLUMN),
+				errmsg("column \"%s\" of relation \"%s\" does not exist",
+					   subcmd->name, RelationGetRelationName(rel)));
+	attTup = (Form_pg_attribute) GETSTRUCT(heapTup);
+	attnum = attTup->attnum;
+
+	ObjectAddressSubSet(address, RelationRelationId,
+						RelationGetRelid(rel), attnum);
+	heap_freetuple(heapTup);
+	table_close(attrelation, RowExclusiveLock);
+	newsub->address = address;
+
+	if (def->raw_default)
+	{
+		OverrideSearchPath *overridePath;
+		char	   *defexpr;
+
+		/*
+		 * We want all object names to be qualified when deparsing the
+		 * expression, so that results are "portable" to environments with
+		 * different search_path settings. Rather than inject what would be
+		 * repetitive calls to override search path all over the place, we do
+		 * it centrally here.
+		 */
+		overridePath = GetOverrideSearchPath(CurrentMemoryContext);
+		overridePath->schemas = NIL;
+		overridePath->addCatalog = false;
+		overridePath->addTemp = true;
+		PushOverrideSearchPath(overridePath);
+
+		defexpr = nodeToString(def->cooked_default);
+		newsub->usingexpr = TextDatumGetCString(DirectFunctionCall2(pg_get_expr,
+																	CStringGetTextDatum(defexpr),
+																	RelationGetRelid(rel)));
+
+		PopOverrideSearchPath();
+	}
+	else
+		newsub->usingexpr = NULL;
+
 	currentEventTriggerState->currentCommand->d.alterTable.subcmds =
 		lappend(currentEventTriggerState->currentCommand->d.alterTable.subcmds, newsub);
 
 	MemoryContextSwitchTo(oldcxt);
 }
 
+/*
+ * EventTriggerAlterTypeEnd
+ *		Finish up saving an ALTER TYPE command, and add it to command list.
+ */
+void
+EventTriggerAlterTypeEnd(Node *subcmd, ObjectAddress address, bool rewrite)
+{
+	MemoryContext oldcxt;
+	CollectedATSubcmd *newsub;
+	ListCell   *cell;
+	CollectedCommand *cmd;
+	AlterTableCmd *altsubcmd = (AlterTableCmd *)subcmd;
+
+	/* ignore if event trigger context not set, or collection disabled */
+	if (!currentEventTriggerState ||
+		currentEventTriggerState->commandCollectionInhibited)
+		return;
+
+	cmd = currentEventTriggerState->currentCommand;
+
+	Assert(IsA(subcmd, AlterTableCmd));
+	Assert(cmd != NULL);
+	Assert(OidIsValid(cmd->d.alterTable.objectId));
+
+	foreach(cell, cmd->d.alterTable.subcmds)
+	{
+		CollectedATSubcmd *sub = (CollectedATSubcmd *) lfirst(cell);
+		AlterTableCmd *collcmd = (AlterTableCmd *) sub->parsetree;
+
+		if (collcmd->subtype == altsubcmd->subtype &&
+			address.classId == sub->address.classId &&
+			address.objectId == sub->address.objectId &&
+			address.objectSubId == sub->address.objectSubId)
+		{
+			cmd->d.alterTable.rewrite |= rewrite;
+			return;
+		}
+	}
+
+	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
+
+	newsub = palloc(sizeof(CollectedATSubcmd));
+	newsub->address = address;
+	newsub->parsetree = copyObject(subcmd);
+
+	cmd->d.alterTable.rewrite |= rewrite;
+	cmd->d.alterTable.subcmds = lappend(cmd->d.alterTable.subcmds, newsub);
+
+	MemoryContextSwitchTo(oldcxt);
+}
+
 /*
  * EventTriggerAlterTableEnd
  *		Finish up saving an ALTER TABLE command, and add it to command list.
@@ -1864,6 +2123,7 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
 			case SCT_AlterOpFamily:
 			case SCT_CreateOpClass:
 			case SCT_AlterTSConfig:
+			case SCT_CreateTableAs:
 				{
 					char	   *identity;
 					char	   *type;
@@ -1881,6 +2141,8 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
 						addr = cmd->d.createopc.address;
 					else if (cmd->type == SCT_AlterTSConfig)
 						addr = cmd->d.atscfg.address;
+					else if (cmd->type == SCT_CreateTableAs)
+						addr = cmd->d.ctas.address;
 
 					/*
 					 * If an object was dropped in the same command we may end
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index c15e943f1d..d0e649baaf 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -4742,6 +4742,9 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
 			cmd = ATParseTransformCmd(wqueue, tab, rel, cmd, recurse, lockmode,
 									  AT_PASS_UNSET, context);
 			Assert(cmd != NULL);
+
+			EventTriggerAlterTypeStart(cmd, rel);
+
 			/* Performs own recursion */
 			ATPrepAlterColumnType(wqueue, tab, rel, recurse, recursing, cmd,
 								  lockmode, context);
@@ -5013,6 +5016,7 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
 {
 	ObjectAddress address = InvalidObjectAddress;
 	Relation	rel = tab->rel;
+	bool		commandCollected = false;
 
 	switch (cmd->subtype)
 	{
@@ -5136,6 +5140,8 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
 		case AT_AlterColumnType:	/* ALTER COLUMN TYPE */
 			/* parse transformation was done earlier */
 			address = ATExecAlterColumnType(tab, rel, cmd, lockmode);
+			EventTriggerAlterTypeEnd((Node *) cmd, address, tab->rewrite);
+			commandCollected = true;
 			break;
 		case AT_AlterColumnGenericOptions:	/* ALTER COLUMN OPTIONS */
 			address =
@@ -5308,8 +5314,8 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
 	/*
 	 * Report the subcommand to interested event triggers.
 	 */
-	if (cmd)
-		EventTriggerCollectAlterTableSubcmd((Node *) cmd, address);
+	if (cmd && !commandCollected)
+		EventTriggerCollectAlterTableSubcmd((Node *) cmd, address, tab->rewrite);
 
 	/*
 	 * Bump the command counter to ensure the next subcommand in the sequence
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index c0f7f29747..3aa6270a88 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1675,8 +1675,11 @@ ProcessUtilitySlow(ParseState *pstate,
 				break;
 
 			case T_CreateTableAsStmt:
+				EventTriggerTableInitWriteStart(parsetree);
 				address = ExecCreateTableAs(pstate, (CreateTableAsStmt *) parsetree,
 											params, queryEnv, qc);
+				EventTriggerTableInitWriteEnd(address);
+				commandCollected = true;
 				break;
 
 			case T_RefreshMatViewStmt:
diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c
index 1f5e7eb4c6..f2a9f5dcc2 100644
--- a/src/backend/utils/cache/evtcache.c
+++ b/src/backend/utils/cache/evtcache.c
@@ -167,6 +167,8 @@ BuildEventTriggerCache(void)
 			event = EVT_SQLDrop;
 		else if (strcmp(evtevent, "table_rewrite") == 0)
 			event = EVT_TableRewrite;
+		else if (strcmp(evtevent, "table_init_write") == 0)
+			event = EVT_TableInitWrite;
 		else
 			continue;
 
diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h
index 5ed6ece555..cba4e72455 100644
--- a/src/include/commands/event_trigger.h
+++ b/src/include/commands/event_trigger.h
@@ -16,6 +16,7 @@
 #include "catalog/dependency.h"
 #include "catalog/objectaddress.h"
 #include "catalog/pg_event_trigger.h"
+#include "lib/ilist.h"
 #include "nodes/parsenodes.h"
 #include "tcop/cmdtag.h"
 #include "tcop/deparse_utility.h"
@@ -29,6 +30,44 @@ typedef struct EventTriggerData
 	CommandTag	tag;
 } EventTriggerData;
 
+typedef struct EventTriggerQueryState
+{
+	/* memory context for this state's objects */
+	MemoryContext cxt;
+
+	/* sql_drop */
+	slist_head	SQLDropList;
+	bool		in_sql_drop;
+
+	/* table_rewrite */
+	Oid			table_rewrite_oid;	/* InvalidOid, or set for table_rewrite
+									 * event */
+	int			table_rewrite_reason;	/* AT_REWRITE reason */
+
+	/* Support for command collection */
+	bool		commandCollectionInhibited;
+	CollectedCommand *currentCommand;
+	List	   *commandList;	/* list of CollectedCommand; see
+								 * deparse_utility.h */
+	struct EventTriggerQueryState *previous;
+} EventTriggerQueryState;
+
+/* Support for dropped objects */
+typedef struct SQLDropObject
+{
+	ObjectAddress address;
+	const char *schemaname;
+	const char *objname;
+	const char *objidentity;
+	const char *objecttype;
+	List	   *addrnames;
+	List	   *addrargs;
+	bool		original;
+	bool		normal;
+	bool		istemp;
+	slist_node	next;
+} SQLDropObject;
+
 #define AT_REWRITE_ALTER_PERSISTENCE	0x01
 #define AT_REWRITE_DEFAULT_VAL			0x02
 #define AT_REWRITE_COLUMN_REWRITE		0x04
@@ -55,6 +94,10 @@ extern void EventTriggerDDLCommandEnd(Node *parsetree);
 extern void EventTriggerSQLDrop(Node *parsetree);
 extern void EventTriggerTableRewrite(Node *parsetree, Oid tableOid, int reason);
 
+extern void EventTriggerTableInitWriteStart(Node *parsetree);
+extern void EventTriggerTableInitWrite(Node *parsetree, ObjectAddress address);
+extern void EventTriggerTableInitWriteEnd(ObjectAddress address);
+
 extern bool EventTriggerBeginCompleteQuery(void);
 extern void EventTriggerEndCompleteQuery(void);
 extern bool trackDroppedObjectsNeeded(void);
@@ -71,7 +114,12 @@ extern void EventTriggerCollectSimpleCommand(ObjectAddress address,
 extern void EventTriggerAlterTableStart(Node *parsetree);
 extern void EventTriggerAlterTableRelid(Oid objectId);
 extern void EventTriggerCollectAlterTableSubcmd(Node *subcmd,
-												ObjectAddress address);
+												ObjectAddress address,
+												bool rewrite);
+
+extern void EventTriggerAlterTypeStart(AlterTableCmd *subcmd, Relation rel);
+extern void EventTriggerAlterTypeEnd(Node *subcmd, ObjectAddress address,
+									 bool rewrite);
 extern void EventTriggerAlterTableEnd(void);
 
 extern void EventTriggerCollectGrant(InternalGrant *istmt);
diff --git a/src/include/tcop/deparse_utility.h b/src/include/tcop/deparse_utility.h
index b585810b9a..a4a12377b8 100644
--- a/src/include/tcop/deparse_utility.h
+++ b/src/include/tcop/deparse_utility.h
@@ -29,7 +29,8 @@ typedef enum CollectedCommandType
 	SCT_AlterOpFamily,
 	SCT_AlterDefaultPrivileges,
 	SCT_CreateOpClass,
-	SCT_AlterTSConfig
+	SCT_AlterTSConfig,
+	SCT_CreateTableAs
 } CollectedCommandType;
 
 /*
@@ -39,6 +40,7 @@ typedef struct CollectedATSubcmd
 {
 	ObjectAddress address;		/* affected column, constraint, index, ... */
 	Node	   *parsetree;
+	char	   *usingexpr;
 } CollectedATSubcmd;
 
 typedef struct CollectedCommand
@@ -62,6 +64,7 @@ typedef struct CollectedCommand
 		{
 			Oid			objectId;
 			Oid			classId;
+			bool		rewrite;
 			List	   *subcmds;
 		}			alterTable;
 
@@ -100,6 +103,13 @@ typedef struct CollectedCommand
 		{
 			ObjectType	objtype;
 		}			defprivs;
+
+		/* CREATE TABLE AS */
+		struct
+		{
+			ObjectAddress address;
+			Node		 *real_create;
+		}			ctas;
 	}			d;
 
 	struct CollectedCommand *parent;	/* when nested */
diff --git a/src/include/utils/evtcache.h b/src/include/utils/evtcache.h
index d340026518..91d4bdd6b3 100644
--- a/src/include/utils/evtcache.h
+++ b/src/include/utils/evtcache.h
@@ -22,7 +22,8 @@ typedef enum
 	EVT_DDLCommandStart,
 	EVT_DDLCommandEnd,
 	EVT_SQLDrop,
-	EVT_TableRewrite
+	EVT_TableRewrite,
+	EVT_TableInitWrite
 } EventTriggerEvent;
 
 typedef struct
-- 
2.34.1

