public inbox for pgsql-general@postgresql.org  
help / color / mirror / Atom feed
From: Ajin Cherian <itsajin@gmail.com>
To: Zheng Li <zhengli10@gmail.com>
Cc: Runqi Tian <runqidev@gmail.com>
Cc: vignesh C <vignesh21@gmail.com>
Cc: Peter Smith <smithpb2250@gmail.com>
Cc: li jie <ggysxcq@gmail.com>
Cc: Dilip Kumar <dilipbalaut@gmail.com>
Cc: Alvaro Herrera <alvherre@alvh.no-ip.org>
Cc: houzj.fnst@fujitsu.com <houzj.fnst@fujitsu.com>
Cc: Amit Kapila <amit.kapila16@gmail.com>
Cc: Masahiko Sawada <sawada.mshk@gmail.com>
Cc: Japin Li <japinli@hotmail.com>
Cc: rajesh singarapu <rajesh.rs0541@gmail.com>
Cc: PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Subject: Re: Support logical replication of DDLs
Date: Tue, 14 Mar 2023 15:17:20 +1100
Message-ID: <CAFPTHDaaewvYUznZD1YjUQnvHycgvgMKNK4w=V8Q-8MKTpVDrw@mail.gmail.com> (raw)
In-Reply-To: <CAAD30ULCxqOJp0sffm_y9jNC4BVPYv7Q7_va_JE8qyfRXkfu+g@mail.gmail.com>
References: <CAAD30UKg8rXeGM8Oy_MAmxKBL_K5DiHXdeNF=hUefcu1C_6VfQ@mail.gmail.com>
	<20221006171601.6um4ey5idm4h62vf@alvherre.pgsql>
	<CAAD30UJh+LcUND+zg_A5dbQ_Bi=m_n7qUfKrOwAx2v4jBKWvKQ@mail.gmail.com>
	<CAFPTHDbVujj6C3TdMCmoBXovpc4=5Ow3i5M1_HNhmnqdiA5qSA@mail.gmail.com>
	<CAAD30UKCCpMTZd4WSSxYu-qRAEFd+0kjXTgje+EXHdo1JTkz0g@mail.gmail.com>
	<CALDaNm3F9GvQ9bPrxobhqkUKP3HmrRZGCU3EX0xt3=Ef0-Reaw@mail.gmail.com>
	<CAFPTHDY2O42ouQFMeEbPt51CWQ=zyzYhgK6B9basyd5PLaOv0A@mail.gmail.com>
	<CAFPTHDZmS2PrOyJx8OAe+Nt-Fx4-GZetJatqCEJhDNXA2orwCg@mail.gmail.com>
	<CAFiTN-tWkJW-JEGANkK+O3KXUjv_Yb5Tb+r83ujbognHG_brTA@mail.gmail.com>
	<CALDaNm08gZq9a7xnsbaJMmHmi29_kbEuyShHHfxAKLXPh6btWQ@mail.gmail.com>
	<CAFPTHDbGRpXOF-j+oemm=xkzjrh-ZnqPV7SMS_+QBPYdUwhWxg@mail.gmail.com>
	<CAAD30UL=wV7pvdwJ6w5UQUc3urHs6W2vnomK2MKUyek3rzsKcA@mail.gmail.com>
	<CAHut+Psm+9q++y8b70QTeBeZiYcfDNtc_obxSwhxukp0MFhnRA@mail.gmail.com>
	<CAHut+PsO0dwWoB4B6L3Ucd6D8ckgdXY2Sd3JK7F_3wLsXU7ZAg@mail.gmail.com>
	<CAHut+Puxo_kq2toicNK_BQdeccK3REGW-Xv8tVauFvTNku6V-w@mail.gmail.com>
	<CAHut+Pu6H6hY0JJNNRCRmFpM_3817z=0xjm-_ibP+cL85pBOpQ@mail.gmail.com>
	<CALDaNm3q_2Qfo4XbFkBT8mPz_ALS2MyuR=isP7_8Pz27JnLHiw@mail.gmail.com>
	<CAGfChW5Qbb8WKznzVqp+cyTqkzLt_vEeSe14td14et6HjnH7qw@mail.gmail.com>
	<CAAD30UKwHmLo1YyjB1j_vCEth0+OS9hkLr9Nrrsw5uwEuOs=+g@mail.gmail.com>
	<CALDaNm2V6YL6H4P9ZT95Ua_RDJaeDTUf6V0UDfrz4_vxhM5pMg@mail.gmail.com>
	<CAAD30ULrZB-RNmuD3NMr1jGNUt15ZpPgFdFRX53HbcAB76hefw@mail.gmail.com>
	<CAAD30UL0EmSGk58eZxxYzFTQ5EqSpX6d+OcX5MuE0j0r2ZgyDA@mail.gmail.com>
	<CAAD30ULAVzCnNOsnHwZWoeWfaYr3yDtM-7TnkMJf9HTrW7HVCQ@mail.gmail.com>
	<CAAD30U+fqaaD6533-eiaWVHpUaBNBCEvqyXOT_ow1B--Aa_jOQ@mail.gmail.com>
	<CALDaNm0mnkHXnQ7zMDxY6=ZtWn8A1iKLKGhEtqRVC9c3gc8YCw@mail.gmail.com>
	<CAFPTHDY_9_xd8JEckB=Au2ALPnx+hfmn9ztutVw4aVwZxLhrNQ@mail.gmail.com>
	<CALDaNm3YEFNwFkkbzS1J8NiHKX6LWQ_h3CA+CPtkUqAZgD8q+Q@mail.gmail.com>
	<CAFPTHDY_4koZ135_Bub_=HPBxpG1u+XBEv8zspwXW7rAQps6eA@mail.gmail.com>
	<CALDaNm0dOwbPVrkqw9OLN=TVFdo5aroUNwdjG5SAcKQg93-g0w@mail.gmail.com>
	<CAHut+PtH9S+3-TGPa4_uipBP-4-Kksx-FrEkg9ZtK0FphVRA5A@mail.gmail.com>
	<CAFPTHDbZzCeYMPJn0iFuD_ggpY-0ZHfVBHgQ9VJ6v4dF59xang@mail.gmail.com>
	<CAHut+PusvDXTJa2drUPzePBBW0i9we8yns8Z4DU4b7JVs6Ew1Q@mail.gmail.com>
	<CAFPTHDa6aHhwZkQ+GjFNL1dSQbMfoEtN-6y9wseMywCLdKuUYQ@mail.gmail.com>
	<CALDaNm3u2eskS_eC19AFpg5Mx3DgyuSuyoJ4wHtgK1AAicSfzQ@mail.gmail.com>
	<CALDaNm2vrBn3iW7++mWrXCLLh-VkVZGSKPZko_rRhSbFUCTWcA@mail.gmail.com>
	<CAH8n8_jGK0Db95HtFWmPOLerQYPZ5c2sCO8ed6_ghjtypEhX3w@mail.gmail.com>
	<CAAD30ULCxqOJp0sffm_y9jNC4BVPYv7Q7_va_JE8qyfRXkfu+g@mail.gmail.com>

On Mon, Mar 13, 2023 at 2:24 AM Zheng Li <zhengli10@gmail.com> wrote:
>
> Thanks for working on the test coverage for CREATE and ALTER TABLE.
> I've made fixes for some of the failures in the v79 patch set (0002,
> 0003 and 0004 are updated). The changes includes:
> 1. Fixed a syntax error caused by ON COMMIT clause placement in
> deparse_CreateStmt.
> 2. Fixed deparse_Seq_As and start using it in deparse_CreateSeqStmt,
> this issue is also reported in [1].
> 3. Fixed a bug in append_not_present: the 'present: false' element
> can't be omitted even in non-verbose mode. It will cause syntax error
> on reformed command if 'present: false' element is missing but the fmt
> string indicates the corresponding object must be present.
> 4. Replaced if_not_exists with if_exists in deparse of
> AT_DropConstraint and AT_DropColumn.
> 5. Added missing CASCADE clause for AT_DropConstraint deparse.
> 6. Enabled the fixed test cases.
>

I found out that the option ONLY was not parsed in the "CREATE INDEX" command,
for eg: CREATE UNIQUE INDEX ... ON ONLY table_name ...

I've fixed this in patch 0002.

regards,
Ajin Cherian
Fujitsu Australia


Attachments:

  [application/octet-stream] v80-0005-DDL-messaging-infrastructure-for-DDL-replication.patch (41.2K, 2-v80-0005-DDL-messaging-infrastructure-for-DDL-replication.patch)
  download | inline diff:
From f2dea8ea97574764b0e93a3cca6e16113b75ee67 Mon Sep 17 00:00:00 2001
From: Ajin Cherian <ajinc@fast.au.fujitsu.com>
Date: Mon, 13 Mar 2023 23:53:48 -0400
Subject: [PATCH v80 5/8] DDL messaging infrastructure for DDL replication.

DDL messaging infrastructure for DDL replication.
---
 contrib/test_decoding/expected/ddl.out          |  26 +++++
 contrib/test_decoding/sql/ddl.sql               |   5 +
 contrib/test_decoding/test_decoding.c           |  48 +++++++++
 src/backend/access/rmgrdesc/Makefile            |   1 +
 src/backend/access/rmgrdesc/logicalddlmsgdesc.c |  52 ++++++++++
 src/backend/access/rmgrdesc/meson.build         |   1 +
 src/backend/access/transam/rmgr.c               |   1 +
 src/backend/replication/logical/Makefile        |   1 +
 src/backend/replication/logical/ddlmessage.c    |  84 ++++++++++++++++
 src/backend/replication/logical/decode.c        |  41 ++++++++
 src/backend/replication/logical/logical.c       |  44 ++++++++
 src/backend/replication/logical/logicalfuncs.c  |  24 +++++
 src/backend/replication/logical/meson.build     |   1 +
 src/backend/replication/logical/reorderbuffer.c | 127 ++++++++++++++++++++++++
 src/bin/pg_waldump/rmgrdesc.c                   |   1 +
 src/include/access/rmgrlist.h                   |   1 +
 src/include/catalog/pg_proc.dat                 |   8 ++
 src/include/replication/ddlmessage.h            |  60 +++++++++++
 src/include/replication/decode.h                |   1 +
 src/include/replication/output_plugin.h         |  14 +++
 src/include/replication/reorderbuffer.h         |  27 +++++
 21 files changed, 568 insertions(+)
 create mode 100644 src/backend/access/rmgrdesc/logicalddlmsgdesc.c
 create mode 100644 src/backend/replication/logical/ddlmessage.c
 create mode 100644 src/include/replication/ddlmessage.h

diff --git a/contrib/test_decoding/expected/ddl.out b/contrib/test_decoding/expected/ddl.out
index 9a28b5d..0f51f2b 100644
--- a/contrib/test_decoding/expected/ddl.out
+++ b/contrib/test_decoding/expected/ddl.out
@@ -831,6 +831,32 @@ SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'inc
 ------
 (0 rows)
 
+SELECT 'ddl msg1' FROM pg_logical_emit_ddl_message('ddl msg1', 16394, 1, 'msg1');
+ ?column? 
+----------
+ ddl msg1
+(1 row)
+
+SELECT 'ddl msg2' FROM pg_logical_emit_ddl_message('ddl msg2', 16394, 1, '{"fmt": "CREATE SCHEMA %{if_not_exists}s %{name}I %{authorization}s", "name": "foo", "authorization": {"fmt": "AUTHORIZATION %{authorization_role}I", "present": false, "authorization_role": null}, "if_not_exists": ""}');
+ ?column? 
+----------
+ ddl msg2
+(1 row)
+
+SELECT 'ddl msg3' FROM pg_logical_emit_ddl_message('ddl msg3', 16394, 1, '{"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{tablespace}s %{on_commit}s %{partition_by}s %{access_method}s %{with_clause}s", "identity": {"objname": "foo", "schemaname": "element_test"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}}');
+ ?column? 
+----------
+ ddl msg3
+(1 row)
+
+SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
+                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                data                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ message: prefix: ddl msg1, relid: 16394, cmdtype: Drop start, sz: 4 content:msg1
+ message: prefix: ddl msg2, relid: 16394, cmdtype: Drop start, sz: 217 content:{"fmt": "CREATE SCHEMA %{if_not_exists}s %{name}I %{authorization}s", "name": "foo", "authorization": {"fmt": "AUTHORIZATION %{authorization_role}I", "present": false, "authorization_role": null}, "if_not_exists": ""}
+ message: prefix: ddl msg3, relid: 16394, cmdtype: Drop start, sz: 1396 content:{"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{tablespace}s %{on_commit}s %{partition_by}s %{access_method}s %{with_clause}s", "identity": {"objname": "foo", "schemaname": "element_test"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}}
+(3 rows)
+
 SELECT pg_drop_replication_slot('regression_slot');
  pg_drop_replication_slot 
 --------------------------
diff --git a/contrib/test_decoding/sql/ddl.sql b/contrib/test_decoding/sql/ddl.sql
index 4f76bed..1ea5a4b 100644
--- a/contrib/test_decoding/sql/ddl.sql
+++ b/contrib/test_decoding/sql/ddl.sql
@@ -431,6 +431,11 @@ SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'inc
 -- done, free logical replication slot
 SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
 
+SELECT 'ddl msg1' FROM pg_logical_emit_ddl_message('ddl msg1', 16394, 1, 'msg1');
+SELECT 'ddl msg2' FROM pg_logical_emit_ddl_message('ddl msg2', 16394, 1, '{"fmt": "CREATE SCHEMA %{if_not_exists}s %{name}I %{authorization}s", "name": "foo", "authorization": {"fmt": "AUTHORIZATION %{authorization_role}I", "present": false, "authorization_role": null}, "if_not_exists": ""}');
+SELECT 'ddl msg3' FROM pg_logical_emit_ddl_message('ddl msg3', 16394, 1, '{"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{tablespace}s %{on_commit}s %{partition_by}s %{access_method}s %{with_clause}s", "identity": {"objname": "foo", "schemaname": "element_test"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}}');
+SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
+
 SELECT pg_drop_replication_slot('regression_slot');
 
 /* check that the slot is gone */
diff --git a/contrib/test_decoding/test_decoding.c b/contrib/test_decoding/test_decoding.c
index b7e6048..e967e3b 100644
--- a/contrib/test_decoding/test_decoding.c
+++ b/contrib/test_decoding/test_decoding.c
@@ -14,9 +14,11 @@
 
 #include "catalog/pg_type.h"
 
+#include "replication/ddlmessage.h"
 #include "replication/logical.h"
 #include "replication/origin.h"
 
+#include "tcop/ddl_deparse.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
@@ -72,6 +74,12 @@ static void pg_decode_message(LogicalDecodingContext *ctx,
 							  ReorderBufferTXN *txn, XLogRecPtr lsn,
 							  bool transactional, const char *prefix,
 							  Size sz, const char *message);
+static void pg_decode_ddl_message(LogicalDecodingContext *ctx,
+								  ReorderBufferTXN *txn,
+								  XLogRecPtr message_lsn,
+								  const char *prefix, Oid relid,
+								  DeparsedCommandType cmdtype,
+								  Size sz, const char *message);
 static bool pg_decode_filter_prepare(LogicalDecodingContext *ctx,
 									 TransactionId xid,
 									 const char *gid);
@@ -135,6 +143,7 @@ _PG_output_plugin_init(OutputPluginCallbacks *cb)
 	cb->filter_by_origin_cb = pg_decode_filter;
 	cb->shutdown_cb = pg_decode_shutdown;
 	cb->message_cb = pg_decode_message;
+	cb->ddl_cb = pg_decode_ddl_message;
 	cb->filter_prepare_cb = pg_decode_filter_prepare;
 	cb->begin_prepare_cb = pg_decode_begin_prepare_txn;
 	cb->prepare_cb = pg_decode_prepare_txn;
@@ -751,6 +760,45 @@ pg_decode_message(LogicalDecodingContext *ctx,
 }
 
 static void
+pg_decode_ddl_message(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
+					  XLogRecPtr message_lsn, const char *prefix, Oid relid,
+					  DeparsedCommandType cmdtype, Size sz, const char *message)
+{
+	OutputPluginPrepareWrite(ctx, true);
+	appendStringInfo(ctx->out, "message: prefix: %s, relid: %u, ",
+					 prefix, relid);
+
+	switch(cmdtype)
+	{
+	case DCT_SimpleCmd:
+		appendStringInfo(ctx->out, "cmdtype: Simple, ");
+		break;
+	case DCT_TableDropStart:
+		appendStringInfo(ctx->out, "cmdtype: Drop start, ");
+		break;
+	case DCT_TableDropEnd:
+		appendStringInfo(ctx->out, "cmdtype: Drop end, ");
+		break;
+	case DCT_TableAlter:
+		appendStringInfo(ctx->out, "cmdtype: Alter table, ");
+		break;
+	case DCT_ObjectCreate:
+		appendStringInfo(ctx->out, "cmdtype: Create, ");
+		break;
+	case DCT_ObjectDrop:
+		appendStringInfo(ctx->out, "cmdtype: Drop, ");
+		break;
+	default:
+		appendStringInfo(ctx->out, "cmdtype: Invalid, ");
+		break;
+	}
+
+	appendStringInfo(ctx->out, "sz: %zu content:", sz);
+	appendBinaryStringInfo(ctx->out, message, sz);
+	OutputPluginWrite(ctx, true);
+}
+
+static void
 pg_decode_stream_start(LogicalDecodingContext *ctx,
 					   ReorderBufferTXN *txn)
 {
diff --git a/src/backend/access/rmgrdesc/Makefile b/src/backend/access/rmgrdesc/Makefile
index f88d72f..2ff01e6 100644
--- a/src/backend/access/rmgrdesc/Makefile
+++ b/src/backend/access/rmgrdesc/Makefile
@@ -18,6 +18,7 @@ OBJS = \
 	gistdesc.o \
 	hashdesc.o \
 	heapdesc.o \
+	logicalddlmsgdesc.o \
 	logicalmsgdesc.o \
 	mxactdesc.o \
 	nbtdesc.o \
diff --git a/src/backend/access/rmgrdesc/logicalddlmsgdesc.c b/src/backend/access/rmgrdesc/logicalddlmsgdesc.c
new file mode 100644
index 0000000..05e930c
--- /dev/null
+++ b/src/backend/access/rmgrdesc/logicalddlmsgdesc.c
@@ -0,0 +1,52 @@
+/*-------------------------------------------------------------------------
+ *
+ * logicalddlmsgdesc.c
+ *	  rmgr descriptor routines for replication/logical/ddlmessage.c
+ *
+ * Portions Copyright (c) 2015-2022, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ *	  src/backend/access/rmgrdesc/logicalddlmsgdesc.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "replication/ddlmessage.h"
+
+void
+logicalddlmsg_desc(StringInfo buf, XLogReaderState *record)
+{
+	char	   *rec = XLogRecGetData(record);
+	uint8		info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
+
+	if (info == XLOG_LOGICAL_DDL_MESSAGE)
+	{
+		xl_logical_ddl_message *xlrec = (xl_logical_ddl_message *) rec;
+		char	   *prefix = xlrec->message;
+		char	   *message = xlrec->message + xlrec->prefix_size;
+		char	   *sep = "";
+
+		Assert(prefix[xlrec->prefix_size] != '\0');
+
+		appendStringInfo(buf, "prefix \"%s\"; payload (%zu bytes): ",
+						 prefix, xlrec->message_size);
+		appendStringInfo(buf, "relid %u cmdtype %u", xlrec->relid, xlrec->cmdtype);
+		/* Write message payload as a series of hex bytes */
+		for (int cnt = 0; cnt < xlrec->message_size; cnt++)
+		{
+			appendStringInfo(buf, "%s%02X", sep, (unsigned char) message[cnt]);
+			sep = " ";
+		}
+	}
+}
+
+const char *
+logicalddlmsg_identify(uint8 info)
+{
+	if ((info & ~XLR_INFO_MASK) == XLOG_LOGICAL_DDL_MESSAGE)
+		return "DDL";
+
+	return NULL;
+}
diff --git a/src/backend/access/rmgrdesc/meson.build b/src/backend/access/rmgrdesc/meson.build
index 166cee6..781e2d7 100644
--- a/src/backend/access/rmgrdesc/meson.build
+++ b/src/backend/access/rmgrdesc/meson.build
@@ -11,6 +11,7 @@ rmgr_desc_sources = files(
   'gistdesc.c',
   'hashdesc.c',
   'heapdesc.c',
+  'logicalddlmsgdesc.c',
   'logicalmsgdesc.c',
   'mxactdesc.c',
   'nbtdesc.c',
diff --git a/src/backend/access/transam/rmgr.c b/src/backend/access/transam/rmgr.c
index 7d67eda..678e81a 100644
--- a/src/backend/access/transam/rmgr.c
+++ b/src/backend/access/transam/rmgr.c
@@ -27,6 +27,7 @@
 #include "fmgr.h"
 #include "funcapi.h"
 #include "miscadmin.h"
+#include "replication/ddlmessage.h"
 #include "replication/decode.h"
 #include "replication/message.h"
 #include "replication/origin.h"
diff --git a/src/backend/replication/logical/Makefile b/src/backend/replication/logical/Makefile
index 2dc25e3..d3680e9 100644
--- a/src/backend/replication/logical/Makefile
+++ b/src/backend/replication/logical/Makefile
@@ -16,6 +16,7 @@ override CPPFLAGS := -I$(srcdir) $(CPPFLAGS)
 
 OBJS = \
 	applyparallelworker.o \
+	ddlmessage.o \
 	decode.o \
 	launcher.o \
 	logical.o \
diff --git a/src/backend/replication/logical/ddlmessage.c b/src/backend/replication/logical/ddlmessage.c
new file mode 100644
index 0000000..e11e56e
--- /dev/null
+++ b/src/backend/replication/logical/ddlmessage.c
@@ -0,0 +1,84 @@
+/*-------------------------------------------------------------------------
+ *
+ * ddlmessage.c
+ *	  Logical DDL messages.
+ *
+ * Copyright (c) 2022, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/backend/replication/logical/ddlmessage.c
+ *
+ * NOTES
+ *
+ * Logical DDL messages allow XLOG logging of DDL command strings that
+ * get passed to the logical decoding plugin. In normal XLOG processing they
+ * are same as NOOP.
+ *
+ * Unlike generic logical messages, these DDL messages have only transactional
+ * mode. Note by default DDLs in PostgreSQL are transactional.
+ *
+ * These messages are part of current transaction and will be sent to
+ * decoding plugin using in a same way as DML operations.
+ *
+ * Every message carries prefix to avoid conflicts between different decoding
+ * plugins. The plugin authors must take extra care to use unique prefix,
+ * good options seems to be for example to use the name of the extension.
+ *
+ * ---------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/xact.h"
+#include "access/xloginsert.h"
+#include "catalog/namespace.h"
+#include "miscadmin.h"
+#include "nodes/execnodes.h"
+#include "replication/logical.h"
+#include "replication/ddlmessage.h"
+#include "utils/memutils.h"
+
+/*
+ * Write logical decoding DDL message into XLog.
+ */
+XLogRecPtr
+LogLogicalDDLMessage(const char *prefix, Oid relid, DeparsedCommandType cmdtype,
+					 const char *message, size_t size)
+{
+	xl_logical_ddl_message xlrec;
+
+	 /* Ensure we have a valid transaction id. */
+	Assert(IsTransactionState());
+	GetCurrentTransactionId();
+
+	xlrec.dbId = MyDatabaseId;
+	/* Trailing zero is critical; see logicalddlmsg_desc */
+	xlrec.prefix_size = strlen(prefix) + 1;
+	xlrec.message_size = size;
+	xlrec.relid = relid;
+	xlrec.cmdtype = cmdtype;
+
+	XLogBeginInsert();
+	XLogRegisterData((char *) &xlrec, SizeOfLogicalDDLMessage);
+	XLogRegisterData(unconstify(char *, prefix), xlrec.prefix_size);
+	XLogRegisterData(unconstify(char *, message), size);
+
+	/* Allow origin filtering */
+	XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
+
+	return XLogInsert(RM_LOGICALDDLMSG_ID, XLOG_LOGICAL_DDL_MESSAGE);
+}
+
+/*
+ * Redo is basically just noop for logical decoding ddl messages.
+ */
+void
+logicalddlmsg_redo(XLogReaderState *record)
+{
+	uint8		info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
+
+	if (info != XLOG_LOGICAL_DDL_MESSAGE)
+		elog(PANIC, "logicalddlmsg_redo: unknown op code %u", info);
+
+	/* This is only interesting for logical decoding, see decode.c. */
+}
diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c
index 8fe7bb6..c615a23 100644
--- a/src/backend/replication/logical/decode.c
+++ b/src/backend/replication/logical/decode.c
@@ -36,6 +36,7 @@
 #include "access/xlogutils.h"
 #include "catalog/pg_control.h"
 #include "replication/decode.h"
+#include "replication/ddlmessage.h"
 #include "replication/logical.h"
 #include "replication/message.h"
 #include "replication/origin.h"
@@ -614,6 +615,46 @@ logicalmsg_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
 }
 
 /*
+ * Handle rmgr LOGICALDDLMSG_ID records for DecodeRecordIntoReorderBuffer().
+ */
+void
+logicalddl_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
+{
+	SnapBuild  *builder = ctx->snapshot_builder;
+	XLogReaderState *r = buf->record;
+	TransactionId xid = XLogRecGetXid(r);
+	uint8		info = XLogRecGetInfo(r) & ~XLR_INFO_MASK;
+	RepOriginId origin_id = XLogRecGetOrigin(r);
+	xl_logical_ddl_message *message;
+
+	if (info != XLOG_LOGICAL_DDL_MESSAGE)
+		elog(ERROR, "unexpected RM_LOGICALDDLMSG_ID record type: %u", info);
+
+	ReorderBufferProcessXid(ctx->reorder, XLogRecGetXid(r), buf->origptr);
+
+	/*
+	 * If we don't have snapshot or we are just fast-forwarding, there is no
+	 * point in decoding ddl messages.
+	 */
+	if (SnapBuildCurrentState(builder) < SNAPBUILD_FULL_SNAPSHOT ||
+		ctx->fast_forward)
+		return;
+
+	message = (xl_logical_ddl_message *) XLogRecGetData(r);
+
+	if (message->dbId != ctx->slot->data.database ||
+		FilterByOrigin(ctx, origin_id))
+		return;
+
+	if (SnapBuildProcessChange(builder, xid, buf->origptr))
+		ReorderBufferQueueDDLMessage(ctx->reorder, xid, buf->endptr,
+									 message->message, /* first part of message is prefix */
+									 message->message_size,
+									 message->message + message->prefix_size,
+									 message->relid, message->cmdtype);
+}
+
+/*
  * Consolidated commit record handling between the different form of commit
  * records.
  *
diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c
index c3ec97a..39e6861 100644
--- a/src/backend/replication/logical/logical.c
+++ b/src/backend/replication/logical/logical.c
@@ -33,6 +33,7 @@
 #include "fmgr.h"
 #include "miscadmin.h"
 #include "pgstat.h"
+#include "replication/ddlmessage.h"
 #include "replication/decode.h"
 #include "replication/logical.h"
 #include "replication/origin.h"
@@ -73,6 +74,10 @@ static void truncate_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
 static void message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
 							   XLogRecPtr message_lsn, bool transactional,
 							   const char *prefix, Size message_size, const char *message);
+static void ddl_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
+								  XLogRecPtr message_lsn, const char *prefix,
+								  Oid relid, DeparsedCommandType cmdtype,
+								  Size message_size, const char *message);
 
 /* streaming callbacks */
 static void stream_start_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
@@ -223,6 +228,7 @@ StartupDecodingContext(List *output_plugin_options,
 	ctx->reorder->apply_truncate = truncate_cb_wrapper;
 	ctx->reorder->commit = commit_cb_wrapper;
 	ctx->reorder->message = message_cb_wrapper;
+	ctx->reorder->ddl = ddl_cb_wrapper;
 
 	/*
 	 * To support streaming, we require start/stop/abort/commit/change
@@ -1234,6 +1240,44 @@ message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
 }
 
 static void
+ddl_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
+					  XLogRecPtr message_lsn,
+					  const char *prefix, Oid relid, DeparsedCommandType cmdtype,
+					  Size message_size,
+					  const char *message)
+{
+	LogicalDecodingContext *ctx = cache->private_data;
+	LogicalErrorCallbackState state;
+	ErrorContextCallback errcallback;
+
+	Assert(!ctx->fast_forward);
+
+	if (ctx->callbacks.ddl_cb == NULL)
+		return;
+
+	/* Push callback + info on the error context stack */
+	state.ctx = ctx;
+	state.callback_name = "ddl";
+	state.report_location = message_lsn;
+	errcallback.callback = output_plugin_error_callback;
+	errcallback.arg = (void *) &state;
+	errcallback.previous = error_context_stack;
+	error_context_stack = &errcallback;
+
+	/* set output state */
+	ctx->accept_writes = true;
+	ctx->write_xid = txn != NULL ? txn->xid : InvalidTransactionId;
+	ctx->write_location = message_lsn;
+
+	/* do the actual work: call callback */
+	ctx->callbacks.ddl_cb(ctx, txn, message_lsn, prefix, relid, cmdtype,
+								 message_size, message);
+
+	/* Pop the error context stack */
+	error_context_stack = errcallback.previous;
+}
+
+static void
 stream_start_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
 						XLogRecPtr first_lsn)
 {
diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c
index fa1b641..92f5f93 100644
--- a/src/backend/replication/logical/logicalfuncs.c
+++ b/src/backend/replication/logical/logicalfuncs.c
@@ -29,6 +29,7 @@
 #include "nodes/makefuncs.h"
 #include "replication/decode.h"
 #include "replication/logical.h"
+#include "replication/ddlmessage.h"
 #include "replication/message.h"
 #include "storage/fd.h"
 #include "utils/array.h"
@@ -388,3 +389,26 @@ pg_logical_emit_message_text(PG_FUNCTION_ARGS)
 	/* bytea and text are compatible */
 	return pg_logical_emit_message_bytea(fcinfo);
 }
+
+/*
+ * SQL function for writing logical decoding DDL message into WAL.
+ */
+Datum
+pg_logical_emit_ddl_message_bytea(PG_FUNCTION_ARGS)
+{
+	char	   *prefix = text_to_cstring(PG_GETARG_TEXT_PP(0));
+	Oid			relid = PG_GETARG_OID(1);
+	DeparsedCommandType cmdtype = PG_GETARG_INT16(2);
+	char	   *data = text_to_cstring(PG_GETARG_TEXT_PP(3));
+	XLogRecPtr	lsn;
+
+	lsn = LogLogicalDDLMessage(prefix, relid, cmdtype, data, strlen(data));
+	PG_RETURN_LSN(lsn);
+}
+
+Datum
+pg_logical_emit_ddl_message_text(PG_FUNCTION_ARGS)
+{
+	/* bytea and text are compatible */
+	return pg_logical_emit_ddl_message_bytea(fcinfo);
+}
diff --git a/src/backend/replication/logical/meson.build b/src/backend/replication/logical/meson.build
index d48cd4c..99c608d 100644
--- a/src/backend/replication/logical/meson.build
+++ b/src/backend/replication/logical/meson.build
@@ -2,6 +2,7 @@
 
 backend_sources += files(
   'applyparallelworker.c',
+  'ddlmessage.c',
   'decode.c',
   'launcher.c',
   'logical.c',
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 2d17c55..811739b 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -94,6 +94,7 @@
 #include "lib/binaryheap.h"
 #include "miscadmin.h"
 #include "pgstat.h"
+#include "replication/ddlmessage.h"
 #include "replication/logical.h"
 #include "replication/reorderbuffer.h"
 #include "replication/slot.h"
@@ -516,6 +517,14 @@ ReorderBufferReturnChange(ReorderBuffer *rb, ReorderBufferChange *change,
 				pfree(change->data.msg.message);
 			change->data.msg.message = NULL;
 			break;
+		case REORDER_BUFFER_CHANGE_DDL:
+			if (change->data.ddl.prefix != NULL)
+				pfree(change->data.ddl.prefix);
+			change->data.ddl.prefix = NULL;
+			if (change->data.ddl.message != NULL)
+				pfree(change->data.ddl.message);
+			change->data.ddl.message = NULL;
+			break;
 		case REORDER_BUFFER_CHANGE_INVALIDATION:
 			if (change->data.inval.invalidations)
 				pfree(change->data.inval.invalidations);
@@ -905,6 +914,36 @@ ReorderBufferQueueMessage(ReorderBuffer *rb, TransactionId xid,
 }
 
 /*
+ * A transactional DDL message is queued to be processed upon commit.
+ */
+void
+ReorderBufferQueueDDLMessage(ReorderBuffer *rb, TransactionId xid,
+							 XLogRecPtr lsn, const char *prefix,
+							 Size message_size, const char *message,
+							 Oid relid, DeparsedCommandType cmdtype)
+{
+	MemoryContext oldcontext;
+	ReorderBufferChange *change;
+
+	Assert(TransactionIdIsValid(xid));
+
+	oldcontext = MemoryContextSwitchTo(rb->context);
+
+	change = ReorderBufferGetChange(rb);
+	change->action = REORDER_BUFFER_CHANGE_DDL;
+	change->data.ddl.prefix = pstrdup(prefix);
+	change->data.ddl.relid = relid;
+	change->data.ddl.cmdtype = cmdtype;
+	change->data.ddl.message_size = message_size;
+	change->data.ddl.message = palloc(message_size);
+	memcpy(change->data.ddl.message, message, message_size);
+
+	ReorderBufferQueueChange(rb, xid, lsn, change, false);
+
+	MemoryContextSwitchTo(oldcontext);
+}
+
+/*
  * AssertTXNLsnOrder
  *		Verify LSN ordering of transaction lists in the reorderbuffer
  *
@@ -2007,6 +2046,21 @@ ReorderBufferApplyMessage(ReorderBuffer *rb, ReorderBufferTXN *txn,
 }
 
 /*
+ * Helper function for ReorderBufferProcessTXN for applying the DDL message.
+ */
+static inline void
+ReorderBufferApplyDDLMessage(ReorderBuffer *rb, ReorderBufferTXN *txn,
+							 ReorderBufferChange *change, bool streaming)
+{
+	rb->ddl(rb, txn, change->lsn,
+			change->data.ddl.prefix,
+			change->data.ddl.relid,
+			change->data.ddl.cmdtype,
+			change->data.ddl.message_size,
+			change->data.ddl.message);
+}
+
+/*
  * Function to store the command id and snapshot at the end of the current
  * stream so that we can reuse the same while sending the next stream.
  */
@@ -2388,6 +2442,10 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn,
 					ReorderBufferApplyMessage(rb, txn, change, streaming);
 					break;
 
+				case REORDER_BUFFER_CHANGE_DDL:
+					ReorderBufferApplyDDLMessage(rb, txn, change, streaming);
+					break;
+
 				case REORDER_BUFFER_CHANGE_INVALIDATION:
 					/* Execute the invalidation messages locally */
 					ReorderBufferExecuteInvalidations(change->data.inval.ninvalidations,
@@ -3847,6 +3905,39 @@ ReorderBufferSerializeChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
 
 				break;
 			}
+		case REORDER_BUFFER_CHANGE_DDL:
+			{
+				char	   *data;
+				Size		prefix_size = strlen(change->data.ddl.prefix) + 1;
+
+				sz += prefix_size + change->data.ddl.message_size +
+					sizeof(Size) + sizeof(Oid) + sizeof(int) + sizeof(Size);
+				ReorderBufferSerializeReserve(rb, sz);
+
+				data = ((char *) rb->outbuf) + sizeof(ReorderBufferDiskChange);
+
+				/* might have been reallocated above */
+				ondisk = (ReorderBufferDiskChange *) rb->outbuf;
+
+				/* write the prefix, relid and cmdtype including the size */
+				memcpy(data, &prefix_size, sizeof(Size));
+				data += sizeof(Size);
+				memcpy(data, &change->data.ddl.relid, sizeof(Oid));
+				data += sizeof(Oid);
+				memcpy(data, &change->data.ddl.cmdtype, sizeof(DeparsedCommandType));
+				data += sizeof(int);
+				memcpy(data, change->data.ddl.prefix, prefix_size);
+				data += prefix_size;
+
+				/* write the message including the size */
+				memcpy(data, &change->data.ddl.message_size, sizeof(Size));
+				data += sizeof(Size);
+				memcpy(data, change->data.ddl.message,
+					   change->data.ddl.message_size);
+				data += change->data.ddl.message_size;
+
+				break;
+			}
 		case REORDER_BUFFER_CHANGE_INVALIDATION:
 			{
 				char	   *data;
@@ -4161,6 +4252,15 @@ ReorderBufferChangeSize(ReorderBufferChange *change)
 
 				break;
 			}
+		case REORDER_BUFFER_CHANGE_DDL:
+			{
+				Size		prefix_size = strlen(change->data.ddl.prefix) + 1;
+
+				sz += prefix_size + change->data.ddl.message_size +
+					sizeof(Size) + sizeof(Size) + sizeof(Oid) + sizeof(DeparsedCommandType);
+
+				break;
+			}
 		case REORDER_BUFFER_CHANGE_INVALIDATION:
 			{
 				sz += sizeof(SharedInvalidationMessage) *
@@ -4438,6 +4538,33 @@ ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
 
 				break;
 			}
+		case REORDER_BUFFER_CHANGE_DDL:
+			{
+				Size		prefix_size;
+
+				/* read prefix */
+				memcpy(&prefix_size, data, sizeof(Size));
+				data += sizeof(Size);
+				memcpy(&change->data.ddl.relid, data, sizeof(Oid));
+				data += sizeof(Oid);
+				memcpy(&change->data.ddl.cmdtype, data, sizeof(DeparsedCommandType));
+				data += sizeof(int);
+				change->data.ddl.prefix = MemoryContextAlloc(rb->context, prefix_size);
+				memcpy(change->data.ddl.prefix, data, prefix_size);
+				Assert(change->data.ddl.prefix[prefix_size - 1] == '\0');
+				data += prefix_size;
+
+				/* read the message */
+				memcpy(&change->data.msg.message_size, data, sizeof(Size));
+				data += sizeof(Size);
+				change->data.msg.message = MemoryContextAlloc(rb->context,
+															  change->data.msg.message_size);
+				memcpy(change->data.msg.message, data,
+					   change->data.msg.message_size);
+				data += change->data.msg.message_size;
+
+				break;
+			}
 		case REORDER_BUFFER_CHANGE_INVALIDATION:
 			{
 				Size		inval_size = sizeof(SharedInvalidationMessage) *
diff --git a/src/bin/pg_waldump/rmgrdesc.c b/src/bin/pg_waldump/rmgrdesc.c
index 6b8c17b..daf1730 100644
--- a/src/bin/pg_waldump/rmgrdesc.c
+++ b/src/bin/pg_waldump/rmgrdesc.c
@@ -26,6 +26,7 @@
 #include "commands/dbcommands_xlog.h"
 #include "commands/sequence.h"
 #include "commands/tablespace.h"
+#include "replication/ddlmessage.h"
 #include "replication/message.h"
 #include "replication/origin.h"
 #include "rmgrdesc.h"
diff --git a/src/include/access/rmgrlist.h b/src/include/access/rmgrlist.h
index 463bcb6..abcbe97 100644
--- a/src/include/access/rmgrlist.h
+++ b/src/include/access/rmgrlist.h
@@ -47,3 +47,4 @@ PG_RMGR(RM_COMMIT_TS_ID, "CommitTs", commit_ts_redo, commit_ts_desc, commit_ts_i
 PG_RMGR(RM_REPLORIGIN_ID, "ReplicationOrigin", replorigin_redo, replorigin_desc, replorigin_identify, NULL, NULL, NULL, NULL)
 PG_RMGR(RM_GENERIC_ID, "Generic", generic_redo, generic_desc, generic_identify, NULL, NULL, generic_mask, NULL)
 PG_RMGR(RM_LOGICALMSG_ID, "LogicalMessage", logicalmsg_redo, logicalmsg_desc, logicalmsg_identify, NULL, NULL, NULL, logicalmsg_decode)
+PG_RMGR(RM_LOGICALDDLMSG_ID, "LogicalDDLMessage", logicalddlmsg_redo, logicalddlmsg_desc, logicalddlmsg_identify, NULL, NULL, NULL, logicalddl_decode)
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index e04de52..5cd263e 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -11044,6 +11044,14 @@
   proname => 'pg_logical_emit_message', provolatile => 'v', proparallel => 'u',
   prorettype => 'pg_lsn', proargtypes => 'bool text bytea',
   prosrc => 'pg_logical_emit_message_bytea' },
+{ oid => '3813', descr => 'emit a textual logical decoding message',
+  proname => 'pg_logical_emit_ddl_message', provolatile => 'v', proparallel => 'u',
+  prorettype => 'pg_lsn', proargtypes => 'bool text text',
+  prosrc => 'pg_logical_emit_ddl_message_text' },
+{ oid => '3814', descr => 'emit a binary logical decoding message',
+  proname => 'pg_logical_emit_ddl_message', provolatile => 'v', proparallel => 'u',
+  prorettype => 'pg_lsn', proargtypes => 'text regclass int4 text',
+  prosrc => 'pg_logical_emit_ddl_message_bytea' },
 
 # event triggers
 { oid => '3566', descr => 'list objects dropped by the current command',
diff --git a/src/include/replication/ddlmessage.h b/src/include/replication/ddlmessage.h
new file mode 100644
index 0000000..77df6ea
--- /dev/null
+++ b/src/include/replication/ddlmessage.h
@@ -0,0 +1,60 @@
+/*-------------------------------------------------------------------------
+ * ddlmessage.h
+ *	   Exports from replication/logical/ddlmessage.c
+ *
+ * Copyright (c) 2022, PostgreSQL Global Development Group
+ *
+ * src/include/replication/ddlmessage.h
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_LOGICAL_DDL_MESSAGE_H
+#define PG_LOGICAL_DDL_MESSAGE_H
+
+#include "access/xlog.h"
+#include "access/xlogdefs.h"
+#include "access/xlogreader.h"
+#include "nodes/nodes.h"
+
+
+/*
+ * Support for keeping track of deparsed commands.
+ */
+typedef enum DeparsedCommandType
+{
+	DCT_SimpleCmd,
+	DCT_TableDropStart,
+	DCT_TableDropEnd,
+	DCT_TableAlter,
+	DCT_ObjectCreate,
+	DCT_ObjectDrop
+} DeparsedCommandType;
+
+/*
+ * Generic logical decoding DDL message wal record.
+ */
+typedef struct xl_logical_ddl_message
+{
+	Oid			dbId;			/* database Oid emitted from */
+	Size		prefix_size;	/* length of prefix including null terminator */
+	Oid			relid;			/* id of the table */
+	DeparsedCommandType cmdtype;	/* type of sql command */
+	Size		message_size;	/* size of the message */
+
+	/*
+	 * payload, including null-terminated prefix of length prefix_size
+	 */
+	char		message[FLEXIBLE_ARRAY_MEMBER];
+} xl_logical_ddl_message;
+
+#define SizeOfLogicalDDLMessage	(offsetof(xl_logical_ddl_message, message))
+
+extern XLogRecPtr LogLogicalDDLMessage(const char *prefix, Oid relid, DeparsedCommandType cmdtype,
+									   const char *ddl_message, size_t size);
+
+/* RMGR API*/
+#define XLOG_LOGICAL_DDL_MESSAGE	0x00
+void		logicalddlmsg_redo(XLogReaderState *record);
+void		logicalddlmsg_desc(StringInfo buf, XLogReaderState *record);
+const char *logicalddlmsg_identify(uint8 info);
+
+#endif
diff --git a/src/include/replication/decode.h b/src/include/replication/decode.h
index 14fa921..c9ac708 100644
--- a/src/include/replication/decode.h
+++ b/src/include/replication/decode.h
@@ -27,6 +27,7 @@ extern void heap2_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
 extern void xact_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
 extern void standby_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
 extern void logicalmsg_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
+extern void logicalddl_decode(LogicalDecodingContext *ctx, XLogRecordBuffer *buf);
 
 extern void LogicalDecodingProcessRecord(LogicalDecodingContext *ctx,
 										 XLogReaderState *record);
diff --git a/src/include/replication/output_plugin.h b/src/include/replication/output_plugin.h
index 2d89d26..5ed5e6a 100644
--- a/src/include/replication/output_plugin.h
+++ b/src/include/replication/output_plugin.h
@@ -9,6 +9,7 @@
 #ifndef OUTPUT_PLUGIN_H
 #define OUTPUT_PLUGIN_H
 
+#include "replication/ddlmessage.h"
 #include "replication/reorderbuffer.h"
 
 struct LogicalDecodingContext;
@@ -91,6 +92,18 @@ typedef void (*LogicalDecodeMessageCB) (struct LogicalDecodingContext *ctx,
 										const char *message);
 
 /*
+ * Called for the logical decoding DDL messages.
+ */
+typedef void (*LogicalDecodeDDLMessageCB) (struct LogicalDecodingContext *ctx,
+										   ReorderBufferTXN *txn,
+										   XLogRecPtr message_lsn,
+										   const char *prefix,
+										   Oid relid,
+										   DeparsedCommandType cmdtype,
+										   Size message_size,
+										   const char *message);
+
+/*
  * Filter changes by origin.
  */
 typedef bool (*LogicalDecodeFilterByOriginCB) (struct LogicalDecodingContext *ctx,
@@ -221,6 +234,7 @@ typedef struct OutputPluginCallbacks
 	LogicalDecodeTruncateCB truncate_cb;
 	LogicalDecodeCommitCB commit_cb;
 	LogicalDecodeMessageCB message_cb;
+	LogicalDecodeDDLMessageCB ddl_cb;
 	LogicalDecodeFilterByOriginCB filter_by_origin_cb;
 	LogicalDecodeShutdownCB shutdown_cb;
 
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
index 215d149..e92b816 100644
--- a/src/include/replication/reorderbuffer.h
+++ b/src/include/replication/reorderbuffer.h
@@ -11,6 +11,8 @@
 
 #include "access/htup_details.h"
 #include "lib/ilist.h"
+#include "nodes/nodes.h"
+#include "replication/ddlmessage.h"
 #include "storage/sinval.h"
 #include "utils/hsearch.h"
 #include "utils/relcache.h"
@@ -65,6 +67,7 @@ typedef enum ReorderBufferChangeType
 	REORDER_BUFFER_CHANGE_INSERT,
 	REORDER_BUFFER_CHANGE_UPDATE,
 	REORDER_BUFFER_CHANGE_DELETE,
+	REORDER_BUFFER_CHANGE_DDL,
 	REORDER_BUFFER_CHANGE_MESSAGE,
 	REORDER_BUFFER_CHANGE_INVALIDATION,
 	REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT,
@@ -139,6 +142,16 @@ typedef struct ReorderBufferChange
 			char	   *message;
 		}			msg;
 
+		/* DDL */
+		struct
+		{
+			char	   *prefix;
+			Size		message_size;
+			char	   *message;
+			Oid			relid;
+			DeparsedCommandType cmdtype;
+		}			ddl;
+
 		/* New snapshot, set when action == *_INTERNAL_SNAPSHOT */
 		Snapshot	snapshot;
 
@@ -452,6 +465,16 @@ typedef void (*ReorderBufferMessageCB) (ReorderBuffer *rb,
 										const char *prefix, Size sz,
 										const char *message);
 
+/* DDL message callback signature */
+typedef void (*ReorderBufferDDLMessageCB) (ReorderBuffer *rb,
+										   ReorderBufferTXN *txn,
+										   XLogRecPtr message_lsn,
+										   const char *prefix,
+										   Oid relid,
+										   DeparsedCommandType cmdtype,
+										   Size sz,
+										   const char *message);
+
 /* begin prepare callback signature */
 typedef void (*ReorderBufferBeginPrepareCB) (ReorderBuffer *rb,
 											 ReorderBufferTXN *txn);
@@ -574,6 +597,7 @@ struct ReorderBuffer
 	ReorderBufferApplyTruncateCB apply_truncate;
 	ReorderBufferCommitCB commit;
 	ReorderBufferMessageCB message;
+	ReorderBufferDDLMessageCB ddl;
 
 	/*
 	 * Callbacks to be called when streaming a transaction at prepare time.
@@ -678,6 +702,9 @@ extern void ReorderBufferQueueMessage(ReorderBuffer *rb, TransactionId xid,
 									  Snapshot snap, XLogRecPtr lsn,
 									  bool transactional, const char *prefix,
 									  Size message_size, const char *message);
+extern void ReorderBufferQueueDDLMessage(ReorderBuffer *, TransactionId, XLogRecPtr lsn,
+										 const char *prefix, Size message_size,
+										 const char *message, Oid relid, DeparsedCommandType cmdtype);
 extern void ReorderBufferCommit(ReorderBuffer *rb, TransactionId xid,
 								XLogRecPtr commit_lsn, XLogRecPtr end_lsn,
 								TimestampTz commit_time, RepOriginId origin_id, XLogRecPtr origin_lsn);
-- 
1.8.3.1



  [application/octet-stream] v80-0001-Infrastructure-to-support-DDL-deparsing.patch (44.0K, 3-v80-0001-Infrastructure-to-support-DDL-deparsing.patch)
  download | inline diff:
From fd15a812972f88e3e7b821b8504114f176898211 Mon Sep 17 00:00:00 2001
From: Ajin Cherian <ajinc@fast.au.fujitsu.com>
Date: Mon, 13 Mar 2023 23:34:43 -0400
Subject: [PATCH v80 1/8] Infrastructure to support DDL deparsing.

Infrastructure to support DDL deparsing.
1) Some of the event trigger structures were moved from event_trigger.c
   to event_trigger.h as these will be required for publication event
   trigger creation.
2) Some of the prototypes and structures were moved from pg_publication.h
   to publicationcmds.h. This was because one of the later patch required the inclusion of
   pg_publication.h and these prototype had references to server header
   files.
3) Change the object identity to match with the syntax in objectaddress.c
   This is so that the deparse logic can use this identity directly in the deparse logic.
---
 src/backend/catalog/aclchk.c                |   9 +-
 src/backend/commands/collationcmds.c        |  21 +-
 src/backend/commands/event_trigger.c        |  73 +++----
 src/backend/commands/seclabel.c             |   6 +
 src/backend/commands/sequence.c             |  43 ++++
 src/backend/replication/pgoutput/pgoutput.c |   1 +
 src/backend/tcop/utility.c                  | 110 +++++++++-
 src/backend/utils/adt/format_type.c         |   4 +-
 src/backend/utils/adt/regproc.c             |  52 ++++-
 src/backend/utils/adt/ruleutils.c           | 324 +++++++++++++++++++---------
 src/include/catalog/pg_publication.h        |  17 +-
 src/include/commands/collationcmds.h        |   3 +-
 src/include/commands/event_trigger.h        |  41 ++++
 src/include/commands/publicationcmds.h      |  14 ++
 src/include/commands/sequence.h             |   9 +
 src/include/tcop/deparse_utility.h          |  10 +-
 src/include/tcop/utility.h                  |   2 +
 src/include/utils/acl.h                     |   2 +
 src/include/utils/aclchk_internal.h         |   1 +
 src/include/utils/builtins.h                |   2 +
 src/include/utils/rel.h                     |   2 +
 src/include/utils/ruleutils.h               |  19 ++
 src/tools/pgindent/typedefs.list            |   1 +
 23 files changed, 596 insertions(+), 170 deletions(-)

diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index c423234..36a6677 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -129,7 +129,6 @@ static void expand_all_col_privileges(Oid table_oid, Form_pg_class classForm,
 									  AclMode *col_privileges,
 									  int num_col_privileges);
 static AclMode string_to_privilege(const char *privname);
-static const char *privilege_to_string(AclMode privilege);
 static AclMode restrict_and_check_grant(bool is_grant, AclMode avail_goptions,
 										bool all_privs, AclMode privileges,
 										Oid objectId, Oid grantorId,
@@ -385,11 +384,10 @@ ExecuteGrantStmt(GrantStmt *stmt)
 	ListCell   *cell;
 	const char *errormsg;
 	AclMode		all_privileges;
+	Oid			grantor = InvalidOid;
 
 	if (stmt->grantor)
 	{
-		Oid			grantor;
-
 		grantor = get_rolespec_oid(stmt->grantor, false);
 
 		/*
@@ -408,6 +406,9 @@ ExecuteGrantStmt(GrantStmt *stmt)
 	istmt.is_grant = stmt->is_grant;
 	istmt.objtype = stmt->objtype;
 
+	/* Copy the grantor id needed for DDL deparsing of Grant */
+	istmt.grantor_uid = grantor;
+
 	/* Collect the OIDs of the target objects */
 	switch (stmt->targtype)
 	{
@@ -2628,7 +2629,7 @@ string_to_privilege(const char *privname)
 	return 0;					/* appease compiler */
 }
 
-static const char *
+const char *
 privilege_to_string(AclMode privilege)
 {
 	switch (privilege)
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index 8949684..e5b2d99 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -50,9 +50,21 @@ typedef struct
 
 /*
  * CREATE COLLATION
+ *
+ * pstate: parse state.
+ * names: qualified collation names (a list of String).
+ * parameters: collation attributes (a list of DefElem).
+ * if_not_exists: if true, don't fail on duplicate name, just print a notice
+ * and return InvalidOid.
+ * from_existing_collid: output argument which, if not NULL, is set to the
+ * address of existing collation that was used to create in case of
+ * CREATE COLLATION any_name FROM existing_collation.
+ *
+ * If successful, returns the address of the new collation.
  */
 ObjectAddress
-DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists)
+DefineCollation(ParseState *pstate, List *names, List *parameters,
+				bool if_not_exists, ObjectAddress *from_existing_collid)
 {
 	char	   *collName;
 	Oid			collNamespace;
@@ -143,6 +155,13 @@ DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_e
 		if (!HeapTupleIsValid(tp))
 			elog(ERROR, "cache lookup failed for collation %u", collid);
 
+		/*
+		 * Make from existing collationid available to callers for statements such as
+		 * CREATE COLLATION any_name FROM any_name
+		 */
+		if (from_existing_collid && OidIsValid(collid))
+			ObjectAddressSet(*from_existing_collid, CollationRelationId, collid);
+
 		collprovider = ((Form_pg_collation) GETSTRUCT(tp))->collprovider;
 		collisdeterministic = ((Form_pg_collation) GETSTRUCT(tp))->collisdeterministic;
 		collencoding = ((Form_pg_collation) GETSTRUCT(tp))->collencoding;
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index d4b00d1..b380e39 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -48,45 +48,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,
@@ -1813,6 +1775,36 @@ EventTriggerCollectAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt)
 }
 
 /*
+ * EventTriggerCollectSecLabel
+ *		Save data about an SECURITY LABEL command being executed
+ */
+void
+EventTriggerCollectSecLabel(ObjectAddress address, char *provider,
+							SecLabelStmt *stmt)
+{
+	MemoryContext oldcxt;
+	CollectedCommand *command;
+
+	/* ignore if event trigger context not set, or collection disabled */
+	if (!currentEventTriggerState ||
+		currentEventTriggerState->commandCollectionInhibited)
+		return;
+
+	oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt);
+
+	command = palloc0(sizeof(CollectedCommand));
+	command->type = SCT_SecurityLabel;
+	command->in_extension = creating_extension;
+	command->d.seclabel.address = address;
+	command->d.seclabel.provider = provider;
+	command->parsetree = (Node *) copyObject(stmt);
+
+	currentEventTriggerState->commandList =
+		lappend(currentEventTriggerState->commandList, command);
+	MemoryContextSwitchTo(oldcxt);
+}
+
+/*
  * In a ddl_command_end event trigger, this function reports the DDL commands
  * being run.
  */
@@ -1863,6 +1855,7 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
 			case SCT_AlterOpFamily:
 			case SCT_CreateOpClass:
 			case SCT_AlterTSConfig:
+			case SCT_SecurityLabel:
 				{
 					char	   *identity;
 					char	   *type;
@@ -1880,6 +1873,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_SecurityLabel)
+						addr = cmd->d.seclabel.address;
 
 					/*
 					 * If an object was dropped in the same command we may end
diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c
index 7ff16e3..7ee54cd 100644
--- a/src/backend/commands/seclabel.c
+++ b/src/backend/commands/seclabel.c
@@ -18,6 +18,7 @@
 #include "catalog/indexing.h"
 #include "catalog/pg_seclabel.h"
 #include "catalog/pg_shseclabel.h"
+#include "commands/event_trigger.h"
 #include "commands/seclabel.h"
 #include "miscadmin.h"
 #include "utils/builtins.h"
@@ -213,6 +214,11 @@ ExecSecLabelStmt(SecLabelStmt *stmt)
 	if (relation != NULL)
 		relation_close(relation, NoLock);
 
+	/* Pass the info to event triggers about the SECURITY LABEL. */
+	if (EventTriggerSupportsObjectType(stmt->objtype))
+		EventTriggerCollectSecLabel(address, pstrdup(provider->provider_name),
+									stmt);
+
 	return address;
 }
 
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index bfe279c..2969d3d 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1708,6 +1708,49 @@ process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
 		relation_close(tablerel, NoLock);
 }
 
+/*
+ * Return sequence parameters, detailed
+ */
+Sequence_values *
+get_sequence_values(Oid sequenceId)
+{
+	Buffer      buf;
+	SeqTable    elm;
+	Relation    seqrel;
+	HeapTuple	seqtuple;
+	HeapTupleData seqtupledata;
+	Form_pg_sequence seqform;
+	Form_pg_sequence_data seq;
+	Sequence_values *seqvalues;
+
+	seqtuple = SearchSysCache1(SEQRELID, sequenceId);
+	if (!HeapTupleIsValid(seqtuple))
+		elog(ERROR, "cache lookup failed for sequence %u", sequenceId);
+	seqform = (Form_pg_sequence) GETSTRUCT(seqtuple);
+
+	ReleaseSysCache(seqtuple);
+
+	/* Open and lock sequence */
+	init_sequence(sequenceId, &elm, &seqrel);
+
+	if (pg_class_aclcheck(sequenceId, GetUserId(),
+		ACL_SELECT | ACL_USAGE) != ACLCHECK_OK)
+		ereport(ERROR,
+				errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				errmsg("permission denied for sequence %s",
+					   RelationGetRelationName(seqrel)));
+
+	seq = read_seq_tuple(seqrel, &buf, &seqtupledata);
+
+	seqvalues = (Sequence_values *) palloc(sizeof(Sequence_values));
+	seqvalues->last_value = seq->last_value;
+	seqvalues->seqform = seqform;
+
+	UnlockReleaseBuffer(buf);
+	relation_close(seqrel, NoLock);
+
+	return seqvalues;
+}
 
 /*
  * Return sequence parameters in a list of the form created by the parser.
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 00a2d73..4e61ad3 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -18,6 +18,7 @@
 #include "catalog/pg_publication_rel.h"
 #include "catalog/pg_subscription.h"
 #include "commands/defrem.h"
+#include "commands/publicationcmds.h"
 #include "commands/subscriptioncmds.h"
 #include "executor/executor.h"
 #include "fmgr.h"
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index c7d9d96..6fd3d47 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1446,7 +1446,8 @@ ProcessUtilitySlow(ParseState *pstate,
 							address = DefineCollation(pstate,
 													  stmt->defnames,
 													  stmt->definition,
-													  stmt->if_not_exists);
+													  stmt->if_not_exists,
+													  &secondaryObject);
 							break;
 						default:
 							elog(ERROR, "unrecognized define stmt type: %d",
@@ -1826,6 +1827,7 @@ ProcessUtilitySlow(ParseState *pstate,
 
 			case T_SecLabelStmt:
 				address = ExecSecLabelStmt((SecLabelStmt *) parsetree);
+				commandCollected = true;
 				break;
 
 			case T_CreateAmStmt:
@@ -2196,6 +2198,112 @@ UtilityContainsQuery(Node *parsetree)
 	}
 }
 
+/*
+ * Return the given object type as a string.
+ *
+ * If isgrant is true, then this function is called while deparsing GRANT
+ * statement and some object names are replaced.
+ */
+const char *
+stringify_objtype(ObjectType objtype, bool isgrant)
+{
+	switch (objtype)
+	{
+		case OBJECT_AGGREGATE:
+			return "AGGREGATE";
+		case OBJECT_CAST:
+			return "CAST";
+		case OBJECT_COLLATION:
+			return "COLLATION";
+		case OBJECT_COLUMN:
+			return isgrant ? "TABLE" : "COLUMN";
+		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 "FOREIGN DATA WRAPPER";
+		case OBJECT_FOREIGN_SERVER:
+			return isgrant ? "FOREIGN SERVER" : "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_MATVIEW:
+			return "MATERIALIZED VIEW";
+		case OBJECT_OPCLASS:
+			return "OPERATOR CLASS";
+		case OBJECT_OPERATOR:
+			return "OPERATOR";
+		case OBJECT_OPFAMILY:
+			return "OPERATOR FAMILY";
+		case OBJECT_POLICY:
+			return "POLICY";
+		case OBJECT_PROCEDURE:
+			return "PROCEDURE";
+		case OBJECT_ROLE:
+			return "ROLE";
+		case OBJECT_ROUTINE:
+			return "ROUTINE";
+		case OBJECT_RULE:
+			return "RULE";
+		case OBJECT_SCHEMA:
+			return "SCHEMA";
+		case OBJECT_SEQUENCE:
+			return "SEQUENCE";
+		case OBJECT_STATISTIC_EXT:
+			return "STATISTICS";
+		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_USER_MAPPING:
+			return "USER MAPPING";
+		case OBJECT_VIEW:
+			return "VIEW";
+		case OBJECT_ACCESS_METHOD:
+		case OBJECT_AMOP:
+		case OBJECT_AMPROC:
+		case OBJECT_ATTRIBUTE:
+		case OBJECT_DEFAULT:
+		case OBJECT_DEFACL:
+		case OBJECT_DOMCONSTRAINT:
+		case OBJECT_PARAMETER_ACL:
+		case OBJECT_PUBLICATION:
+		case OBJECT_PUBLICATION_NAMESPACE:
+		case OBJECT_PUBLICATION_REL:
+		case OBJECT_SUBSCRIPTION:
+		case OBJECT_TABCONSTRAINT:
+		case OBJECT_TRANSFORM:
+			elog(ERROR, "unsupported object type %d", objtype);
+	}
+
+	return "???";				/* keep compiler quiet */
+}
 
 /*
  * AlterObjectTypeCommandTag
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index 12402a0..7b476ad 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -27,8 +27,6 @@
 #include "utils/numeric.h"
 #include "utils/syscache.h"
 
-static char *printTypmod(const char *typname, int32 typmod, Oid typmodout);
-
 
 /*
  * SQL function: format_type(type_oid, typemod)
@@ -363,7 +361,7 @@ format_type_with_typemod(Oid type_oid, int32 typemod)
 /*
  * Add typmod decoration to the basic type name
  */
-static char *
+char *
 printTypmod(const char *typname, int32 typmod, Oid typmodout)
 {
 	char	   *res;
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 296930e..ce5e3a7 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -49,7 +49,6 @@ static bool parseNameAndArgTypes(const char *string, bool allowNone,
 								 List **names, int *nargs, Oid *argtypes,
 								 Node *escontext);
 
-
 /*****************************************************************************
  *	 USER I/O ROUTINES														 *
  *****************************************************************************/
@@ -308,6 +307,57 @@ format_procedure_qualified(Oid procedure_oid)
 }
 
 /*
+ * Append the parenthesized arguments of the given pg_proc row into the output
+ * buffer. force_qualify indicates whether to schema-qualify type names
+ * regardless of visibility.
+ */
+static void
+format_procedure_args_internal(Form_pg_proc procform, StringInfo buf,
+							   bool force_qualify)
+{
+	int			i;
+	char	   *(*func[2]) (Oid) = {format_type_be, format_type_be_qualified};
+
+	appendStringInfoChar(buf, '(');
+	for (i = 0; i < procform->pronargs; i++)
+	{
+		Oid			thisargtype = procform->proargtypes.values[i];
+		char	   *argtype;
+
+		if (i > 0)
+			appendStringInfoChar(buf, ',');
+
+		argtype = func[force_qualify] (thisargtype);
+		appendStringInfoString(buf, argtype);
+		pfree(argtype);
+	}
+	appendStringInfoChar(buf, ')');
+}
+
+/*
+ * format_procedure_args   - converts proc OID to "(args)"
+ */
+char *
+format_procedure_args(Oid procedure_oid, bool force_qualify)
+{
+	StringInfoData buf;
+	HeapTuple	proctup;
+	Form_pg_proc procform;
+
+	proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procedure_oid));
+	if (!HeapTupleIsValid(proctup))
+		elog(ERROR, "cache lookup failed for procedure %u", procedure_oid);
+	procform = (Form_pg_proc) GETSTRUCT(proctup);
+
+	initStringInfo(&buf);
+	format_procedure_args_internal(procform, &buf, force_qualify);
+
+	ReleaseSysCache(proctup);
+
+	return buf.data;
+}
+
+/*
  * format_procedure_extended - converts procedure OID to "pro_name(args)"
  *
  * This exports the useful functionality of regprocedureout for use
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index bcb493b..6402aca 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -35,6 +35,7 @@
 #include "catalog/pg_operator.h"
 #include "catalog/pg_partitioned_table.h"
 #include "catalog/pg_proc.h"
+#include "catalog/pg_rewrite.h"
 #include "catalog/pg_statistic_ext.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_type.h"
@@ -341,6 +342,8 @@ static char *pg_get_triggerdef_worker(Oid trigid, bool pretty);
 static int	decompile_column_index_array(Datum column_index_array, Oid relId,
 										 StringInfo buf);
 static char *pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
+static void pg_get_rule_whereclause(char *qualstr, Query *query,
+									 StringInfo buf, int prettyFlags);
 static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
 									const Oid *excludeOps,
 									bool attrsOnly, bool keysOnly,
@@ -358,7 +361,6 @@ static int	print_function_arguments(StringInfo buf, HeapTuple proctup,
 									 bool print_table_args, bool print_defaults);
 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
 static void print_function_trftypes(StringInfo buf, HeapTuple proctup);
-static void print_function_sqlbody(StringInfo buf, HeapTuple proctup);
 static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
 							 Bitmapset *rels_used);
 static void set_deparse_for_query(deparse_namespace *dpns, Query *query,
@@ -484,22 +486,15 @@ static void get_from_clause_coldeflist(RangeTblFunction *rtfunc,
 									   deparse_context *context);
 static void get_tablesample_def(TableSampleClause *tablesample,
 								deparse_context *context);
-static void get_opclass_name(Oid opclass, Oid actual_datatype,
-							 StringInfo buf);
 static Node *processIndirection(Node *node, deparse_context *context);
 static void printSubscripts(SubscriptingRef *sbsref, deparse_context *context);
 static char *get_relation_name(Oid relid);
 static char *generate_relation_name(Oid relid, List *namespaces);
 static char *generate_qualified_relation_name(Oid relid);
-static char *generate_function_name(Oid funcid, int nargs,
-									List *argnames, Oid *argtypes,
-									bool has_variadic, bool *use_variadic_p,
-									ParseExprKind special_exprkind);
 static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
 static void add_cast_to(StringInfo buf, Oid typid);
 static char *generate_qualified_type_name(Oid typid);
 static text *string_to_text(char *str);
-static char *flatten_reloptions(Oid relid);
 static void get_reloptions(StringInfo buf, Datum reloptions);
 
 #define only_marker(rte)  ((rte)->inh ? "" : "ONLY ")
@@ -547,6 +542,80 @@ pg_get_ruledef_ext(PG_FUNCTION_ARGS)
 	PG_RETURN_TEXT_P(string_to_text(res));
 }
 
+/*
+ * Given a pair of Datum corresponding to a rule's pg_rewrite.ev_qual and
+ * ev_action columns, return their text representation; ev_qual as a single
+ * string in whereClause and ev_action as a List of strings (which might be
+ * NIL, signalling NOTHING) in actions.
+ */
+void
+pg_get_ruledef_detailed(Datum ev_qual, Datum ev_action,
+						char **whereClause, List **actions)
+{
+	int			prettyFlags = 0;
+	char	   *qualstr = TextDatumGetCString(ev_qual);
+	char	   *actionstr = TextDatumGetCString(ev_action);
+	List	   *actionNodeList = (List *) stringToNode(actionstr);
+	StringInfoData buf;
+
+	*whereClause = NULL;
+	*actions = NIL;
+	initStringInfo(&buf);
+
+	if (strcmp(qualstr, "<>") != 0)
+	{
+		Query	   *query = (Query *) linitial(actionNodeList);
+
+		pg_get_rule_whereclause(qualstr, query, &buf, 0);
+		*whereClause = pstrdup(buf.data);
+	}
+
+	if (list_length(actionNodeList) > 0)
+	{
+		ListCell   *cell;
+
+		foreach(cell, actionNodeList)
+		{
+			Query	   *query = (Query *) lfirst(cell);
+
+			resetStringInfo(&buf);
+			get_query_def(query, &buf, NIL, NULL, true,
+						  prettyFlags, WRAP_COLUMN_DEFAULT, 0);
+			*actions = lappend(*actions, pstrdup(buf.data));
+		}
+	}
+}
+
+/*
+ * To get the rewrite rule of a view when the CREATE VIEW command execution is
+ * still in progress: we search the system cache RULERELNAME to get the rewrite
+ * rule of the view as opposed to querying pg_rewrite as in pg_get_viewdef_worker(),
+ * which will return empty result.
+ */
+char *
+pg_get_viewdef_string(Oid viewoid)
+{
+	StringInfoData buf;
+	Relation	pg_rewrite;
+	HeapTuple	ruletup;
+	TupleDesc	rulettc;
+
+	initStringInfo(&buf);
+	pg_rewrite = table_open(RewriteRelationId, AccessShareLock);
+
+	ruletup = SearchSysCache2(RULERELNAME,
+							  ObjectIdGetDatum(viewoid),
+							  PointerGetDatum(ViewSelectRuleName));
+	if (!HeapTupleIsValid(ruletup))
+		elog(ERROR, "cache lookup failed for rewrite rule for view with OID %u", viewoid);
+
+	rulettc = pg_rewrite->rd_att;
+	make_viewdef(&buf, ruletup, rulettc, 0, WRAP_COLUMN_DEFAULT);
+	ReleaseSysCache(ruletup);
+	table_close(pg_rewrite, AccessShareLock);
+
+	return buf.data;
+}
 
 static char *
 pg_get_ruledef_worker(Oid ruleoid, int prettyFlags)
@@ -1017,65 +1086,12 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
 	if (!isnull)
 	{
 		Node	   *qual;
-		char		relkind;
-		deparse_context context;
-		deparse_namespace dpns;
-		RangeTblEntry *oldrte;
-		RangeTblEntry *newrte;
-
-		appendStringInfoString(&buf, "WHEN (");
+		char	   *qualstr;
 
 		qual = stringToNode(TextDatumGetCString(value));
+		qualstr = pg_get_trigger_whenclause(trigrec, qual, pretty);
 
-		relkind = get_rel_relkind(trigrec->tgrelid);
-
-		/* Build minimal OLD and NEW RTEs for the rel */
-		oldrte = makeNode(RangeTblEntry);
-		oldrte->rtekind = RTE_RELATION;
-		oldrte->relid = trigrec->tgrelid;
-		oldrte->relkind = relkind;
-		oldrte->rellockmode = AccessShareLock;
-		oldrte->alias = makeAlias("old", NIL);
-		oldrte->eref = oldrte->alias;
-		oldrte->lateral = false;
-		oldrte->inh = false;
-		oldrte->inFromCl = true;
-
-		newrte = makeNode(RangeTblEntry);
-		newrte->rtekind = RTE_RELATION;
-		newrte->relid = trigrec->tgrelid;
-		newrte->relkind = relkind;
-		newrte->rellockmode = AccessShareLock;
-		newrte->alias = makeAlias("new", NIL);
-		newrte->eref = newrte->alias;
-		newrte->lateral = false;
-		newrte->inh = false;
-		newrte->inFromCl = true;
-
-		/* Build two-element rtable */
-		memset(&dpns, 0, sizeof(dpns));
-		dpns.rtable = list_make2(oldrte, newrte);
-		dpns.subplans = NIL;
-		dpns.ctes = NIL;
-		dpns.appendrels = NULL;
-		set_rtable_names(&dpns, NIL, NULL);
-		set_simple_column_names(&dpns);
-
-		/* Set up context with one-deep namespace stack */
-		context.buf = &buf;
-		context.namespaces = list_make1(&dpns);
-		context.windowClause = NIL;
-		context.windowTList = NIL;
-		context.varprefix = true;
-		context.prettyFlags = GET_PRETTY_FLAGS(pretty);
-		context.wrapColumn = WRAP_COLUMN_DEFAULT;
-		context.indentLevel = PRETTYINDENT_STD;
-		context.special_exprkind = EXPR_KIND_NONE;
-		context.appendparents = NULL;
-
-		get_rule_expr(qual, &context, false);
-
-		appendStringInfoString(&buf, ") ");
+		appendStringInfo(&buf, "WHEN (%s) ", qualstr);
 	}
 
 	appendStringInfo(&buf, "EXECUTE FUNCTION %s(",
@@ -1116,6 +1132,74 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
 	return buf.data;
 }
 
+/*
+ * Pass back the TriggerWhen clause of a trigger given the pg_trigger record and
+ * the expression tree (in nodeToString() representation) from pg_trigger.tgqual
+ * for the trigger's WHEN condition.
+ */
+char *
+pg_get_trigger_whenclause(Form_pg_trigger trigrec, Node *whenClause, bool pretty)
+{
+	StringInfoData buf;
+	char		relkind;
+	deparse_context context;
+	deparse_namespace dpns;
+	RangeTblEntry *oldrte;
+	RangeTblEntry *newrte;
+
+	initStringInfo(&buf);
+
+	relkind = get_rel_relkind(trigrec->tgrelid);
+
+	/* Build minimal OLD and NEW RTEs for the rel */
+	oldrte = makeNode(RangeTblEntry);
+	oldrte->rtekind = RTE_RELATION;
+	oldrte->relid = trigrec->tgrelid;
+	oldrte->relkind = relkind;
+	oldrte->rellockmode = AccessShareLock;
+	oldrte->alias = makeAlias("old", NIL);
+	oldrte->eref = oldrte->alias;
+	oldrte->lateral = false;
+	oldrte->inh = false;
+	oldrte->inFromCl = true;
+
+	newrte = makeNode(RangeTblEntry);
+	newrte->rtekind = RTE_RELATION;
+	newrte->relid = trigrec->tgrelid;
+	newrte->relkind = relkind;
+	newrte->rellockmode = AccessShareLock;
+	newrte->alias = makeAlias("new", NIL);
+	newrte->eref = newrte->alias;
+	newrte->lateral = false;
+	newrte->inh = false;
+	newrte->inFromCl = true;
+
+	/* Build two-element rtable */
+	memset(&dpns, 0, sizeof(dpns));
+	dpns.rtable = list_make2(oldrte, newrte);
+	dpns.subplans = NIL;
+	dpns.ctes = NIL;
+	dpns.appendrels = NULL;
+	set_rtable_names(&dpns, NIL, NULL);
+	set_simple_column_names(&dpns);
+
+	/* Set up context with one-deep namespace stack */
+	context.buf = &buf;
+	context.namespaces = list_make1(&dpns);
+	context.windowClause = NIL;
+	context.windowTList = NIL;
+	context.varprefix = true;
+	context.prettyFlags = GET_PRETTY_FLAGS(pretty);
+	context.wrapColumn = WRAP_COLUMN_DEFAULT;
+	context.indentLevel = PRETTYINDENT_STD;
+	context.special_exprkind = EXPR_KIND_NONE;
+	context.appendparents = NULL;
+
+	get_rule_expr(whenClause, &context, false);
+
+	return buf.data;
+}
+
 /* ----------
  * pg_get_indexdef			- Get the definition of an index
  *
@@ -1882,6 +1966,14 @@ pg_get_partkeydef_columns(Oid relid, bool pretty)
 	return pg_get_partkeydef_worker(relid, prettyFlags, true, false);
 }
 
+/* Internal version that reports the full partition key definition */
+char *
+pg_get_partkeydef_string(Oid relid)
+{
+	return pg_get_partkeydef_worker(relid, GET_PRETTY_FLAGS(false), false,
+									false);
+}
+
 /*
  * Internal workhorse to decompile a partition key definition.
  */
@@ -2134,6 +2226,16 @@ pg_get_constraintdef_ext(PG_FUNCTION_ARGS)
 }
 
 /*
+ * Internal version that returns the definition of a CONSTRAINT command
+ */
+char *
+pg_get_constraintdef_string(Oid constraintId)
+{
+	return pg_get_constraintdef_worker(constraintId, false,
+									   GET_PRETTY_FLAGS(false), false);
+}
+
+/*
  * Internal version that returns a full ALTER TABLE ... ADD CONSTRAINT command
  */
 char *
@@ -3503,7 +3605,12 @@ pg_get_function_arg_default(PG_FUNCTION_ARGS)
 	PG_RETURN_TEXT_P(string_to_text(str));
 }
 
-static void
+/*
+ * Produce the formatted SQL body (not the whole function definition)
+ * of a function given the pg_proc tuple. Save the formatted SQL in the
+ * given StringInfo.
+ */
+void
 print_function_sqlbody(StringInfo buf, HeapTuple proctup)
 {
 	int			numargs;
@@ -5250,48 +5357,18 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
 	/* If the rule has an event qualification, add it */
 	if (strcmp(ev_qual, "<>") != 0)
 	{
-		Node	   *qual;
-		Query	   *query;
-		deparse_context context;
-		deparse_namespace dpns;
-
-		if (prettyFlags & PRETTYFLAG_INDENT)
-			appendStringInfoString(buf, "\n  ");
-		appendStringInfoString(buf, " WHERE ");
-
-		qual = stringToNode(ev_qual);
-
 		/*
 		 * We need to make a context for recognizing any Vars in the qual
 		 * (which can only be references to OLD and NEW).  Use the rtable of
 		 * the first query in the action list for this purpose.
 		 */
-		query = (Query *) linitial(actions);
+		Query	   *query = (Query *) linitial(actions);
 
-		/*
-		 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
-		 * into the SELECT, and that's what we need to look at. (Ugly kluge
-		 * ... try to fix this when we redesign querytrees.)
-		 */
-		query = getInsertSelectQuery(query, NULL);
-
-		/* Must acquire locks right away; see notes in get_query_def() */
-		AcquireRewriteLocks(query, false, false);
-
-		context.buf = buf;
-		context.namespaces = list_make1(&dpns);
-		context.windowClause = NIL;
-		context.windowTList = NIL;
-		context.varprefix = (list_length(query->rtable) != 1);
-		context.prettyFlags = prettyFlags;
-		context.wrapColumn = WRAP_COLUMN_DEFAULT;
-		context.indentLevel = PRETTYINDENT_STD;
-		context.special_exprkind = EXPR_KIND_NONE;
-		context.appendparents = NULL;
-
-		set_deparse_for_query(&dpns, query, NIL);
+		if (prettyFlags & PRETTYFLAG_INDENT)
+			appendStringInfoString(buf, "\n  ");
+		appendStringInfoString(buf, " WHERE ");
 
-		get_rule_expr(qual, &context, false);
+		pg_get_rule_whereclause(ev_qual, query, buf, prettyFlags);
 	}
 
 	appendStringInfoString(buf, " DO ");
@@ -5332,6 +5409,47 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
 	table_close(ev_relation, AccessShareLock);
 }
 
+/*
+ * Given a string corresponding to a rule's pg_rewrite.ev_qual and a query
+ * parsetree, append ev_qual's text representation into the output buf.
+ *
+ * Tries to pretty up the output according to prettyFlags.
+ */
+static void
+pg_get_rule_whereclause(char *qualstr, Query *query, StringInfo buf,
+						int prettyFlags)
+{
+	Node	   *qual;
+	deparse_context context;
+	deparse_namespace dpns;
+
+	qual = stringToNode(qualstr);
+
+	/*
+	 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
+	 * into the SELECT, and that's what we need to look at. (Ugly kluge
+	 * ... try to fix this when we redesign querytrees.)
+	 */
+	query = getInsertSelectQuery(query, NULL);
+
+	/* Must acquire locks right away; see notes in get_query_def() */
+	AcquireRewriteLocks(query, false, false);
+
+	context.buf = buf;
+	context.namespaces = list_make1(&dpns);
+	context.windowClause = NIL;
+	context.windowTList = NIL;
+	context.varprefix = (list_length(query->rtable) != 1);
+	context.prettyFlags = prettyFlags;
+	context.wrapColumn = WRAP_COLUMN_DEFAULT;
+	context.indentLevel = PRETTYINDENT_STD;
+	context.special_exprkind = EXPR_KIND_NONE;
+	context.appendparents = NULL;
+
+	set_deparse_for_query(&dpns, query, NIL);
+
+	get_rule_expr(qual, &context, false);
+}
 
 /* ----------
  * make_viewdef			- reconstruct the SELECT part of a
@@ -11379,7 +11497,7 @@ get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
  * actual_datatype.  (If you don't want this behavior, just pass
  * InvalidOid for actual_datatype.)
  */
-static void
+void
 get_opclass_name(Oid opclass, Oid actual_datatype,
 				 StringInfo buf)
 {
@@ -11773,7 +11891,7 @@ generate_qualified_relation_name(Oid relid)
  *
  * The result includes all necessary quoting and schema-prefixing.
  */
-static char *
+char *
 generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
 					   bool has_variadic, bool *use_variadic_p,
 					   ParseExprKind special_exprkind)
@@ -12159,7 +12277,7 @@ get_reloptions(StringInfo buf, Datum reloptions)
 /*
  * Generate a C string representing a relation's reloptions, or NULL if none.
  */
-static char *
+char *
 flatten_reloptions(Oid relid)
 {
 	char	   *result = NULL;
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index 6ecaa2a..715f2a2 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -18,8 +18,8 @@
 #define PG_PUBLICATION_H
 
 #include "catalog/genbki.h"
-#include "catalog/objectaddress.h"
 #include "catalog/pg_publication_d.h"
+#include "nodes/pg_list.h"
 
 /* ----------------
  *		pg_publication definition.  cpp turns this into
@@ -103,12 +103,6 @@ typedef struct Publication
 	PublicationActions pubactions;
 } Publication;
 
-typedef struct PublicationRelInfo
-{
-	Relation	relation;
-	Node	   *whereClause;
-	List	   *columns;
-} PublicationRelInfo;
 
 extern Publication *GetPublication(Oid pubid);
 extern Publication *GetPublicationByName(const char *pubname, bool missing_ok);
@@ -144,15 +138,6 @@ extern List *GetPubPartitionOptionRelations(List *result,
 											Oid relid);
 extern Oid	GetTopMostAncestorInPublication(Oid puboid, List *ancestors,
 											int *ancestor_level);
-
-extern bool is_publishable_relation(Relation rel);
 extern bool is_schema_publication(Oid pubid);
-extern ObjectAddress publication_add_relation(Oid pubid, PublicationRelInfo *pri,
-											  bool if_not_exists);
-extern ObjectAddress publication_add_schema(Oid pubid, Oid schemaid,
-											bool if_not_exists);
-
-extern Bitmapset *pub_collist_to_bitmapset(Bitmapset *columns, Datum pubcols,
-										   MemoryContext mcxt);
 
 #endif							/* PG_PUBLICATION_H */
diff --git a/src/include/commands/collationcmds.h b/src/include/commands/collationcmds.h
index b76c7b3..53c4a1a 100644
--- a/src/include/commands/collationcmds.h
+++ b/src/include/commands/collationcmds.h
@@ -18,7 +18,8 @@
 #include "catalog/objectaddress.h"
 #include "parser/parse_node.h"
 
-extern ObjectAddress DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists);
+extern ObjectAddress DefineCollation(ParseState *pstate, List *names, List *parameters,
+									  bool if_not_exists, ObjectAddress *from_collid);
 extern void IsThereCollationInNamespace(const char *collname, Oid nspOid);
 extern ObjectAddress AlterCollation(AlterCollationStmt *stmt);
 
diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h
index 5ed6ece..a97e8b7 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
@@ -84,5 +123,7 @@ extern void EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt,
 extern void EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt,
 											 Oid cfgId, Oid *dictIds, int ndicts);
 extern void EventTriggerCollectAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt);
+extern void EventTriggerCollectSecLabel(ObjectAddress address, char *provider,
+										SecLabelStmt *stmt);
 
 #endif							/* EVENT_TRIGGER_H */
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
index 70d5e36..a3fca9e 100644
--- a/src/include/commands/publicationcmds.h
+++ b/src/include/commands/publicationcmds.h
@@ -22,6 +22,13 @@
 /* Same as MAXNUMMESSAGES in sinvaladt.c */
 #define MAX_RELCACHE_INVAL_MSGS 4096
 
+typedef struct PublicationRelInfo
+{
+	Relation	relation;
+	Node	   *whereClause;
+	List	   *columns;
+} PublicationRelInfo;
+
 extern ObjectAddress CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt);
 extern void AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt);
 extern void RemovePublicationById(Oid pubid);
@@ -35,5 +42,12 @@ extern bool pub_rf_contains_invalid_column(Oid pubid, Relation relation,
 										   List *ancestors, bool pubviaroot);
 extern bool pub_collist_contains_invalid_column(Oid pubid, Relation relation,
 												List *ancestors, bool pubviaroot);
+extern Bitmapset *pub_collist_to_bitmapset(Bitmapset *columns, Datum pubcols,
+										   MemoryContext mcxt);
+extern ObjectAddress publication_add_relation(Oid pubid, PublicationRelInfo *pri,
+											  bool if_not_exists);
+extern ObjectAddress publication_add_schema(Oid pubid, Oid schemaid,
+											bool if_not_exists);
+extern bool is_publishable_relation(Relation rel);
 
 #endif							/* PUBLICATIONCMDS_H */
diff --git a/src/include/commands/sequence.h b/src/include/commands/sequence.h
index 7db7b3d..c0a3959 100644
--- a/src/include/commands/sequence.h
+++ b/src/include/commands/sequence.h
@@ -15,6 +15,7 @@
 
 #include "access/xlogreader.h"
 #include "catalog/objectaddress.h"
+#include "catalog/pg_sequence.h"
 #include "fmgr.h"
 #include "lib/stringinfo.h"
 #include "nodes/parsenodes.h"
@@ -51,9 +52,17 @@ typedef struct xl_seq_rec
 	/* SEQUENCE TUPLE DATA FOLLOWS AT THE END */
 } xl_seq_rec;
 
+/* Information needed to define a sequence. */
+typedef struct Sequence_values
+{
+	Form_pg_sequence seqform;
+	int64		last_value;
+} Sequence_values;
+
 extern int64 nextval_internal(Oid relid, bool check_permissions);
 extern Datum nextval(PG_FUNCTION_ARGS);
 extern List *sequence_options(Oid relid);
+extern Sequence_values *get_sequence_values(Oid sequenceId);
 
 extern ObjectAddress DefineSequence(ParseState *pstate, CreateSeqStmt *seq);
 extern ObjectAddress AlterSequence(ParseState *pstate, AlterSeqStmt *stmt);
diff --git a/src/include/tcop/deparse_utility.h b/src/include/tcop/deparse_utility.h
index b585810..a1e06da 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_SecurityLabel
 } CollectedCommandType;
 
 /*
@@ -100,6 +101,13 @@ typedef struct CollectedCommand
 		{
 			ObjectType	objtype;
 		}			defprivs;
+
+		/* SECURITY LABEL */
+		struct
+		{
+			ObjectAddress address;
+			char		 *provider;
+		}			seclabel;
 	}			d;
 
 	struct CollectedCommand *parent;	/* when nested */
diff --git a/src/include/tcop/utility.h b/src/include/tcop/utility.h
index 59e64ae..a68ce3d 100644
--- a/src/include/tcop/utility.h
+++ b/src/include/tcop/utility.h
@@ -99,6 +99,8 @@ extern Query *UtilityContainsQuery(Node *parsetree);
 
 extern CommandTag CreateCommandTag(Node *parsetree);
 
+extern const char *stringify_objtype(ObjectType objtype, bool isgrant);
+
 static inline const char *
 CreateCommandName(Node *parsetree)
 {
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index f8e1238..f05578d 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -209,6 +209,8 @@ extern AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId,
 					   AclMode mask, AclMaskHow how);
 extern int	aclmembers(const Acl *acl, Oid **roleids);
 
+extern const char *privilege_to_string(AclMode privilege);
+
 extern bool has_privs_of_role(Oid member, Oid role);
 extern bool member_can_set_role(Oid member, Oid role);
 extern void check_can_set_role(Oid member, Oid role);
diff --git a/src/include/utils/aclchk_internal.h b/src/include/utils/aclchk_internal.h
index 55af624..946545f 100644
--- a/src/include/utils/aclchk_internal.h
+++ b/src/include/utils/aclchk_internal.h
@@ -39,6 +39,7 @@ typedef struct
 	List	   *grantees;
 	bool		grant_option;
 	DropBehavior behavior;
+	Oid			grantor_uid;
 } InternalGrant;
 
 
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 2f8b46d..48b8bfd 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -123,10 +123,12 @@ extern Datum numeric_float8_no_overflow(PG_FUNCTION_ARGS);
 #define FORMAT_TYPE_FORCE_QUALIFY	0x04	/* force qualification of type */
 #define FORMAT_TYPE_INVALID_AS_NULL	0x08	/* NULL if undefined */
 extern char *format_type_extended(Oid type_oid, int32 typemod, bits16 flags);
+extern char *format_procedure_args(Oid procedure_oid, bool force_qualify);
 
 extern char *format_type_be(Oid type_oid);
 extern char *format_type_be_qualified(Oid type_oid);
 extern char *format_type_with_typemod(Oid type_oid, int32 typemod);
+extern char *printTypmod(const char *typname, int32 typmod, Oid typmodout);
 
 extern int32 type_maximum_size(Oid type_oid, int32 typemod);
 
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 67f994c..22ca7a8 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -16,10 +16,12 @@
 
 #include "access/tupdesc.h"
 #include "access/xlog.h"
+#include "catalog/objectaddress.h"
 #include "catalog/pg_class.h"
 #include "catalog/pg_index.h"
 #include "catalog/pg_publication.h"
 #include "nodes/bitmapset.h"
+#include "nodes/lockoptions.h"
 #include "partitioning/partdefs.h"
 #include "rewrite/prs2lock.h"
 #include "storage/block.h"
diff --git a/src/include/utils/ruleutils.h b/src/include/utils/ruleutils.h
index 1a42d9f..b6e20e7 100644
--- a/src/include/utils/ruleutils.h
+++ b/src/include/utils/ruleutils.h
@@ -13,9 +13,12 @@
 #ifndef RULEUTILS_H
 #define RULEUTILS_H
 
+#include "access/htup.h"
+#include "catalog/pg_trigger.h"
 #include "nodes/nodes.h"
 #include "nodes/parsenodes.h"
 #include "nodes/pg_list.h"
+#include "parser/parse_node.h"
 
 struct Plan;					/* avoid including plannodes.h here */
 struct PlannedStmt;
@@ -23,12 +26,20 @@ struct PlannedStmt;
 
 extern char *pg_get_indexdef_string(Oid indexrelid);
 extern char *pg_get_indexdef_columns(Oid indexrelid, bool pretty);
+extern char *pg_get_trigger_whenclause(Form_pg_trigger trigrec,
+									   Node *whenClause, bool pretty);
 extern char *pg_get_querydef(Query *query, bool pretty);
+extern char *pg_get_viewdef_string(Oid viewoid);
 
 extern char *pg_get_partkeydef_columns(Oid relid, bool pretty);
+extern char *pg_get_partkeydef_string(Oid relid);
 extern char *pg_get_partconstrdef_string(Oid partitionId, char *aliasname);
 
 extern char *pg_get_constraintdef_command(Oid constraintId);
+extern char *pg_get_constraintdef_string(Oid constraintId);
+extern void pg_get_ruledef_detailed(Datum ev_qual, Datum ev_action,
+									char **whereClause, List **actions);
+
 extern char *deparse_expression(Node *expr, List *dpcontext,
 								bool forceprefix, bool showimplicit);
 extern List *deparse_context_for(const char *aliasname, Oid relid);
@@ -40,8 +51,16 @@ extern List *select_rtable_names_for_explain(List *rtable,
 											 Bitmapset *rels_used);
 extern char *generate_collation_name(Oid collid);
 extern char *generate_opclass_name(Oid opclass);
+extern char *generate_function_name(Oid funcid, int nargs, List *argnames,
+									Oid *argtypes, bool has_variadic,
+									bool *use_variadic_p,
+									ParseExprKind special_exprkind);
 extern char *get_range_partbound_string(List *bound_datums);
+extern void get_opclass_name(Oid opclass, Oid actual_datatype,
+							 StringInfo buf);
+extern char *flatten_reloptions(Oid relid);
 
 extern char *pg_get_statisticsobjdef_string(Oid statextid);
+extern void print_function_sqlbody(StringInfo buf, HeapTuple proctup);
 
 #endif							/* RULEUTILS_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 86a9303..428689a 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2458,6 +2458,7 @@ SeqScan
 SeqScanState
 SeqTable
 SeqTableData
+Sequence_values
 SerCommitSeqNo
 SerialControl
 SerializableXactHandle
-- 
1.8.3.1



  [application/octet-stream] v80-0004-Introduce-the-test_ddl_deparse_regress-test-modu.patch (919.0K, 4-v80-0004-Introduce-the-test_ddl_deparse_regress-test-modu.patch)
  download | inline diff:
From a12c86ea7010e75960acca296d7981717b8327df Mon Sep 17 00:00:00 2001
From: Ajin Cherian <ajinc@fast.au.fujitsu.com>
Date: Mon, 13 Mar 2023 23:52:10 -0400
Subject: [PATCH v80 4/8] Introduce the test_ddl_deparse_regress test module.

This testing module aims to achieve the following four testing goals for the DDL deparser:
1. Test that the generated JSON blob is expected using SQL tests.
2. Test that the re-formed DDL command is expected using SQL tests.
3. Test that the re-formed DDL command has the same effect as the original command by comparing
   the results of pg_dump, using the SQL tests in 1 and 2.
4. Test that new DDL syntax is handled by the DDL deparser by capturing and deparing DDL commands
   ran by pg_regress.

1 and 2 is tested with SQL tests, by printing the deparsed JSON blob and the re-formed command.

Goal 3 is tested with TAP framework in t/001_compare_dumped_results.pl, see README for details.

Goal 4 is tested with TAP framework and pg_regress in 002_regress_tests.pl, the execution is currently commented out because it will fail due unimplemented commands in the DDL deparser.

Test coverage is added for:
CREATE TABLE
ALTER TABLE
column constraints/table constraints
---
 src/test/modules/Makefile                          |   1 +
 .../modules/test_ddl_deparse_regress/.gitignore    |   4 +
 src/test/modules/test_ddl_deparse_regress/Makefile |  46 +
 .../modules/test_ddl_deparse_regress/README.md     |  38 +
 .../expected/aggregate.out                         |   8 +
 .../expected/alter_table.out                       | 924 +++++++++++++++++++++
 .../expected/constraints.out                       | 638 ++++++++++++++
 .../expected/create_extension.out                  |   6 +
 .../expected/create_schema.out                     |  22 +
 .../expected/create_table.out                      | 599 +++++++++++++
 .../expected/test_ddl_deparse.out                  |  20 +
 .../modules/test_ddl_deparse_regress/meson.build   |  45 +
 .../test_ddl_deparse_regress/sql/aggregate.sql     |   7 +
 .../test_ddl_deparse_regress/sql/alter_table.sql   | 524 ++++++++++++
 .../test_ddl_deparse_regress/sql/constraints.sql   | 385 +++++++++
 .../sql/create_extension.sql                       |   5 +
 .../test_ddl_deparse_regress/sql/create_schema.sql |  16 +
 .../test_ddl_deparse_regress/sql/create_table.sql  | 417 ++++++++++
 .../sql/test_ddl_deparse.sql                       |  23 +
 .../t/001_compare_dumped_results.pl                | 211 +++++
 .../t/002_regress_tests.pl                         | 207 +++++
 .../test_ddl_deparse_regress--1.0.sql              |   9 +
 .../test_ddl_deparse_regress.c                     |  59 ++
 .../test_ddl_deparse_regress.control               |   4 +
 24 files changed, 4218 insertions(+)
 create mode 100644 src/test/modules/test_ddl_deparse_regress/.gitignore
 create mode 100644 src/test/modules/test_ddl_deparse_regress/Makefile
 create mode 100644 src/test/modules/test_ddl_deparse_regress/README.md
 create mode 100644 src/test/modules/test_ddl_deparse_regress/expected/aggregate.out
 create mode 100644 src/test/modules/test_ddl_deparse_regress/expected/alter_table.out
 create mode 100644 src/test/modules/test_ddl_deparse_regress/expected/constraints.out
 create mode 100644 src/test/modules/test_ddl_deparse_regress/expected/create_extension.out
 create mode 100644 src/test/modules/test_ddl_deparse_regress/expected/create_schema.out
 create mode 100644 src/test/modules/test_ddl_deparse_regress/expected/create_table.out
 create mode 100644 src/test/modules/test_ddl_deparse_regress/expected/test_ddl_deparse.out
 create mode 100644 src/test/modules/test_ddl_deparse_regress/meson.build
 create mode 100644 src/test/modules/test_ddl_deparse_regress/sql/aggregate.sql
 create mode 100644 src/test/modules/test_ddl_deparse_regress/sql/alter_table.sql
 create mode 100644 src/test/modules/test_ddl_deparse_regress/sql/constraints.sql
 create mode 100644 src/test/modules/test_ddl_deparse_regress/sql/create_extension.sql
 create mode 100644 src/test/modules/test_ddl_deparse_regress/sql/create_schema.sql
 create mode 100644 src/test/modules/test_ddl_deparse_regress/sql/create_table.sql
 create mode 100644 src/test/modules/test_ddl_deparse_regress/sql/test_ddl_deparse.sql
 create mode 100644 src/test/modules/test_ddl_deparse_regress/t/001_compare_dumped_results.pl
 create mode 100644 src/test/modules/test_ddl_deparse_regress/t/002_regress_tests.pl
 create mode 100644 src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress--1.0.sql
 create mode 100644 src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress.c
 create mode 100644 src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress.control

diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index c629cbe..c272c64 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -18,6 +18,7 @@ SUBDIRS = \
 		  test_copy_callbacks \
 		  test_custom_rmgrs \
 		  test_ddl_deparse \
+		  test_ddl_deparse_regress \
 		  test_extensions \
 		  test_ginpostinglist \
 		  test_integerset \
diff --git a/src/test/modules/test_ddl_deparse_regress/.gitignore b/src/test/modules/test_ddl_deparse_regress/.gitignore
new file mode 100644
index 0000000..5dcb3ff
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/src/test/modules/test_ddl_deparse_regress/Makefile b/src/test/modules/test_ddl_deparse_regress/Makefile
new file mode 100644
index 0000000..84cc108
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/Makefile
@@ -0,0 +1,46 @@
+#-------------------------------------------------------------------------
+#
+# Makefile for src/test/modules/test_ddl_deparse_regress
+#
+# Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/test/modules/test_ddl_deparse_regress/Makefile
+#
+#-------------------------------------------------------------------------
+
+
+MODULES = test_ddl_deparse_regress
+PGFILEDESC = "test_ddl_deparse_regress - regression testing for DDL deparsing"
+
+EXTENSION = test_ddl_deparse_regress
+DATA = test_ddl_deparse_regress--1.0.sql
+
+# test_ddl_deparse must be first
+REGRESS = test_ddl_deparse \
+	create_extension \
+	create_schema \
+	aggregate \
+	create_table \
+	constraints \
+	alter_table
+
+export REGRESS
+
+EXTRA_INSTALL = contrib/pg_stat_statements
+
+TAP_TESTS = 1
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_ddl_deparse_regress
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
+
+REGRESS_SHLIB=$(abs_top_builddir)/src/test/regress/regress$(DLSUFFIX)
+export REGRESS_SHLIB
diff --git a/src/test/modules/test_ddl_deparse_regress/README.md b/src/test/modules/test_ddl_deparse_regress/README.md
new file mode 100644
index 0000000..e261319
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/README.md
@@ -0,0 +1,38 @@
+# Testing harness for DDL deparser
+
+## Testing goals
+
+DDL Deparser provides the ability to encode the original DDL command to a JSON string, then decode it to a fully schema-qualified DDL command which is supposed to have the same effect as the original command. This testing module aims to achieve the following four testing for the DDL deparser:
+
+1. Test that the generated JSON blob is expected using SQL tests.
+2. Test that the re-formed DDL command is expected using SQL tests.
+3. Test that the re-formed DDL command has the same effect as the original command
+   by comparing the results of pg_dump, using the SQL tests in 1 and 2.
+4. Test that new DDL syntax is handled by the DDL deparser by capturing and deparing
+   DDL commands ran by pg_regress.
+
+1 and 2 is tested with SQL tests, by noticing the deparsed JSON blob and the re-formed command.
+
+Goal 3 is tested with TAP framework in t/001_compare_dumped_results.pl
+
+Goal 4 is tested with TAP framework and pg_regress in 002_regress_tests.pl (Not enabled)
+
+## Usage
+
+Run `make check`, it will run the SQL tests first, then it will run the TAP tests. The execution of 002_regress_tests.pl is currently commented out because it will fail due to unimplemented commands in the DDL deparser.
+
+## How to add more test cases and find out the failure?
+
+You can add test cases to existed files in `sql` folder directly. If you need to create a new test file, you can create a file in `sql` folder, add that test file name to `meson.build` and `Makefile` following the convention used by other test files.
+
+After you have added you test cases, run `make check` and check goal 1 and goal 2 of the added test cases in `results` folder, if the result is right, copy that file to `expected` folder.
+
+Now SQL tests should pass, run `make check` again to check the TAP tests. If everything passed, this test case also meet goal 3. If it fails, check the error message to locate the failure position.
+
+You can find execution logs are in `tmp_check/log` folder, dumped results are in `tmp_check/dumps` folder, reformed sql commands are in `tmp_check/ddl` folder for further investigation.
+
+
+
+
+
+
diff --git a/src/test/modules/test_ddl_deparse_regress/expected/aggregate.out b/src/test/modules/test_ddl_deparse_regress/expected/aggregate.out
new file mode 100644
index 0000000..1e19a7c
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/expected/aggregate.out
@@ -0,0 +1,8 @@
+CREATE AGGREGATE newavg(int4) (
+   sfunc = int4_avg_accum, stype = _int8,
+   finalfunc = int8_avg,
+   initcond1 = '{0,0}'
+);
+NOTICE:  deparsed json: {"fmt": "CREATE AGGREGATE %{identity}D (%{types}s) (%{elems:, }s)", "elems": [{"fmt": "SFUNC=%{procedure}D", "procedure": {"objname": "int4_avg_accum", "schemaname": "pg_catalog"}}, {"fmt": "STYPE=%{type}T", "type": {"typmod": "", "typarray": true, "typename": "int8", "schemaname": "pg_catalog"}}, {"fmt": "SSPACE=", "present": false}, {"fmt": "FINALFUNC= %{procedure}D", "procedure": {"objname": "int8_avg", "schemaname": "pg_catalog"}}, {"fmt": "FINALFUNC_EXTRA=", "present": false}, {"fmt": "INITCOND= %{initval}L", "initval": "{0,0}"}, {"fmt": "MSFUNC=", "present": false}, {"fmt": "MSTYPE=", "present": false}, {"fmt": "MSSPACE=", "present": false}, {"fmt": "MINVFUNC=", "present": false}, {"fmt": "MFINALFUNC=", "present": false}, {"fmt": "MFINALFUNC_EXTRA=", "present": false}, {"fmt": "MINITCOND=", "present": false}, {"fmt": "HYPOTHETICAL=", "present": false}, {"fmt": "SORTOP=", "present": false}], "types": {"fmt": "%{direct:, }s", "direct": [{"fmt": "%{mode}s %{name}s %{type}T", "mode": "", "name": "", "type": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}}]}, "identity": {"objname": "newavg", "schemaname": "public"}}
+NOTICE:  re-formed command: CREATE AGGREGATE public.newavg (  pg_catalog.int4) (SFUNC=pg_catalog.int4_avg_accum, STYPE=pg_catalog.int8[], FINALFUNC= pg_catalog.int8_avg, INITCOND= '{0,0}')
+DROP AGGREGATE newavg(int4);
diff --git a/src/test/modules/test_ddl_deparse_regress/expected/alter_table.out b/src/test/modules/test_ddl_deparse_regress/expected/alter_table.out
new file mode 100644
index 0000000..7537b2a
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/expected/alter_table.out
@@ -0,0 +1,924 @@
+-- parent table defintion
+CREATE TABLE orders(
+    id int,
+    name varchar,
+    description text,
+    price float4,
+    quantity int,
+    purchase_date date
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "orders", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.orders (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+-- ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
+--     action [, ... ]
+CREATE TABLE parent_table(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "parent_table", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.parent_table (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+CREATE TABLE test_only () INHERITS (parent_table);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D () %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_only", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": [{"objname": "parent_table", "schemaname": "public"}]}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_only () INHERITS (public.parent_table)     
+ALTER TABLE test_only ADD col1 int;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD %{objtype}s %{if_not_exists}s %{definition}s", "type": "add column", "objtype": "COLUMN", "definition": {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "col1", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, "if_not_exists": ""}], "identity": {"objname": "test_only", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_only ADD COLUMN  col1 pg_catalog.int4 STORAGE plain     
+ALTER TABLE IF EXISTS fake_table ADD col2 int;
+NOTICE:  relation "fake_table" does not exist, skipping
+-- ALTER TABLE IF EXISTS ONLY parent_table ADD PRIMARY KEY (id);
+ALTER TABLE IF EXISTS parent_table * ADD CHECK (id > 10);
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "parent_table_id_check", "type": "add constraint", "definition": "CHECK ((id OPERATOR(pg_catalog.>) 10))"}], "identity": {"objname": "parent_table", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.parent_table ADD CONSTRAINT parent_table_id_check CHECK ((id OPERATOR(pg_catalog.>) 10))
+-- ADD [ COLUMN ] [ IF NOT EXISTS ] column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
+CREATE TABLE test_add_column(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_add_column", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_add_column (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_add_column ADD col1 int;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD %{objtype}s %{if_not_exists}s %{definition}s", "type": "add column", "objtype": "COLUMN", "definition": {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "col1", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, "if_not_exists": ""}], "identity": {"objname": "test_add_column", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_column ADD COLUMN  col1 pg_catalog.int4 STORAGE plain     
+ALTER TABLE test_add_column ADD COLUMN col2 int;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD %{objtype}s %{if_not_exists}s %{definition}s", "type": "add column", "objtype": "COLUMN", "definition": {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "col2", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, "if_not_exists": ""}], "identity": {"objname": "test_add_column", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_column ADD COLUMN  col2 pg_catalog.int4 STORAGE plain     
+ALTER TABLE test_add_column ADD COLUMN IF NOT EXISTS col2 varchar;
+NOTICE:  column "col2" of relation "test_add_column" already exists, skipping
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD %{objtype}s %{if_not_exists}s %{definition}s", "type": "add column", "objtype": "COLUMN", "definition": {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "col2", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, "if_not_exists": "IF NOT EXISTS"}], "identity": {"objname": "test_add_column", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_column ADD COLUMN IF NOT EXISTS col2 pg_catalog.int4 STORAGE plain     
+ALTER TABLE test_add_column ADD col3 varchar COLLATE "fr_FR";
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD %{objtype}s %{if_not_exists}s %{definition}s", "type": "add column", "objtype": "COLUMN", "definition": {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "col3", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "fr_FR", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, "if_not_exists": ""}], "identity": {"objname": "test_add_column", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_column ADD COLUMN  col3 pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."fr_FR"   
+ALTER TABLE test_add_column ADD col4 int CHECK (col4 > 100) UNIQUE;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD %{objtype}s %{if_not_exists}s %{definition}s", "type": "add column", "objtype": "COLUMN", "definition": {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "col4", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, "if_not_exists": ""}, {"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "test_add_column_col4_key", "type": "add constraint", "definition": "UNIQUE (col4)"}, {"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "test_add_column_col4_check", "type": "add constraint", "definition": "CHECK ((col4 OPERATOR(pg_catalog.>) 100))"}], "identity": {"objname": "test_add_column", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_column ADD COLUMN  col4 pg_catalog.int4 STORAGE plain     , ADD CONSTRAINT test_add_column_col4_key UNIQUE (col4), ADD CONSTRAINT test_add_column_col4_check CHECK ((col4 OPERATOR(pg_catalog.>) 100))
+ALTER TABLE test_add_column ADD COLUMN IF NOT EXISTS col5 text COLLATE "es_ES" DEFAULT 'foo' NOT NULL;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD %{objtype}s %{if_not_exists}s %{definition}s", "type": "add column", "objtype": "COLUMN", "definition": {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "col5", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT %{default}s", "default": "'foo'::pg_catalog.text"}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "es_ES", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, "if_not_exists": "IF NOT EXISTS"}], "identity": {"objname": "test_add_column", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_column ADD COLUMN IF NOT EXISTS col5 pg_catalog.text STORAGE extended  COLLATE pg_catalog."es_ES" NOT NULL DEFAULT 'foo'::pg_catalog.text 
+-- DROP [ COLUMN ] [ IF EXISTS ] column_name [ RESTRICT | CASCADE ]
+CREATE TABLE test_drop_column(
+    LIKE orders,
+    UNIQUE (id),
+    UNIQUE (name)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_drop_column", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "test_drop_column_id_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id)"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "test_drop_column_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (name)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_drop_column (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     , CONSTRAINT test_drop_column_id_key UNIQUE (id), CONSTRAINT test_drop_column_name_key UNIQUE (name))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE foreign_table(
+    id int REFERENCES test_drop_column (id),
+    name varchar REFERENCES test_drop_column (name)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "foreign_table", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.foreign_table (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "foreign_table_id_fkey", "type": "add constraint", "definition": "FOREIGN KEY (id) REFERENCES public.test_drop_column(id)"}, {"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "foreign_table_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.test_drop_column(name)"}], "identity": {"objname": "foreign_table", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.foreign_table ADD CONSTRAINT foreign_table_id_fkey FOREIGN KEY (id) REFERENCES public.test_drop_column(id), ADD CONSTRAINT foreign_table_name_fkey FOREIGN KEY (name) REFERENCES public.test_drop_column(name)
+ALTER TABLE test_drop_column DROP price;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "DROP %{objtype}s %{if_exists}s %{column}I %{cascade}s", "type": "drop column", "column": "price", "cascade": {"fmt": "CASCADE", "present": false}, "objtype": "COLUMN", "if_exists": ""}], "identity": {"objname": "test_drop_column", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_drop_column DROP COLUMN  price 
+ALTER TABLE test_drop_column DROP COLUMN quantity;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "DROP %{objtype}s %{if_exists}s %{column}I %{cascade}s", "type": "drop column", "column": "quantity", "cascade": {"fmt": "CASCADE", "present": false}, "objtype": "COLUMN", "if_exists": ""}], "identity": {"objname": "test_drop_column", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_drop_column DROP COLUMN  quantity 
+ALTER TABLE test_drop_column DROP IF EXISTS description RESTRICT;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "DROP %{objtype}s %{if_exists}s %{column}I %{cascade}s", "type": "drop column", "column": "description", "cascade": {"fmt": "CASCADE", "present": false}, "objtype": "COLUMN", "if_exists": "IF EXISTS"}], "identity": {"objname": "test_drop_column", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_drop_column DROP COLUMN IF EXISTS description 
+-- TOFIX
+-- ALTER TABLE test_drop_column DROP IF EXISTS name CASCADE;
+-- ALTER [ COLUMN ] column_name [ SET DATA ] TYPE data_type [ COLLATE collation ] [ USING expression ]
+CREATE TABLE test_alter_type(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_alter_type", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_alter_type (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_alter_type ALTER price TYPE int;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER %{objtype}s %{column}I SET DATA TYPE %{datatype}T %{collation}s %{using}s", "type": "alter column type", "using": {"fmt": "USING", "present": false}, "column": "price", "objtype": "COLUMN", "datatype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "collation": {"fmt": "COLLATE", "present": false}}], "identity": {"objname": "test_alter_type", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_alter_type ALTER COLUMN price SET DATA TYPE pg_catalog.int4  
+ALTER TABLE test_alter_type ALTER COLUMN purchase_date TYPE text COLLATE "fr_FR";
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER %{objtype}s %{column}I SET DATA TYPE %{datatype}T %{collation}s %{using}s", "type": "alter column type", "using": {"fmt": "USING", "present": false}, "column": "purchase_date", "objtype": "COLUMN", "datatype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "fr_FR", "schemaname": "pg_catalog"}}}], "identity": {"objname": "test_alter_type", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_alter_type ALTER COLUMN purchase_date SET DATA TYPE pg_catalog.text COLLATE pg_catalog."fr_FR" 
+ALTER TABLE test_alter_type ALTER COLUMN quantity SET DATA TYPE float4;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER %{objtype}s %{column}I SET DATA TYPE %{datatype}T %{collation}s %{using}s", "type": "alter column type", "using": {"fmt": "USING", "present": false}, "column": "quantity", "objtype": "COLUMN", "datatype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "collation": {"fmt": "COLLATE", "present": false}}], "identity": {"objname": "test_alter_type", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_alter_type ALTER COLUMN quantity SET DATA TYPE pg_catalog.float4  
+ALTER TABLE test_alter_type ALTER name TYPE int USING id::integer;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER %{objtype}s %{column}I SET DATA TYPE %{datatype}T %{collation}s %{using}s", "type": "alter column type", "using": {"fmt": "USING %{expression}s", "expression": "id"}, "column": "name", "objtype": "COLUMN", "datatype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "collation": {"fmt": "COLLATE", "present": false}}], "identity": {"objname": "test_alter_type", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_alter_type ALTER COLUMN name SET DATA TYPE pg_catalog.int4  USING id
+-- ALTER [ COLUMN ] column_name SET DEFAULT expression
+CREATE TABLE test_alter_set_default(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_alter_set_default", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_alter_set_default (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_alter_set_default ALTER price SET DEFAULT 100;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET DEFAULT %{definition}s", "type": "set default", "column": "price", "definition": "100"}], "identity": {"objname": "test_alter_set_default", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_alter_set_default ALTER COLUMN price SET DEFAULT 100
+ALTER TABLE test_alter_set_default ALTER COLUMN quantity SET DEFAULT 10;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET DEFAULT %{definition}s", "type": "set default", "column": "quantity", "definition": "10"}], "identity": {"objname": "test_alter_set_default", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_alter_set_default ALTER COLUMN quantity SET DEFAULT 10
+-- ALTER [ COLUMN ] column_name DROP DEFAULT
+CREATE TABLE test_drop_default(
+    LIKE orders,
+    default_price float4 DEFAULT 10.0,
+    default_name varchar DEFAULT 'foo'
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_drop_default", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "default_price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT %{default}s", "default": "10.0"}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "default_name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT %{default}s", "default": "'foo'::character varying"}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_drop_default (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     , default_price pg_catalog.float4 STORAGE plain    DEFAULT 10.0 , default_name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"  DEFAULT 'foo'::character varying )      
+ALTER TABLE test_drop_default ALTER default_price DROP DEFAULT;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I DROP DEFAULT", "type": "drop default", "column": "default_price"}], "identity": {"objname": "test_drop_default", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_drop_default ALTER COLUMN default_price DROP DEFAULT
+ALTER TABLE test_drop_default ALTER COLUMN default_name DROP DEFAULT;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I DROP DEFAULT", "type": "drop default", "column": "default_name"}], "identity": {"objname": "test_drop_default", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_drop_default ALTER COLUMN default_name DROP DEFAULT
+-- ALTER [ COLUMN ] column_name { SET | DROP } NOT NULL
+CREATE TABLE test_set_not_null(
+    LIKE orders,
+    size int NOT NULL
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_not_null", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "size", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_not_null (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     , size pg_catalog.int4 STORAGE plain   NOT NULL  )      
+ALTER TABLE test_set_not_null ALTER COLUMN id SET NOT NULL;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET NOT NULL", "type": "set not null", "column": "id"}], "identity": {"objname": "test_set_not_null", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_not_null ALTER COLUMN id SET NOT NULL
+ALTER TABLE test_set_not_null ALTER size DROP NOT NULL;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I DROP NOT NULL", "type": "drop not null", "column": "size"}], "identity": {"objname": "test_set_not_null", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_not_null ALTER COLUMN size DROP NOT NULL
+-- ALTER [ COLUMN ] column_name DROP EXPRESSION [ IF EXISTS ]
+CREATE TABLE test_drop_expression(
+    LIKE orders,
+    new_id int GENERATED ALWAYS AS ( 3 * ID ) STORED
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_drop_expression", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "new_id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS (%{generation_expr}s) STORED", "generation_expr": "(3 OPERATOR(pg_catalog.*) id)"}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_drop_expression (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     , new_id pg_catalog.int4 STORAGE plain     GENERATED ALWAYS AS ((3 OPERATOR(pg_catalog.*) id)) STORED)      
+ALTER TABLE test_drop_expression ALTER new_id DROP EXPRESSION;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I DROP EXPRESSION %{if_exists}s", "type": "drop expression", "column": "new_id", "if_exists": ""}], "identity": {"objname": "test_drop_expression", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_drop_expression ALTER COLUMN new_id DROP EXPRESSION 
+ALTER TABLE test_drop_expression ALTER id DROP EXPRESSION IF EXISTS;
+NOTICE:  column "id" of relation "test_drop_expression" is not a stored generated column, skipping
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I DROP EXPRESSION %{if_exists}s", "type": "drop expression", "column": "id", "if_exists": "IF EXISTS"}], "identity": {"objname": "test_drop_expression", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_drop_expression ALTER COLUMN id DROP EXPRESSION IF EXISTS
+-- ALTER [ COLUMN ] column_name ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]
+CREATE TABLE test_add_generated(
+    LIKE orders,
+    col1 int NOT NULL,
+    col2 int NOT NULL,
+    col3 int NOT NULL
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_add_generated", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "col1", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "col2", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "col3", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_add_generated (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     , col1 pg_catalog.int4 STORAGE plain   NOT NULL  , col2 pg_catalog.int4 STORAGE plain   NOT NULL  , col3 pg_catalog.int4 STORAGE plain   NOT NULL  )      
+ALTER TABLE test_add_generated ALTER col1 ADD GENERATED ALWAYS AS IDENTITY;
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I ADD %{identity_column}s", "type": "add identity", "column": "col1", "identity_column": {"fmt": "%{identity_type}s ( %{seq_definition: }s )", "identity_type": {"fmt": "GENERATED %{option}s AS IDENTITY", "option": "ALWAYS"}, "seq_definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}}], "identity": {"objname": "test_add_generated", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_generated ALTER COLUMN col1 ADD GENERATED ALWAYS AS IDENTITY ( CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 )
+ALTER TABLE test_add_generated ALTER COLUMN col2 ADD GENERATED BY DEFAULT AS IDENTITY;
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I ADD %{identity_column}s", "type": "add identity", "column": "col2", "identity_column": {"fmt": "%{identity_type}s ( %{seq_definition: }s )", "identity_type": {"fmt": "GENERATED %{option}s AS IDENTITY", "option": "BY DEFAULT"}, "seq_definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}}], "identity": {"objname": "test_add_generated", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_generated ALTER COLUMN col2 ADD GENERATED BY DEFAULT AS IDENTITY ( CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 )
+ALTER TABLE test_add_generated ALTER col3 ADD GENERATED BY DEFAULT AS IDENTITY ( INCREMENT BY 10 );
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I ADD %{identity_column}s", "type": "add identity", "column": "col3", "identity_column": {"fmt": "%{identity_type}s ( %{seq_definition: }s )", "identity_type": {"fmt": "GENERATED %{option}s AS IDENTITY", "option": "BY DEFAULT"}, "seq_definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "10", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}}], "identity": {"objname": "test_add_generated", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_generated ALTER COLUMN col3 ADD GENERATED BY DEFAULT AS IDENTITY ( CACHE 1 NO CYCLE INCREMENT BY 10 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 )
+-- ALTER [ COLUMN ] column_name { SET GENERATED { ALWAYS | BY DEFAULT } | SET sequence_option | RESTART [ [ WITH ] restart ] } [...]
+CREATE TABLE test_set_generated(
+    id1 int GENERATED BY DEFAULT AS IDENTITY,
+    id2 int GENERATED ALWAYS AS IDENTITY,
+    id3 int GENERATED ALWAYS AS IDENTITY,
+    id4 int GENERATED ALWAYS AS IDENTITY,
+    id5 int GENERATED ALWAYS AS IDENTITY,
+    id6 int GENERATED ALWAYS AS IDENTITY,
+    id7 int GENERATED ALWAYS AS IDENTITY
+);
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_generated", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{identity_column}s %{generated_column}s", "name": "id1", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "identity_column": {"fmt": "%{identity_type}s ( %{seq_definition: }s )", "identity_type": {"fmt": "GENERATED %{option}s AS IDENTITY", "option": "BY DEFAULT"}, "seq_definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{identity_column}s %{generated_column}s", "name": "id2", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "identity_column": {"fmt": "%{identity_type}s ( %{seq_definition: }s )", "identity_type": {"fmt": "GENERATED %{option}s AS IDENTITY", "option": "ALWAYS"}, "seq_definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{identity_column}s %{generated_column}s", "name": "id3", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "identity_column": {"fmt": "%{identity_type}s ( %{seq_definition: }s )", "identity_type": {"fmt": "GENERATED %{option}s AS IDENTITY", "option": "ALWAYS"}, "seq_definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{identity_column}s %{generated_column}s", "name": "id4", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "identity_column": {"fmt": "%{identity_type}s ( %{seq_definition: }s )", "identity_type": {"fmt": "GENERATED %{option}s AS IDENTITY", "option": "ALWAYS"}, "seq_definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{identity_column}s %{generated_column}s", "name": "id5", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "identity_column": {"fmt": "%{identity_type}s ( %{seq_definition: }s )", "identity_type": {"fmt": "GENERATED %{option}s AS IDENTITY", "option": "ALWAYS"}, "seq_definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{identity_column}s %{generated_column}s", "name": "id6", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "identity_column": {"fmt": "%{identity_type}s ( %{seq_definition: }s )", "identity_type": {"fmt": "GENERATED %{option}s AS IDENTITY", "option": "ALWAYS"}, "seq_definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{identity_column}s %{generated_column}s", "name": "id7", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "identity_column": {"fmt": "%{identity_type}s ( %{seq_definition: }s )", "identity_type": {"fmt": "GENERATED %{option}s AS IDENTITY", "option": "ALWAYS"}, "seq_definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_generated (id1 pg_catalog.int4 STORAGE plain     GENERATED BY DEFAULT AS IDENTITY ( CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 ) , id2 pg_catalog.int4 STORAGE plain     GENERATED ALWAYS AS IDENTITY ( CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 ) , id3 pg_catalog.int4 STORAGE plain     GENERATED ALWAYS AS IDENTITY ( CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 ) , id4 pg_catalog.int4 STORAGE plain     GENERATED ALWAYS AS IDENTITY ( CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 ) , id5 pg_catalog.int4 STORAGE plain     GENERATED ALWAYS AS IDENTITY ( CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 ) , id6 pg_catalog.int4 STORAGE plain     GENERATED ALWAYS AS IDENTITY ( CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 ) , id7 pg_catalog.int4 STORAGE plain     GENERATED ALWAYS AS IDENTITY ( CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 ) )      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+ALTER TABLE test_set_generated ALTER id1 SET GENERATED ALWAYS;
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I %{definition}s", "type": "set identity", "column": "id1", "definition": {"fmt": "%{identity_type}s %{seq_definition: }s", "identity_type": {"fmt": "SET GENERATED %{option}s", "option": "ALWAYS"}, "seq_definition": [{"fmt": "SET CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "SET %{no}s CYCLE", "clause": "cycle"}, {"fmt": "SET INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "SET MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "SET MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "SET START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}}], "identity": {"objname": "test_set_generated", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_generated ALTER COLUMN id1 SET GENERATED ALWAYS SET CACHE 1 SET NO CYCLE SET INCREMENT BY 1 SET MINVALUE 1 SET MAXVALUE 2147483647 SET START WITH 1 RESTART 1
+ALTER TABLE test_set_generated ALTER id2 SET GENERATED BY DEFAULT;
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I %{definition}s", "type": "set identity", "column": "id2", "definition": {"fmt": "%{identity_type}s %{seq_definition: }s", "identity_type": {"fmt": "SET GENERATED %{option}s", "option": "BY DEFAULT"}, "seq_definition": [{"fmt": "SET CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "SET %{no}s CYCLE", "clause": "cycle"}, {"fmt": "SET INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "SET MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "SET MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "SET START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}}], "identity": {"objname": "test_set_generated", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_generated ALTER COLUMN id2 SET GENERATED BY DEFAULT SET CACHE 1 SET NO CYCLE SET INCREMENT BY 1 SET MINVALUE 1 SET MAXVALUE 2147483647 SET START WITH 1 RESTART 1
+ALTER TABLE test_set_generated ALTER id3 SET INCREMENT BY 10;
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I %{definition}s", "type": "set identity", "column": "id3", "definition": {"fmt": "%{identity_type}s %{seq_definition: }s", "identity_type": {"fmt": "SET GENERATED ", "present": false}, "seq_definition": [{"fmt": "SET CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "SET %{no}s CYCLE", "clause": "cycle"}, {"fmt": "SET INCREMENT BY %{value}s", "value": "10", "clause": "seqincrement"}, {"fmt": "SET MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "SET MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "SET START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}}], "identity": {"objname": "test_set_generated", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_generated ALTER COLUMN id3  SET CACHE 1 SET NO CYCLE SET INCREMENT BY 10 SET MINVALUE 1 SET MAXVALUE 2147483647 SET START WITH 1 RESTART 1
+ALTER TABLE test_set_generated ALTER id4 RESTART;
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I %{definition}s", "type": "set identity", "column": "id4", "definition": {"fmt": "%{identity_type}s %{seq_definition: }s", "identity_type": {"fmt": "SET GENERATED ", "present": false}, "seq_definition": [{"fmt": "SET CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "SET %{no}s CYCLE", "clause": "cycle"}, {"fmt": "SET INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "SET MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "SET MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "SET START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}}], "identity": {"objname": "test_set_generated", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_generated ALTER COLUMN id4  SET CACHE 1 SET NO CYCLE SET INCREMENT BY 1 SET MINVALUE 1 SET MAXVALUE 2147483647 SET START WITH 1 RESTART 1
+ALTER TABLE test_set_generated ALTER id5 RESTART WITH 101;
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I %{definition}s", "type": "set identity", "column": "id5", "definition": {"fmt": "%{identity_type}s %{seq_definition: }s", "identity_type": {"fmt": "SET GENERATED ", "present": false}, "seq_definition": [{"fmt": "SET CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "SET %{no}s CYCLE", "clause": "cycle"}, {"fmt": "SET INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "SET MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "SET MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "SET START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "101", "clause": "restart"}]}}], "identity": {"objname": "test_set_generated", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_generated ALTER COLUMN id5  SET CACHE 1 SET NO CYCLE SET INCREMENT BY 1 SET MINVALUE 1 SET MAXVALUE 2147483647 SET START WITH 1 RESTART 101
+ALTER TABLE test_set_generated ALTER id6 RESTART WITH 201;
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I %{definition}s", "type": "set identity", "column": "id6", "definition": {"fmt": "%{identity_type}s %{seq_definition: }s", "identity_type": {"fmt": "SET GENERATED ", "present": false}, "seq_definition": [{"fmt": "SET CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "SET %{no}s CYCLE", "clause": "cycle"}, {"fmt": "SET INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "SET MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "SET MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "SET START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "201", "clause": "restart"}]}}], "identity": {"objname": "test_set_generated", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_generated ALTER COLUMN id6  SET CACHE 1 SET NO CYCLE SET INCREMENT BY 1 SET MINVALUE 1 SET MAXVALUE 2147483647 SET START WITH 1 RESTART 201
+ALTER TABLE test_set_generated ALTER COLUMN id7 SET GENERATED BY DEFAULT SET INCREMENT BY 100 RESTART WITH 301;
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I %{definition}s", "type": "set identity", "column": "id7", "definition": {"fmt": "%{identity_type}s %{seq_definition: }s", "identity_type": {"fmt": "SET GENERATED %{option}s", "option": "BY DEFAULT"}, "seq_definition": [{"fmt": "SET CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "SET %{no}s CYCLE", "clause": "cycle"}, {"fmt": "SET INCREMENT BY %{value}s", "value": "100", "clause": "seqincrement"}, {"fmt": "SET MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "SET MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "SET START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "301", "clause": "restart"}]}}], "identity": {"objname": "test_set_generated", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_generated ALTER COLUMN id7 SET GENERATED BY DEFAULT SET CACHE 1 SET NO CYCLE SET INCREMENT BY 100 SET MINVALUE 1 SET MAXVALUE 2147483647 SET START WITH 1 RESTART 301
+-- ALTER [ COLUMN ] column_name DROP IDENTITY [ IF EXISTS ]
+CREATE TABLE test_drop_identity(
+    id int,
+    id_generated int GENERATED ALWAYS AS IDENTITY
+);
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_drop_identity", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{identity_column}s %{generated_column}s", "name": "id_generated", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "identity_column": {"fmt": "%{identity_type}s ( %{seq_definition: }s )", "identity_type": {"fmt": "GENERATED %{option}s AS IDENTITY", "option": "ALWAYS"}, "seq_definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_drop_identity (id pg_catalog.int4 STORAGE plain     , id_generated pg_catalog.int4 STORAGE plain     GENERATED ALWAYS AS IDENTITY ( CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 ) )      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+ALTER TABLE test_drop_identity ALTER id_generated DROP IDENTITY;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I DROP IDENTITY %{if_exists}s", "type": "drop identity", "column": "id_generated", "if_exists": ""}], "identity": {"objname": "test_drop_identity", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_drop_identity ALTER COLUMN id_generated DROP IDENTITY 
+ALTER TABLE test_drop_identity ALTER id DROP IDENTITY IF EXISTS;
+NOTICE:  column "id" of relation "test_drop_identity" is not an identity column, skipping
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I DROP IDENTITY %{if_exists}s", "type": "drop identity", "column": "id", "if_exists": "IF EXISTS"}], "identity": {"objname": "test_drop_identity", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_drop_identity ALTER COLUMN id DROP IDENTITY IF EXISTS
+-- ALTER [ COLUMN ] column_name SET STATISTICS integer
+CREATE TABLE test_set_statistics(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_statistics", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_statistics (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_set_statistics ALTER id SET STATISTICS 1;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET STATISTICS %{statistics}n", "type": "set statistics", "column": "id", "statistics": 1}], "identity": {"objname": "test_set_statistics", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_statistics ALTER COLUMN id SET STATISTICS 1
+-- ALTER [ COLUMN ] column_name SET ( attribute_option = value [, ... ] )
+CREATE TABLE test_set_attribute(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_attribute", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_attribute (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_set_attribute ALTER name SET (n_distinct = 102);
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I %{option}s (%{options:, }s)", "column": "name", "option": "SET", "options": [{"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "n_distinct"}, "value": "102"}]}], "identity": {"objname": "test_set_attribute", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_attribute ALTER COLUMN name SET (n_distinct = '102')
+ALTER TABLE test_set_attribute ALTER id SET (n_distinct_inherited = 99, n_distinct = 9);
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I %{option}s (%{options:, }s)", "column": "id", "option": "SET", "options": [{"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "n_distinct_inherited"}, "value": "99"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "n_distinct"}, "value": "9"}]}], "identity": {"objname": "test_set_attribute", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_attribute ALTER COLUMN id SET (n_distinct_inherited = '99', n_distinct = '9')
+-- ALTER [ COLUMN ] column_name RESET ( attribute_option [, ... ] )
+CREATE TABLE test_reset_attribute(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_reset_attribute", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_reset_attribute (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_reset_attribute ALTER name RESET (n_distinct);
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I %{option}s (%{options:, }s)", "column": "name", "option": "RESET", "options": [{"fmt": "%{label}s", "label": {"fmt": "%{label}I", "label": "n_distinct"}}]}], "identity": {"objname": "test_reset_attribute", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_reset_attribute ALTER COLUMN name RESET (n_distinct)
+ALTER TABLE test_reset_attribute ALTER id RESET (n_distinct, n_distinct_inherited);
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I %{option}s (%{options:, }s)", "column": "id", "option": "RESET", "options": [{"fmt": "%{label}s", "label": {"fmt": "%{label}I", "label": "n_distinct"}}, {"fmt": "%{label}s", "label": {"fmt": "%{label}I", "label": "n_distinct_inherited"}}]}], "identity": {"objname": "test_reset_attribute", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_reset_attribute ALTER COLUMN id RESET (n_distinct, n_distinct_inherited)
+-- ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
+CREATE TABLE test_set_storage(
+    LIKE orders,
+    product_name text
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_storage", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "product_name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_storage (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     , product_name pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   )      
+ALTER TABLE test_set_storage ALTER id SET STORAGE PLAIN;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET STORAGE %{storage}s", "type": "set storage", "column": "id", "storage": "plain"}], "identity": {"objname": "test_set_storage", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_storage ALTER COLUMN id SET STORAGE plain
+ALTER TABLE test_set_storage ALTER name SET STORAGE EXTERNAL;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET STORAGE %{storage}s", "type": "set storage", "column": "name", "storage": "external"}], "identity": {"objname": "test_set_storage", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_storage ALTER COLUMN name SET STORAGE external
+ALTER TABLE test_set_storage ALTER description SET STORAGE EXTENDED;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET STORAGE %{storage}s", "type": "set storage", "column": "description", "storage": "extended"}], "identity": {"objname": "test_set_storage", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_storage ALTER COLUMN description SET STORAGE extended
+ALTER TABLE test_set_storage ALTER product_name SET STORAGE MAIN;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET STORAGE %{storage}s", "type": "set storage", "column": "product_name", "storage": "main"}], "identity": {"objname": "test_set_storage", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_storage ALTER COLUMN product_name SET STORAGE main
+-- ALTER [ COLUMN ] column_name SET COMPRESSION compression_method
+CREATE TABLE test_set_compression(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_compression", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_compression (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_set_compression ALTER name SET COMPRESSION "lz4";
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET COMPRESSION %{compression_method}s", "type": "set compression", "column": "name", "compression_method": "lz4"}], "identity": {"objname": "test_set_compression", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_compression ALTER COLUMN name SET COMPRESSION lz4
+ALTER TABLE test_set_compression ALTER COLUMN description SET COMPRESSION "lz4";
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET COMPRESSION %{compression_method}s", "type": "set compression", "column": "description", "compression_method": "lz4"}], "identity": {"objname": "test_set_compression", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_compression ALTER COLUMN description SET COMPRESSION lz4
+-- ADD table_constraint [ NOT VALID ]
+CREATE TABLE test_add_table_constraint(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_add_table_constraint", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_add_table_constraint (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_add_table_constraint ADD PRIMARY KEY (id);
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET NOT NULL", "type": "set not null", "column": "id"}, {"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "test_add_table_constraint_pkey", "type": "add constraint", "definition": "PRIMARY KEY (id)"}], "identity": {"objname": "test_add_table_constraint", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_table_constraint ALTER COLUMN id SET NOT NULL, ADD CONSTRAINT test_add_table_constraint_pkey PRIMARY KEY (id)
+ALTER TABLE test_add_table_constraint ADD CONSTRAINT max_name_len CHECK (length(name) < 4) NOT VALID;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "max_name_len", "type": "add constraint", "definition": "CHECK ((pg_catalog.length((name)::pg_catalog.text) OPERATOR(pg_catalog.<) 4)) NOT VALID"}], "identity": {"objname": "test_add_table_constraint", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_table_constraint ADD CONSTRAINT max_name_len CHECK ((pg_catalog.length((name)::pg_catalog.text) OPERATOR(pg_catalog.<) 4)) NOT VALID
+ALTER TABLE test_add_table_constraint ADD CHECK (id < 10);
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "test_add_table_constraint_id_check", "type": "add constraint", "definition": "CHECK ((id OPERATOR(pg_catalog.<) 10))"}], "identity": {"objname": "test_add_table_constraint", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_table_constraint ADD CONSTRAINT test_add_table_constraint_id_check CHECK ((id OPERATOR(pg_catalog.<) 10))
+-- ADD table_constraint_using_index
+CREATE TABLE test_add_constraint_using_index(
+    id1 int, 
+    id2 int,
+    id3 int,
+    id4 int,
+    id5 int,
+    id6 int,
+    id7 int
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_add_constraint_using_index", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id1", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id2", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id3", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id4", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id5", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id6", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id7", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_add_constraint_using_index (id1 pg_catalog.int4 STORAGE plain     , id2 pg_catalog.int4 STORAGE plain     , id3 pg_catalog.int4 STORAGE plain     , id4 pg_catalog.int4 STORAGE plain     , id5 pg_catalog.int4 STORAGE plain     , id6 pg_catalog.int4 STORAGE plain     , id7 pg_catalog.int4 STORAGE plain     )      
+CREATE UNIQUE INDEX test_add_constraint_used_index1 ON test_add_constraint_using_index (id1);
+NOTICE:  deparsed json: {"fmt": "CREATE %{unique}s INDEX %{concurrently}s %{if_not_exists}s %{name}I ON %{table}D USING %{index_am}s %{definition}s %{with}s %{tablespace}s %{where_clause}s NULLS DISTINCT", "name": "test_add_constraint_used_index1", "with": {"fmt": "WITH", "present": false}, "table": {"objname": "test_add_constraint_using_index", "schemaname": "public"}, "unique": "UNIQUE", "index_am": "btree", "definition": "(id1 pg_catalog.int4_ops)", "tablespace": {"fmt": "TABLESPACE", "present": false}, "concurrently": "", "where_clause": {"fmt": "WHERE", "present": false}, "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE UNIQUE INDEX   test_add_constraint_used_index1 ON public.test_add_constraint_using_index USING btree (id1 pg_catalog.int4_ops)    NULLS DISTINCT
+ALTER TABLE test_add_constraint_using_index ADD UNIQUE USING INDEX test_add_constraint_used_index1;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{constraint_type}s USING INDEX %{index_name}I %{deferrable}s %{init_deferred}s", "name": "test_add_constraint_used_index1", "type": "add constraint using index", "deferrable": "NOT DEFERRABLE", "index_name": "test_add_constraint_used_index1", "init_deferred": "INITIALLY IMMEDIATE", "constraint_type": "UNIQUE"}], "identity": {"objname": "test_add_constraint_using_index", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_constraint_using_index ADD CONSTRAINT test_add_constraint_used_index1 UNIQUE USING INDEX test_add_constraint_used_index1 NOT DEFERRABLE INITIALLY IMMEDIATE
+CREATE UNIQUE INDEX test_add_constraint_used_index2 ON test_add_constraint_using_index (id2);
+NOTICE:  deparsed json: {"fmt": "CREATE %{unique}s INDEX %{concurrently}s %{if_not_exists}s %{name}I ON %{table}D USING %{index_am}s %{definition}s %{with}s %{tablespace}s %{where_clause}s NULLS DISTINCT", "name": "test_add_constraint_used_index2", "with": {"fmt": "WITH", "present": false}, "table": {"objname": "test_add_constraint_using_index", "schemaname": "public"}, "unique": "UNIQUE", "index_am": "btree", "definition": "(id2 pg_catalog.int4_ops)", "tablespace": {"fmt": "TABLESPACE", "present": false}, "concurrently": "", "where_clause": {"fmt": "WHERE", "present": false}, "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE UNIQUE INDEX   test_add_constraint_used_index2 ON public.test_add_constraint_using_index USING btree (id2 pg_catalog.int4_ops)    NULLS DISTINCT
+--TOFIX
+-- ALTER TABLE test_add_constraint_using_index ADD CONSTRAINT primary_constraint_using_index PRIMARY KEY USING INDEX test_add_constraint_used_index2;
+CREATE UNIQUE INDEX test_add_constraint_used_index3 ON test_add_constraint_using_index (id3);
+NOTICE:  deparsed json: {"fmt": "CREATE %{unique}s INDEX %{concurrently}s %{if_not_exists}s %{name}I ON %{table}D USING %{index_am}s %{definition}s %{with}s %{tablespace}s %{where_clause}s NULLS DISTINCT", "name": "test_add_constraint_used_index3", "with": {"fmt": "WITH", "present": false}, "table": {"objname": "test_add_constraint_using_index", "schemaname": "public"}, "unique": "UNIQUE", "index_am": "btree", "definition": "(id3 pg_catalog.int4_ops)", "tablespace": {"fmt": "TABLESPACE", "present": false}, "concurrently": "", "where_clause": {"fmt": "WHERE", "present": false}, "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE UNIQUE INDEX   test_add_constraint_used_index3 ON public.test_add_constraint_using_index USING btree (id3 pg_catalog.int4_ops)    NULLS DISTINCT
+ALTER TABLE test_add_constraint_using_index ADD UNIQUE USING INDEX test_add_constraint_used_index3 DEFERRABLE;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{constraint_type}s USING INDEX %{index_name}I %{deferrable}s %{init_deferred}s", "name": "test_add_constraint_used_index3", "type": "add constraint using index", "deferrable": "DEFERRABLE", "index_name": "test_add_constraint_used_index3", "init_deferred": "INITIALLY IMMEDIATE", "constraint_type": "UNIQUE"}], "identity": {"objname": "test_add_constraint_using_index", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_constraint_using_index ADD CONSTRAINT test_add_constraint_used_index3 UNIQUE USING INDEX test_add_constraint_used_index3 DEFERRABLE INITIALLY IMMEDIATE
+CREATE UNIQUE INDEX test_add_constraint_used_index4 ON test_add_constraint_using_index (id4);
+NOTICE:  deparsed json: {"fmt": "CREATE %{unique}s INDEX %{concurrently}s %{if_not_exists}s %{name}I ON %{table}D USING %{index_am}s %{definition}s %{with}s %{tablespace}s %{where_clause}s NULLS DISTINCT", "name": "test_add_constraint_used_index4", "with": {"fmt": "WITH", "present": false}, "table": {"objname": "test_add_constraint_using_index", "schemaname": "public"}, "unique": "UNIQUE", "index_am": "btree", "definition": "(id4 pg_catalog.int4_ops)", "tablespace": {"fmt": "TABLESPACE", "present": false}, "concurrently": "", "where_clause": {"fmt": "WHERE", "present": false}, "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE UNIQUE INDEX   test_add_constraint_used_index4 ON public.test_add_constraint_using_index USING btree (id4 pg_catalog.int4_ops)    NULLS DISTINCT
+ALTER TABLE test_add_constraint_using_index ADD UNIQUE USING INDEX test_add_constraint_used_index4 NOT DEFERRABLE;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{constraint_type}s USING INDEX %{index_name}I %{deferrable}s %{init_deferred}s", "name": "test_add_constraint_used_index4", "type": "add constraint using index", "deferrable": "NOT DEFERRABLE", "index_name": "test_add_constraint_used_index4", "init_deferred": "INITIALLY IMMEDIATE", "constraint_type": "UNIQUE"}], "identity": {"objname": "test_add_constraint_using_index", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_constraint_using_index ADD CONSTRAINT test_add_constraint_used_index4 UNIQUE USING INDEX test_add_constraint_used_index4 NOT DEFERRABLE INITIALLY IMMEDIATE
+CREATE UNIQUE INDEX test_add_constraint_used_index5 ON test_add_constraint_using_index (id5);
+NOTICE:  deparsed json: {"fmt": "CREATE %{unique}s INDEX %{concurrently}s %{if_not_exists}s %{name}I ON %{table}D USING %{index_am}s %{definition}s %{with}s %{tablespace}s %{where_clause}s NULLS DISTINCT", "name": "test_add_constraint_used_index5", "with": {"fmt": "WITH", "present": false}, "table": {"objname": "test_add_constraint_using_index", "schemaname": "public"}, "unique": "UNIQUE", "index_am": "btree", "definition": "(id5 pg_catalog.int4_ops)", "tablespace": {"fmt": "TABLESPACE", "present": false}, "concurrently": "", "where_clause": {"fmt": "WHERE", "present": false}, "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE UNIQUE INDEX   test_add_constraint_used_index5 ON public.test_add_constraint_using_index USING btree (id5 pg_catalog.int4_ops)    NULLS DISTINCT
+ALTER TABLE test_add_constraint_using_index ADD UNIQUE USING INDEX test_add_constraint_used_index5 INITIALLY DEFERRED;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{constraint_type}s USING INDEX %{index_name}I %{deferrable}s %{init_deferred}s", "name": "test_add_constraint_used_index5", "type": "add constraint using index", "deferrable": "DEFERRABLE", "index_name": "test_add_constraint_used_index5", "init_deferred": "INITIALLY DEFERRED", "constraint_type": "UNIQUE"}], "identity": {"objname": "test_add_constraint_using_index", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_constraint_using_index ADD CONSTRAINT test_add_constraint_used_index5 UNIQUE USING INDEX test_add_constraint_used_index5 DEFERRABLE INITIALLY DEFERRED
+CREATE UNIQUE INDEX test_add_constraint_used_index6 ON test_add_constraint_using_index (id6);
+NOTICE:  deparsed json: {"fmt": "CREATE %{unique}s INDEX %{concurrently}s %{if_not_exists}s %{name}I ON %{table}D USING %{index_am}s %{definition}s %{with}s %{tablespace}s %{where_clause}s NULLS DISTINCT", "name": "test_add_constraint_used_index6", "with": {"fmt": "WITH", "present": false}, "table": {"objname": "test_add_constraint_using_index", "schemaname": "public"}, "unique": "UNIQUE", "index_am": "btree", "definition": "(id6 pg_catalog.int4_ops)", "tablespace": {"fmt": "TABLESPACE", "present": false}, "concurrently": "", "where_clause": {"fmt": "WHERE", "present": false}, "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE UNIQUE INDEX   test_add_constraint_used_index6 ON public.test_add_constraint_using_index USING btree (id6 pg_catalog.int4_ops)    NULLS DISTINCT
+ALTER TABLE test_add_constraint_using_index ADD UNIQUE USING INDEX test_add_constraint_used_index6 INITIALLY IMMEDIATE;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{constraint_type}s USING INDEX %{index_name}I %{deferrable}s %{init_deferred}s", "name": "test_add_constraint_used_index6", "type": "add constraint using index", "deferrable": "NOT DEFERRABLE", "index_name": "test_add_constraint_used_index6", "init_deferred": "INITIALLY IMMEDIATE", "constraint_type": "UNIQUE"}], "identity": {"objname": "test_add_constraint_using_index", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_constraint_using_index ADD CONSTRAINT test_add_constraint_used_index6 UNIQUE USING INDEX test_add_constraint_used_index6 NOT DEFERRABLE INITIALLY IMMEDIATE
+CREATE UNIQUE INDEX test_add_constraint_used_index7 ON test_add_constraint_using_index (id7);
+NOTICE:  deparsed json: {"fmt": "CREATE %{unique}s INDEX %{concurrently}s %{if_not_exists}s %{name}I ON %{table}D USING %{index_am}s %{definition}s %{with}s %{tablespace}s %{where_clause}s NULLS DISTINCT", "name": "test_add_constraint_used_index7", "with": {"fmt": "WITH", "present": false}, "table": {"objname": "test_add_constraint_using_index", "schemaname": "public"}, "unique": "UNIQUE", "index_am": "btree", "definition": "(id7 pg_catalog.int4_ops)", "tablespace": {"fmt": "TABLESPACE", "present": false}, "concurrently": "", "where_clause": {"fmt": "WHERE", "present": false}, "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE UNIQUE INDEX   test_add_constraint_used_index7 ON public.test_add_constraint_using_index USING btree (id7 pg_catalog.int4_ops)    NULLS DISTINCT
+ALTER TABLE test_add_constraint_using_index ADD UNIQUE USING INDEX test_add_constraint_used_index7 DEFERRABLE INITIALLY DEFERRED;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{constraint_type}s USING INDEX %{index_name}I %{deferrable}s %{init_deferred}s", "name": "test_add_constraint_used_index7", "type": "add constraint using index", "deferrable": "DEFERRABLE", "index_name": "test_add_constraint_used_index7", "init_deferred": "INITIALLY DEFERRED", "constraint_type": "UNIQUE"}], "identity": {"objname": "test_add_constraint_using_index", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_add_constraint_using_index ADD CONSTRAINT test_add_constraint_used_index7 UNIQUE USING INDEX test_add_constraint_used_index7 DEFERRABLE INITIALLY DEFERRED
+-- ALTER CONSTRAINT constraint_name [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
+CREATE TABLE test_alter_constraint_referenced(
+    id1 int UNIQUE, 
+    id2 int UNIQUE,
+    id3 int UNIQUE,
+    id4 int UNIQUE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_alter_constraint_referenced", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id1", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id2", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id3", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id4", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "test_alter_constraint_referenced_id1_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id1)"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "test_alter_constraint_referenced_id2_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id2)"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "test_alter_constraint_referenced_id3_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id3)"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "test_alter_constraint_referenced_id4_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id4)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_alter_constraint_referenced (id1 pg_catalog.int4 STORAGE plain     , id2 pg_catalog.int4 STORAGE plain     , id3 pg_catalog.int4 STORAGE plain     , id4 pg_catalog.int4 STORAGE plain     , CONSTRAINT test_alter_constraint_referenced_id1_key UNIQUE (id1), CONSTRAINT test_alter_constraint_referenced_id2_key UNIQUE (id2), CONSTRAINT test_alter_constraint_referenced_id3_key UNIQUE (id3), CONSTRAINT test_alter_constraint_referenced_id4_key UNIQUE (id4))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE test_alter_constraint(
+    id1 int,
+    id2 int,
+    id3 int,
+    id4 int,
+    id5 int,
+    CONSTRAINT alter_cstr1 FOREIGN KEY (id1) REFERENCES test_alter_constraint_referenced (id1) DEFERRABLE INITIALLY DEFERRED,
+    CONSTRAINT alter_cstr2 FOREIGN KEY (id2) REFERENCES test_alter_constraint_referenced (id2) NOT DEFERRABLE,
+    CONSTRAINT alter_cstr3 FOREIGN KEY (id3) REFERENCES test_alter_constraint_referenced (id3) DEFERRABLE INITIALLY DEFERRED,
+    CONSTRAINT alter_cstr4 FOREIGN KEY (id4) REFERENCES test_alter_constraint_referenced (id4) DEFERRABLE INITIALLY IMMEDIATE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_alter_constraint", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id1", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id2", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id3", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id4", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id5", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_alter_constraint (id1 pg_catalog.int4 STORAGE plain     , id2 pg_catalog.int4 STORAGE plain     , id3 pg_catalog.int4 STORAGE plain     , id4 pg_catalog.int4 STORAGE plain     , id5 pg_catalog.int4 STORAGE plain     )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "alter_cstr1", "type": "add constraint", "definition": "FOREIGN KEY (id1) REFERENCES public.test_alter_constraint_referenced(id1) DEFERRABLE INITIALLY DEFERRED"}, {"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "alter_cstr2", "type": "add constraint", "definition": "FOREIGN KEY (id2) REFERENCES public.test_alter_constraint_referenced(id2)"}, {"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "alter_cstr3", "type": "add constraint", "definition": "FOREIGN KEY (id3) REFERENCES public.test_alter_constraint_referenced(id3) DEFERRABLE INITIALLY DEFERRED"}, {"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "alter_cstr4", "type": "add constraint", "definition": "FOREIGN KEY (id4) REFERENCES public.test_alter_constraint_referenced(id4) DEFERRABLE"}], "identity": {"objname": "test_alter_constraint", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_alter_constraint ADD CONSTRAINT alter_cstr1 FOREIGN KEY (id1) REFERENCES public.test_alter_constraint_referenced(id1) DEFERRABLE INITIALLY DEFERRED, ADD CONSTRAINT alter_cstr2 FOREIGN KEY (id2) REFERENCES public.test_alter_constraint_referenced(id2), ADD CONSTRAINT alter_cstr3 FOREIGN KEY (id3) REFERENCES public.test_alter_constraint_referenced(id3) DEFERRABLE INITIALLY DEFERRED, ADD CONSTRAINT alter_cstr4 FOREIGN KEY (id4) REFERENCES public.test_alter_constraint_referenced(id4) DEFERRABLE
+ALTER TABLE test_alter_constraint ALTER CONSTRAINT alter_cstr1 NOT DEFERRABLE;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER CONSTRAINT %{name}I %{deferrable}s %{init_deferred}s", "name": "alter_cstr1", "type": "alter constraint", "deferrable": "NOT DEFERRABLE", "init_deferred": "INITIALLY IMMEDIATE"}], "identity": {"objname": "test_alter_constraint", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_alter_constraint ALTER CONSTRAINT alter_cstr1 NOT DEFERRABLE INITIALLY IMMEDIATE
+ALTER TABLE test_alter_constraint ALTER CONSTRAINT alter_cstr2 DEFERRABLE;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER CONSTRAINT %{name}I %{deferrable}s %{init_deferred}s", "name": "alter_cstr2", "type": "alter constraint", "deferrable": "DEFERRABLE", "init_deferred": "INITIALLY IMMEDIATE"}], "identity": {"objname": "test_alter_constraint", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_alter_constraint ALTER CONSTRAINT alter_cstr2 DEFERRABLE INITIALLY IMMEDIATE
+ALTER TABLE test_alter_constraint ALTER CONSTRAINT alter_cstr3 DEFERRABLE INITIALLY IMMEDIATE;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER CONSTRAINT %{name}I %{deferrable}s %{init_deferred}s", "name": "alter_cstr3", "type": "alter constraint", "deferrable": "DEFERRABLE", "init_deferred": "INITIALLY IMMEDIATE"}], "identity": {"objname": "test_alter_constraint", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_alter_constraint ALTER CONSTRAINT alter_cstr3 DEFERRABLE INITIALLY IMMEDIATE
+ALTER TABLE test_alter_constraint ALTER CONSTRAINT alter_cstr4 DEFERRABLE INITIALLY DEFERRED;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER CONSTRAINT %{name}I %{deferrable}s %{init_deferred}s", "name": "alter_cstr4", "type": "alter constraint", "deferrable": "DEFERRABLE", "init_deferred": "INITIALLY DEFERRED"}], "identity": {"objname": "test_alter_constraint", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_alter_constraint ALTER CONSTRAINT alter_cstr4 DEFERRABLE INITIALLY DEFERRED
+-- VALIDATE CONSTRAINT constraint_name
+CREATE TABLE test_validate_constraint(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_validate_constraint", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_validate_constraint (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_validate_constraint ADD CONSTRAINT test_validate_constraint_cstr CHECK (length(name) < 10) NOT VALID;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "test_validate_constraint_cstr", "type": "add constraint", "definition": "CHECK ((pg_catalog.length((name)::pg_catalog.text) OPERATOR(pg_catalog.<) 10)) NOT VALID"}], "identity": {"objname": "test_validate_constraint", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_validate_constraint ADD CONSTRAINT test_validate_constraint_cstr CHECK ((pg_catalog.length((name)::pg_catalog.text) OPERATOR(pg_catalog.<) 10)) NOT VALID
+ALTER TABLE test_validate_constraint VALIDATE CONSTRAINT test_validate_constraint_cstr;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "VALIDATE CONSTRAINT %{constraint}I", "type": "validate constraint", "constraint": "test_validate_constraint_cstr"}], "identity": {"objname": "test_validate_constraint", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_validate_constraint VALIDATE CONSTRAINT test_validate_constraint_cstr
+-- DROP CONSTRAINT [ IF EXISTS ]  constraint_name [ RESTRICT | CASCADE ]
+CREATE TABLE test_drop_constraint(
+    LIKE orders,
+    CONSTRAINT test_drop_constraint_check CHECK (id < 100),
+    CONSTRAINT test_drop_constraint_uniq UNIQUE (id)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_drop_constraint", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "test_drop_constraint_check", "type": "constraint", "contype": "check", "definition": "CHECK ((id OPERATOR(pg_catalog.<) 100))"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "test_drop_constraint_uniq", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_drop_constraint (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     , CONSTRAINT test_drop_constraint_check CHECK ((id OPERATOR(pg_catalog.<) 100)), CONSTRAINT test_drop_constraint_uniq UNIQUE (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE test_drop_constraint_reference(
+    id int REFERENCES test_drop_constraint (id),
+    name varchar,
+    CONSTRAINT test_drop_constraint_reference_cstr1 CHECK (length(name) < 10)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_drop_constraint_reference", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "test_drop_constraint_reference_cstr1", "type": "constraint", "contype": "check", "definition": "CHECK ((pg_catalog.length((name)::pg_catalog.text) OPERATOR(pg_catalog.<) 10))"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_drop_constraint_reference (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT test_drop_constraint_reference_cstr1 CHECK ((pg_catalog.length((name)::pg_catalog.text) OPERATOR(pg_catalog.<) 10)))      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "test_drop_constraint_reference_id_fkey", "type": "add constraint", "definition": "FOREIGN KEY (id) REFERENCES public.test_drop_constraint(id)"}], "identity": {"objname": "test_drop_constraint_reference", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_drop_constraint_reference ADD CONSTRAINT test_drop_constraint_reference_id_fkey FOREIGN KEY (id) REFERENCES public.test_drop_constraint(id)
+ALTER TABLE test_drop_constraint_reference DROP CONSTRAINT test_drop_constraint_reference_cstr1;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "DROP CONSTRAINT %{if_exists}s %{constraint}I %{cascade}s", "type": "drop constraint", "cascade": "", "if_exists": "", "constraint": "test_drop_constraint_reference_cstr1"}], "identity": {"objname": "test_drop_constraint_reference", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_drop_constraint_reference DROP CONSTRAINT  test_drop_constraint_reference_cstr1 
+ALTER TABLE test_drop_constraint DROP CONSTRAINT test_drop_constraint_check RESTRICT;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "DROP CONSTRAINT %{if_exists}s %{constraint}I %{cascade}s", "type": "drop constraint", "cascade": "", "if_exists": "", "constraint": "test_drop_constraint_check"}], "identity": {"objname": "test_drop_constraint", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_drop_constraint DROP CONSTRAINT  test_drop_constraint_check 
+ALTER TABLE test_drop_constraint DROP CONSTRAINT IF EXISTS test_drop_constraint_check RESTRICT;
+NOTICE:  constraint "test_drop_constraint_check" of relation "test_drop_constraint" does not exist, skipping
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "DROP CONSTRAINT %{if_exists}s %{constraint}I %{cascade}s", "type": "drop constraint", "cascade": "", "if_exists": "IF EXISTS", "constraint": "test_drop_constraint_check"}], "identity": {"objname": "test_drop_constraint", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_drop_constraint DROP CONSTRAINT IF EXISTS test_drop_constraint_check 
+-- TOFIX
+-- ALTER TABLE test_drop_constraint DROP CONSTRAINT test_drop_constraint_uniq CASCADE;
+-- TODO: This should be tested with TRIGGER related testing
+-- DISABLE TRIGGER [ trigger_name | ALL | USER ]
+-- ENABLE TRIGGER [ trigger_name | ALL | USER ]
+-- ENABLE REPLICA TRIGGER trigger_name
+-- ENABLE ALWAYS TRIGGER trigger_name
+-- DISABLE RULE rewrite_rule_name
+CREATE TABLE test_disable_rule(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_disable_rule", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_disable_rule (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+CREATE RULE sample_rule1 AS
+    ON UPDATE TO test_disable_rule
+    DO INSTEAD
+        SELECT * FROM test_disable_rule;
+NOTICE:  deparsed json: {"fmt": "CREATE RULE %{or_replace}s %{identity}I AS ON %{event}s TO %{table}D %{where_clause}s DO %{instead}s %{actions:; }s", "event": "UPDATE", "table": {"objname": "test_disable_rule", "schemaname": "public"}, "actions": ["SELECT test_disable_rule.id, test_disable_rule.name, test_disable_rule.description, test_disable_rule.price, test_disable_rule.quantity, test_disable_rule.purchase_date FROM public.test_disable_rule"], "instead": "INSTEAD", "identity": "sample_rule1", "or_replace": "", "where_clause": {"fmt": "WHERE %{clause}s", "clause": null, "present": false}}
+NOTICE:  re-formed command: CREATE RULE  sample_rule1 AS ON UPDATE TO public.test_disable_rule  DO INSTEAD SELECT test_disable_rule.id, test_disable_rule.name, test_disable_rule.description, test_disable_rule.price, test_disable_rule.quantity, test_disable_rule.purchase_date FROM public.test_disable_rule
+ALTER TABLE test_disable_rule DISABLE RULE sample_rule1;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "DISABLE RULE %{rule}I", "rule": "sample_rule1", "type": "disable rule"}], "identity": {"objname": "test_disable_rule", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_disable_rule DISABLE RULE sample_rule1
+-- ENABLE RULE rewrite_rule_name
+CREATE TABLE test_enable_rule(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_enable_rule", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_enable_rule (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+CREATE RULE sample_rule2 AS
+    ON UPDATE TO test_enable_rule
+    DO INSTEAD
+        SELECT * FROM test_enable_rule;
+NOTICE:  deparsed json: {"fmt": "CREATE RULE %{or_replace}s %{identity}I AS ON %{event}s TO %{table}D %{where_clause}s DO %{instead}s %{actions:; }s", "event": "UPDATE", "table": {"objname": "test_enable_rule", "schemaname": "public"}, "actions": ["SELECT test_enable_rule.id, test_enable_rule.name, test_enable_rule.description, test_enable_rule.price, test_enable_rule.quantity, test_enable_rule.purchase_date FROM public.test_enable_rule"], "instead": "INSTEAD", "identity": "sample_rule2", "or_replace": "", "where_clause": {"fmt": "WHERE %{clause}s", "clause": null, "present": false}}
+NOTICE:  re-formed command: CREATE RULE  sample_rule2 AS ON UPDATE TO public.test_enable_rule  DO INSTEAD SELECT test_enable_rule.id, test_enable_rule.name, test_enable_rule.description, test_enable_rule.price, test_enable_rule.quantity, test_enable_rule.purchase_date FROM public.test_enable_rule
+ALTER TABLE test_enable_rule DISABLE RULE sample_rule2;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "DISABLE RULE %{rule}I", "rule": "sample_rule2", "type": "disable rule"}], "identity": {"objname": "test_enable_rule", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_enable_rule DISABLE RULE sample_rule2
+ALTER TABLE test_enable_rule ENABLE RULE sample_rule2;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ENABLE RULE %{rule}I", "rule": "sample_rule2", "type": "enable rule"}], "identity": {"objname": "test_enable_rule", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_enable_rule ENABLE RULE sample_rule2
+-- ENABLE REPLICA RULE rewrite_rule_name
+CREATE TABLE test_enable_replica_rule(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_enable_replica_rule", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_enable_replica_rule (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+CREATE RULE sample_rule_enable_replica AS
+    ON UPDATE TO test_enable_replica_rule
+    DO INSTEAD
+        SELECT * FROM test_enable_replica_rule;
+NOTICE:  deparsed json: {"fmt": "CREATE RULE %{or_replace}s %{identity}I AS ON %{event}s TO %{table}D %{where_clause}s DO %{instead}s %{actions:; }s", "event": "UPDATE", "table": {"objname": "test_enable_replica_rule", "schemaname": "public"}, "actions": ["SELECT test_enable_replica_rule.id, test_enable_replica_rule.name, test_enable_replica_rule.description, test_enable_replica_rule.price, test_enable_replica_rule.quantity, test_enable_replica_rule.purchase_date FROM public.test_enable_replica_rule"], "instead": "INSTEAD", "identity": "sample_rule_enable_replica", "or_replace": "", "where_clause": {"fmt": "WHERE %{clause}s", "clause": null, "present": false}}
+NOTICE:  re-formed command: CREATE RULE  sample_rule_enable_replica AS ON UPDATE TO public.test_enable_replica_rule  DO INSTEAD SELECT test_enable_replica_rule.id, test_enable_replica_rule.name, test_enable_replica_rule.description, test_enable_replica_rule.price, test_enable_replica_rule.quantity, test_enable_replica_rule.purchase_date FROM public.test_enable_replica_rule
+ALTER TABLE test_enable_replica_rule ENABLE REPLICA RULE sample_rule_enable_replica;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ENABLE REPLICA RULE %{rule}I", "rule": "sample_rule_enable_replica", "type": "enable replica rule"}], "identity": {"objname": "test_enable_replica_rule", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_enable_replica_rule ENABLE REPLICA RULE sample_rule_enable_replica
+-- ENABLE ALWAYS RULE rewrite_rule_name
+CREATE TABLE test_enable_always_rule(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_enable_always_rule", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_enable_always_rule (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+CREATE RULE sample_rule_enable_always AS
+    ON UPDATE TO test_enable_always_rule
+    DO INSTEAD
+        SELECT * FROM test_enable_always_rule;
+NOTICE:  deparsed json: {"fmt": "CREATE RULE %{or_replace}s %{identity}I AS ON %{event}s TO %{table}D %{where_clause}s DO %{instead}s %{actions:; }s", "event": "UPDATE", "table": {"objname": "test_enable_always_rule", "schemaname": "public"}, "actions": ["SELECT test_enable_always_rule.id, test_enable_always_rule.name, test_enable_always_rule.description, test_enable_always_rule.price, test_enable_always_rule.quantity, test_enable_always_rule.purchase_date FROM public.test_enable_always_rule"], "instead": "INSTEAD", "identity": "sample_rule_enable_always", "or_replace": "", "where_clause": {"fmt": "WHERE %{clause}s", "clause": null, "present": false}}
+NOTICE:  re-formed command: CREATE RULE  sample_rule_enable_always AS ON UPDATE TO public.test_enable_always_rule  DO INSTEAD SELECT test_enable_always_rule.id, test_enable_always_rule.name, test_enable_always_rule.description, test_enable_always_rule.price, test_enable_always_rule.quantity, test_enable_always_rule.purchase_date FROM public.test_enable_always_rule
+ALTER TABLE test_enable_always_rule ENABLE REPLICA RULE sample_rule_enable_always;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ENABLE REPLICA RULE %{rule}I", "rule": "sample_rule_enable_always", "type": "enable replica rule"}], "identity": {"objname": "test_enable_always_rule", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_enable_always_rule ENABLE REPLICA RULE sample_rule_enable_always
+-- DISABLE ROW LEVEL SECURITY
+CREATE TABLE test_disable_row_security(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_disable_row_security", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_disable_row_security (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_disable_row_security DISABLE ROW LEVEL SECURITY;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "DISABLE ROW LEVEL SECURITY", "type": "disable row security"}], "identity": {"objname": "test_disable_row_security", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_disable_row_security DISABLE ROW LEVEL SECURITY
+-- ENABLE ROW LEVEL SECURITY
+CREATE TABLE test_enable_row_security(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_enable_row_security", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_enable_row_security (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_enable_row_security ENABLE ROW LEVEL SECURITY;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ENABLE ROW LEVEL SECURITY", "type": "enable row security"}], "identity": {"objname": "test_enable_row_security", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_enable_row_security ENABLE ROW LEVEL SECURITY
+-- FORCE ROW LEVEL SECURITY
+CREATE TABLE test_force_row_security(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_force_row_security", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_force_row_security (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_force_row_security FORCE ROW LEVEL SECURITY;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "FORCE ROW LEVEL SECURITY"}], "identity": {"objname": "test_force_row_security", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_force_row_security FORCE ROW LEVEL SECURITY
+-- NO FORCE ROW LEVEL SECURITY
+CREATE TABLE test_no_force_row_security(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_no_force_row_security", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_no_force_row_security (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_no_force_row_security NO FORCE ROW LEVEL SECURITY;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "NO FORCE ROW LEVEL SECURITY"}], "identity": {"objname": "test_no_force_row_security", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_no_force_row_security NO FORCE ROW LEVEL SECURITY
+-- CLUSTER ON index_name
+CREATE TABLE test_cluster(
+    LIKE orders,
+    PRIMARY KEY (id)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_cluster", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "test_cluster_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_cluster (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     , CONSTRAINT test_cluster_pkey PRIMARY KEY (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+ALTER TABLE test_cluster CLUSTER ON test_cluster_pkey;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "CLUSTER ON %{index}I", "type": "cluster on", "index": "test_cluster_pkey"}], "identity": {"objname": "test_cluster", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_cluster CLUSTER ON test_cluster_pkey
+-- SET WITHOUT CLUSTER
+CREATE TABLE test_without_cluster(
+    LIKE orders,
+    PRIMARY KEY (id)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_without_cluster", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "test_without_cluster_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_without_cluster (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     , CONSTRAINT test_without_cluster_pkey PRIMARY KEY (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+ALTER TABLE test_without_cluster CLUSTER ON test_without_cluster_pkey;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "CLUSTER ON %{index}I", "type": "cluster on", "index": "test_without_cluster_pkey"}], "identity": {"objname": "test_without_cluster", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_without_cluster CLUSTER ON test_without_cluster_pkey
+ALTER TABLE test_without_cluster SET WITHOUT CLUSTER;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "SET WITHOUT CLUSTER", "type": "set without cluster"}], "identity": {"objname": "test_without_cluster", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_without_cluster SET WITHOUT CLUSTER
+-- SET WITHOUT OIDS
+CREATE TABLE test_set_without_oids(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_without_oids", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_without_oids (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_set_without_oids SET WITHOUT OIDS;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "SET WITHOUT OIDS", "type": "set without oids"}], "identity": {"objname": "test_set_without_oids", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_without_oids SET WITHOUT OIDS
+-- SET ACCESS METHOD new_access_method
+CREATE TABLE test_set_access_method(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_access_method", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_access_method (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_set_access_method SET ACCESS METHOD heap;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "SET ACCESS METHOD %{access_method}I", "type": "set access method", "access_method": "heap"}], "identity": {"objname": "test_set_access_method", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_access_method SET ACCESS METHOD heap
+-- SET TABLESPACE new_tablespace
+CREATE TABLE test_set_tablespace(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_tablespace", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_tablespace (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_set_tablespace SET TABLESPACE pg_default;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "SET TABLESPACE %{tablespace}I", "type": "set tablespace", "tablespace": "pg_default"}], "identity": {"objname": "test_set_tablespace", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_tablespace SET TABLESPACE pg_default
+-- SET { LOGGED | UNLOGGED }
+CREATE TABLE test_set_logged(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_logged", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_logged (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_set_logged SET LOGGED;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "SET LOGGED", "type": "set logged"}], "identity": {"objname": "test_set_logged", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_logged SET LOGGED
+CREATE TABLE test_set_unlogged(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_unlogged", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_unlogged (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_set_unlogged SET UNLOGGED;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "SET UNLOGGED", "type": "set unlogged"}], "identity": {"objname": "test_set_unlogged", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_unlogged SET UNLOGGED
+-- SET ( storage_parameter [= value] [, ... ] )
+CREATE TABLE test_set_storage_params1(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_storage_params1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_storage_params1 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_set_storage_params1 SET (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true);
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "%{set_reset}s (%{options:, }s)", "options": [{"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_index_cleanup"}, "value": "on"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "autovacuum_vacuum_scale_factor"}, "value": "0.2"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_truncate"}, "value": "true"}], "set_reset": "SET"}], "identity": {"objname": "test_set_storage_params1", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_storage_params1 SET (vacuum_index_cleanup = 'on', autovacuum_vacuum_scale_factor = '0.2', vacuum_truncate = 'true')
+CREATE TABLE test_set_storage_params2(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_storage_params2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_storage_params2 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_set_storage_params2 SET (vacuum_index_cleanup = ON);
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "%{set_reset}s (%{options:, }s)", "options": [{"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_index_cleanup"}, "value": "on"}], "set_reset": "SET"}], "identity": {"objname": "test_set_storage_params2", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_storage_params2 SET (vacuum_index_cleanup = 'on')
+-- RESET ( storage_parameter [, ... ] )
+CREATE TABLE test_reset_storage_params1(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_reset_storage_params1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_reset_storage_params1 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_set_storage_params1 SET (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true);
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "%{set_reset}s (%{options:, }s)", "options": [{"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_index_cleanup"}, "value": "on"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "autovacuum_vacuum_scale_factor"}, "value": "0.2"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_truncate"}, "value": "true"}], "set_reset": "SET"}], "identity": {"objname": "test_set_storage_params1", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_storage_params1 SET (vacuum_index_cleanup = 'on', autovacuum_vacuum_scale_factor = '0.2', vacuum_truncate = 'true')
+ALTER TABLE test_reset_storage_params1 RESET (vacuum_index_cleanup, autovacuum_vacuum_scale_factor, vacuum_truncate);
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "%{set_reset}s (%{options:, }s)", "options": [{"fmt": "%{label}s", "label": {"fmt": "%{label}I", "label": "vacuum_index_cleanup"}}, {"fmt": "%{label}s", "label": {"fmt": "%{label}I", "label": "autovacuum_vacuum_scale_factor"}}, {"fmt": "%{label}s", "label": {"fmt": "%{label}I", "label": "vacuum_truncate"}}], "set_reset": "RESET"}], "identity": {"objname": "test_reset_storage_params1", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_reset_storage_params1 RESET (vacuum_index_cleanup, autovacuum_vacuum_scale_factor, vacuum_truncate)
+CREATE TABLE test_reset_storage_params2(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_reset_storage_params2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_reset_storage_params2 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_set_storage_params2 SET (vacuum_index_cleanup = ON);
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "%{set_reset}s (%{options:, }s)", "options": [{"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_index_cleanup"}, "value": "on"}], "set_reset": "SET"}], "identity": {"objname": "test_set_storage_params2", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_storage_params2 SET (vacuum_index_cleanup = 'on')
+ALTER TABLE test_reset_storage_params2 RESET (vacuum_index_cleanup);
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "%{set_reset}s (%{options:, }s)", "options": [{"fmt": "%{label}s", "label": {"fmt": "%{label}I", "label": "vacuum_index_cleanup"}}], "set_reset": "RESET"}], "identity": {"objname": "test_reset_storage_params2", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_reset_storage_params2 RESET (vacuum_index_cleanup)
+-- INHERIT parent_table
+CREATE TABLE test_inherit_parent(
+    parent_id int
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_inherit_parent", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "parent_id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_inherit_parent (parent_id pg_catalog.int4 STORAGE plain     )      
+CREATE TABLE test_inherit_child(
+    parent_id int,
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_inherit_child", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "parent_id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_inherit_child (parent_id pg_catalog.int4 STORAGE plain     , id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_inherit_child INHERIT test_inherit_parent;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "INHERIT %{parent}D", "type": "inherit", "parent": {"objname": "test_inherit_parent", "schemaname": "public"}}], "identity": {"objname": "test_inherit_child", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_inherit_child INHERIT public.test_inherit_parent
+-- NO INHERIT parent_table
+CREATE TABLE test_no_inherit_parent(
+    parent_id int
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_no_inherit_parent", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "parent_id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_no_inherit_parent (parent_id pg_catalog.int4 STORAGE plain     )      
+CREATE TABLE test_no_inherit_child(
+    LIKE orders
+) INHERITS (test_no_inherit_parent);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_no_inherit_child", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": [{"objname": "test_no_inherit_parent", "schemaname": "public"}]}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_no_inherit_child (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     ) INHERITS (public.test_no_inherit_parent)     
+ALTER TABLE test_no_inherit_child NO INHERIT test_no_inherit_parent;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "NO INHERIT %{parent}D", "type": "drop inherit", "parent": {"objname": "test_no_inherit_parent", "schemaname": "public"}}], "identity": {"objname": "test_no_inherit_child", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_no_inherit_child NO INHERIT public.test_no_inherit_parent
+-- OF type_name
+CREATE TYPE test_type_product_type AS (
+    id int,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE TYPE %{identity}D AS (%{columns:, }s)", "columns": [{"fmt": "%{name}I %{coltype}T %{compression}s %{collation}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "collation": {"fmt": "COLLATE", "present": false}, "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}}, {"fmt": "%{name}I %{coltype}T %{compression}s %{collation}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}}], "identity": {"objname": "test_type_product_type", "schemaname": "public"}}
+NOTICE:  re-formed command: CREATE TYPE public.test_type_product_type AS (id pg_catalog.int4  , name pg_catalog."varchar"  COLLATE pg_catalog."default")
+CREATE TABLE test_type(
+    id int,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_type", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_type (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+ALTER TABLE test_type OF test_type_product_type;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "OF %{type_of}T", "type": "add of", "type_of": {"typmod": "", "typarray": false, "typename": "test_type_product_type", "schemaname": "public"}}], "identity": {"objname": "test_type", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_type OF public.test_type_product_type
+-- NOT OF
+CREATE TABLE test_type_not_of OF test_type_product_type;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D OF %{of_type}T %{table_elements}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "of_type": {"typmod": "", "typarray": false, "typename": "test_type_product_type", "schemaname": "public"}, "identity": {"objname": "test_type_not_of", "schemaname": "public"}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": {"fmt": "", "present": false}}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_type_not_of OF public.test_type_product_type      
+ALTER TABLE test_type_not_of NOT OF;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "NOT OF", "type": "not of"}], "identity": {"objname": "test_type_not_of", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_type_not_of NOT OF
+-- TODO: This should be tested with ROLE/USER related testing
+-- OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
+-- REPLICA IDENTITY { DEFAULT | USING INDEX index_name | FULL | NOTHING }
+CREATE TABLE test_replica_identity1(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_replica_identity1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_replica_identity1 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_replica_identity1 REPLICA IDENTITY DEFAULT;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "REPLICA IDENTITY %{ident}s", "type": "replica identity", "ident": "DEFAULT"}], "identity": {"objname": "test_replica_identity1", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_replica_identity1 REPLICA IDENTITY DEFAULT
+CREATE TABLE test_replica_identity2(
+    LIKE orders,
+    PRIMARY KEY (id)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_replica_identity2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "test_replica_identity2_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_replica_identity2 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     , CONSTRAINT test_replica_identity2_pkey PRIMARY KEY (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+ALTER TABLE test_replica_identity2 REPLICA IDENTITY USING INDEX test_replica_identity2_pkey;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "REPLICA IDENTITY %{ident}s", "type": "replica identity", "ident": {"fmt": "USING INDEX %{index}I", "index": "test_replica_identity2_pkey"}}], "identity": {"objname": "test_replica_identity2", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_replica_identity2 REPLICA IDENTITY USING INDEX test_replica_identity2_pkey
+CREATE TABLE test_replica_identity3(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_replica_identity3", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_replica_identity3 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_replica_identity3 REPLICA IDENTITY FULL;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "REPLICA IDENTITY %{ident}s", "type": "replica identity", "ident": "FULL"}], "identity": {"objname": "test_replica_identity3", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_replica_identity3 REPLICA IDENTITY FULL
+CREATE TABLE test_replica_identity4(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_replica_identity4", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_replica_identity4 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_replica_identity4 REPLICA IDENTITY NOTHING;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "REPLICA IDENTITY %{ident}s", "type": "replica identity", "ident": "NOTHING"}], "identity": {"objname": "test_replica_identity4", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_replica_identity4 REPLICA IDENTITY NOTHING
+-- RENAME [ COLUMN ] column_name TO new_column_name
+CREATE TABLE test_alter_col_name(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_alter_col_name", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_alter_col_name (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_alter_col_name RENAME id TO new_id;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{if_exists}s %{identity}D RENAME COLUMN %{colname}I TO %{newname}I", "colname": "id", "newname": "new_id", "objtype": "TABLE", "identity": {"objname": "test_alter_col_name", "schemaname": "public"}, "if_exists": ""}
+NOTICE:  re-formed command: ALTER TABLE  public.test_alter_col_name RENAME COLUMN id TO new_id
+ALTER TABLE test_alter_col_name RENAME COLUMN name TO new_name;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{if_exists}s %{identity}D RENAME COLUMN %{colname}I TO %{newname}I", "colname": "name", "newname": "new_name", "objtype": "TABLE", "identity": {"objname": "test_alter_col_name", "schemaname": "public"}, "if_exists": ""}
+NOTICE:  re-formed command: ALTER TABLE  public.test_alter_col_name RENAME COLUMN name TO new_name
+-- RENAME CONSTRAINT constraint_name TO new_constraint_name
+CREATE TABLE test_alter_constraint_name(
+    LIKE orders,
+    CONSTRAINT test_alter_constraint_name_old CHECK (id > 10)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_alter_constraint_name", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "test_alter_constraint_name_old", "type": "constraint", "contype": "check", "definition": "CHECK ((id OPERATOR(pg_catalog.>) 10))"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_alter_constraint_name (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     , CONSTRAINT test_alter_constraint_name_old CHECK ((id OPERATOR(pg_catalog.>) 10)))      
+ALTER TABLE test_alter_constraint_name RENAME CONSTRAINT test_alter_constraint_name_old TO test_alter_constraint_name_new;
+NOTICE:  deparsed json: {"fmt": "ALTER TABLE %{identity}D RENAME CONSTRAINT %{oldname}I TO %{newname}I", "newname": "test_alter_constraint_name_new", "oldname": "test_alter_constraint_name_old", "identity": {"objname": "test_alter_constraint_name", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.test_alter_constraint_name RENAME CONSTRAINT test_alter_constraint_name_old TO test_alter_constraint_name_new
+-- RENAME TO new_name
+CREATE TABLE test_rename_table(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_rename_table", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_rename_table (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+ALTER TABLE test_rename_table RENAME to new_test_rename_table;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{if_exists}s %{identity}D RENAME TO %{newname}I", "newname": "new_test_rename_table", "objtype": "TABLE", "identity": {"objname": "test_rename_table", "schemaname": "public"}, "if_exists": ""}
+NOTICE:  re-formed command: ALTER TABLE  public.test_rename_table RENAME TO new_test_rename_table
+-- SET SCHEMA new_schema
+CREATE TABLE test_set_schema(
+    LIKE orders
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_set_schema", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_set_schema (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+CREATE SCHEMA new_test_schema;
+NOTICE:  deparsed json: {"fmt": "CREATE SCHEMA %{if_not_exists}s %{name}I %{authorization}s", "name": "new_test_schema", "authorization": {"fmt": "AUTHORIZATION %{authorization_role}I", "present": false, "authorization_role": null}, "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE SCHEMA  new_test_schema 
+ALTER TABLE test_set_schema SET SCHEMA new_test_schema;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}s SET SCHEMA %{newschema}I", "objtype": "TABLE", "identity": "public.test_set_schema", "newschema": "new_test_schema"}
+NOTICE:  re-formed command: ALTER TABLE public.test_set_schema SET SCHEMA new_test_schema
+-- ALTER TABLE ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ]
+--     SET TABLESPACE new_tablespace [ NOWAIT ]
+-- TOFIX: can not be caught by ddl_command_end event trigger.
+-- Deparse of T_AlterTableMoveAllStmt is not supported,
+-- TABLESPACE commands (global object commands) are also not supported.
+-- ALTER TABLE ALL IN TABLESPACE pg_default SET TABLESPACE pg_default;
+-- ALTER TABLE ALL IN TABLESPACE pg_default OWNED BY ddl_testing_role SET TABLESPACE pg_default;
+-- ATTACH PARTITION partition_name { FOR VALUES partition_bound_spec | DEFAULT }
+CREATE TABLE test_partition_attach_range(
+    LIKE orders
+) PARTITION BY RANGE (id);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_partition_attach_range", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "RANGE (id)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_partition_attach_range (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )  PARTITION BY RANGE (id)    
+CREATE TABLE test_partition_attach_range_p_1(
+    LIKE test_partition_attach_range
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_partition_attach_range_p_1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_partition_attach_range_p_1 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+-- TOFIX
+-- ALTER TABLE test_partition_attach_range ATTACH PARTITION test_partition_attach_range_p_1 DEFAULT;
+CREATE TABLE test_partition_attach_range_p_2(
+    LIKE test_partition_attach_range
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_partition_attach_range_p_2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_partition_attach_range_p_2 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+-- TOFIX
+-- ALTER TABLE test_partition_attach_range ATTACH PARTITION test_partition_attach_range_p_2 FOR VALUES FROM (100) TO (200);
+CREATE TABLE test_partition_attach_hash(
+    LIKE orders
+) PARTITION BY HASH (id);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_partition_attach_hash", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "HASH (id)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_partition_attach_hash (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )  PARTITION BY HASH (id)    
+CREATE TABLE test_partition_attach_hash_p(
+    LIKE test_partition_attach_hash
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_partition_attach_hash_p", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_partition_attach_hash_p (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+-- TOFIX
+-- ALTER TABLE test_partition_attach_hash ATTACH PARTITION test_partition_attach_hash_p FOR VALUES WITH (MODULUS 10, REMAINDER 1);
+CREATE TABLE test_partition_attach_list(
+    LIKE orders
+) PARTITION BY LIST (name);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_partition_attach_list", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "LIST (name)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_partition_attach_list (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )  PARTITION BY LIST (name)    
+CREATE TABLE test_partition_attach_list_p1(
+    LIKE test_partition_attach_list
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_partition_attach_list_p1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_partition_attach_list_p1 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+CREATE TABLE test_partition_attach_list_p2(
+    LIKE test_partition_attach_list
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_partition_attach_list_p2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_partition_attach_list_p2 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )      
+-- TOFIX
+-- ALTER TABLE test_partition_attach_list ATTACH PARTITION test_partition_attach_list_p1 FOR VALUES IN ('key1');
+-- ALTER TABLE test_partition_attach_list ATTACH PARTITION test_partition_attach_list_p2 FOR VALUES IN ('key2', 'key3');
+-- DETACH PARTITION partition_name [ CONCURRENTLY | FINALIZE ]
+CREATE TABLE test_detach_partition(
+    LIKE orders
+) PARTITION BY RANGE (id);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_detach_partition", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "RANGE (id)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "description", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "price", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "quantity", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "purchase_date", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_detach_partition (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , description pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , price pg_catalog.float4 STORAGE plain     , quantity pg_catalog.int4 STORAGE plain     , purchase_date pg_catalog.date STORAGE plain     )  PARTITION BY RANGE (id)    
+CREATE TABLE test_detach_partition_p1 PARTITION OF test_detach_partition FOR VALUES FROM (1) TO (100);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D PARTITION OF %{parent_identity}D %{table_elements}s %{partition_bound}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_detach_partition_p1", "schemaname": "public"}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": {"fmt": "", "present": false}, "parent_identity": {"objname": "test_detach_partition", "schemaname": "public"}, "partition_bound": "FOR VALUES FROM (1) TO (100)"}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_detach_partition_p1 PARTITION OF public.test_detach_partition  FOR VALUES FROM (1) TO (100)     
+CREATE TABLE test_detach_partition_p2 PARTITION OF test_detach_partition FOR VALUES FROM (101) TO (200);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D PARTITION OF %{parent_identity}D %{table_elements}s %{partition_bound}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_detach_partition_p2", "schemaname": "public"}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": {"fmt": "", "present": false}, "parent_identity": {"objname": "test_detach_partition", "schemaname": "public"}, "partition_bound": "FOR VALUES FROM (101) TO (200)"}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_detach_partition_p2 PARTITION OF public.test_detach_partition  FOR VALUES FROM (101) TO (200)     
+CREATE TABLE test_detach_partition_p3 PARTITION OF test_detach_partition FOR VALUES FROM (201) TO (300);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D PARTITION OF %{parent_identity}D %{table_elements}s %{partition_bound}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "test_detach_partition_p3", "schemaname": "public"}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": {"fmt": "", "present": false}, "parent_identity": {"objname": "test_detach_partition", "schemaname": "public"}, "partition_bound": "FOR VALUES FROM (201) TO (300)"}
+NOTICE:  re-formed command: CREATE  TABLE  public.test_detach_partition_p3 PARTITION OF public.test_detach_partition  FOR VALUES FROM (201) TO (300)     
+-- TOFIX
+-- ALTER TABLE test_detach_partition DETACH PARTITION test_detach_partition_p1;
+-- ALTER TABLE test_detach_partition DETACH PARTITION test_detach_partition_p2 CONCURRENTLY;
+-- TOFIX: FINALIZE option is not testable
+-- ALTER TABLE test_detach_partition DETACH PARTITION test_detach_partition_p3 FINALIZE;
diff --git a/src/test/modules/test_ddl_deparse_regress/expected/constraints.out b/src/test/modules/test_ddl_deparse_regress/expected/constraints.out
new file mode 100644
index 0000000..87931b1
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/expected/constraints.out
@@ -0,0 +1,638 @@
+-- column constraint, index_parameters
+-- [ CONSTRAINT constraint_name ]
+-- { NOT NULL |
+CREATE TABLE col_cstr_not_null(
+    id int CONSTRAINT id_constraint NOT NULL,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_not_null", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_not_null (id pg_catalog.int4 STORAGE plain   NOT NULL  , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+--  NULL |
+CREATE TABLE col_cstr_null(
+    id int NULL,
+    name varchar CONSTRAINT name_constraint NOT NULL
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_null", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_null (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default" NOT NULL  )      
+--  CHECK ( expression ) [ NO INHERIT ] |
+CREATE TABLE col_cstr_check(
+    id int CHECK (id > 10),
+    name varchar NOT NULL
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_check", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_check_id_check", "type": "constraint", "contype": "check", "definition": "CHECK ((id OPERATOR(pg_catalog.>) 10))"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_check (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default" NOT NULL  , CONSTRAINT col_cstr_check_id_check CHECK ((id OPERATOR(pg_catalog.>) 10)))      
+CREATE TABLE col_cstr_check_no_inherit(
+    id int CHECK (id > 10) NO INHERIT,
+    name varchar NOT NULL
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_check_no_inherit", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_check_no_inherit_id_check", "type": "constraint", "contype": "check", "definition": "CHECK ((id OPERATOR(pg_catalog.>) 10)) NO INHERIT"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_check_no_inherit (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default" NOT NULL  , CONSTRAINT col_cstr_check_no_inherit_id_check CHECK ((id OPERATOR(pg_catalog.>) 10)) NO INHERIT)      
+--  DEFAULT default_expr |
+CREATE TABLE col_cstr_default(
+    id int NOT NULL,
+    name varchar DEFAULT 'foo'
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_default", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT %{default}s", "default": "'foo'::character varying"}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_default (id pg_catalog.int4 STORAGE plain   NOT NULL  , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"  DEFAULT 'foo'::character varying )      
+--  GENERATED ALWAYS AS ( generation_expr ) STORED |
+CREATE TABLE col_cstr_generated_always_as(
+    id int NOT NULL,
+    id_generated int GENERATED ALWAYS AS ( id * 10 ) STORED
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_generated_always_as", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id_generated", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS (%{generation_expr}s) STORED", "generation_expr": "(id OPERATOR(pg_catalog.*) 10)"}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_generated_always_as (id pg_catalog.int4 STORAGE plain   NOT NULL  , id_generated pg_catalog.int4 STORAGE plain     GENERATED ALWAYS AS ((id OPERATOR(pg_catalog.*) 10)) STORED)      
+--  GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] |
+CREATE TABLE col_cstr_generated_always_as_identity(
+    id int NOT NULL,
+    id_generated int GENERATED ALWAYS AS IDENTITY
+);
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_generated_always_as_identity", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{identity_column}s %{generated_column}s", "name": "id_generated", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "identity_column": {"fmt": "%{identity_type}s ( %{seq_definition: }s )", "identity_type": {"fmt": "GENERATED %{option}s AS IDENTITY", "option": "ALWAYS"}, "seq_definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_generated_always_as_identity (id pg_catalog.int4 STORAGE plain   NOT NULL  , id_generated pg_catalog.int4 STORAGE plain     GENERATED ALWAYS AS IDENTITY ( CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 ) )      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE col_cstr_generated_by_default_as_identity_with_options(
+    id int NOT NULL,
+    id_generated int GENERATED BY DEFAULT AS IDENTITY ( INCREMENT BY 10 )
+);
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_generated_by_default_as_identity_with_options", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{identity_column}s %{generated_column}s", "name": "id_generated", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "identity_column": {"fmt": "%{identity_type}s ( %{seq_definition: }s )", "identity_type": {"fmt": "GENERATED %{option}s AS IDENTITY", "option": "BY DEFAULT"}, "seq_definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "10", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}]}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_generated_by_default_as_identity_with_options (id pg_catalog.int4 STORAGE plain   NOT NULL  , id_generated pg_catalog.int4 STORAGE plain     GENERATED BY DEFAULT AS IDENTITY ( CACHE 1 NO CYCLE INCREMENT BY 10 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 ) )      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+--  UNIQUE [ NULLS [ NOT ] DISTINCT ] |
+CREATE TABLE col_cstr_unique(
+    id int NOT NULL,
+    name varchar UNIQUE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_unique", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_unique_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (name)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_unique (id pg_catalog.int4 STORAGE plain   NOT NULL  , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT col_cstr_unique_name_key UNIQUE (name))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE col_cstr_unique_nulls_distinct(
+    id int NOT NULL,
+    name varchar UNIQUE NULLS DISTINCT
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_unique_nulls_distinct", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_unique_nulls_distinct_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (name)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_unique_nulls_distinct (id pg_catalog.int4 STORAGE plain   NOT NULL  , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT col_cstr_unique_nulls_distinct_name_key UNIQUE (name))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE col_cstr_unique_nulls_not_distinct(
+    id int NOT NULL,
+    name varchar UNIQUE NULLS NOT DISTINCT
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_unique_nulls_not_distinct", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_unique_nulls_not_distinct_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE NULLS NOT DISTINCT (name)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_unique_nulls_not_distinct (id pg_catalog.int4 STORAGE plain   NOT NULL  , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT col_cstr_unique_nulls_not_distinct_name_key UNIQUE NULLS NOT DISTINCT (name))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+--  PRIMARY KEY |
+CREATE TABLE col_cstr_primary_key(
+    id int PRIMARY KEY,
+    name varchar UNIQUE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_primary_key", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_primary_key_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (name)"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_primary_key_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_primary_key (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT col_cstr_primary_key_name_key UNIQUE (name), CONSTRAINT col_cstr_primary_key_pkey PRIMARY KEY (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+--  REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]
+--    [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
+CREATE TABLE col_cstr_reference_table_default(
+    id int REFERENCES col_cstr_primary_key,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_default", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_default (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_default_id_fkey", "type": "add constraint", "definition": "FOREIGN KEY (id) REFERENCES public.col_cstr_primary_key(id)"}], "identity": {"objname": "col_cstr_reference_table_default", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_default ADD CONSTRAINT col_cstr_reference_table_default_id_fkey FOREIGN KEY (id) REFERENCES public.col_cstr_primary_key(id)
+CREATE TABLE col_cstr_reference_table_column(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name)"}], "identity": {"objname": "col_cstr_reference_table_column", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column ADD CONSTRAINT col_cstr_reference_table_column_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name)
+-- [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]
+-- skip testing MATCH PARTIAL, which is treated as a syntax error with message
+-- ERROR:  MATCH PARTIAL not yet implemented
+CREATE TABLE col_cstr_reference_table_column_match_full(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) MATCH FULL
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_match_full", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_match_full (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_match_full_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) MATCH FULL"}], "identity": {"objname": "col_cstr_reference_table_column_match_full", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_match_full ADD CONSTRAINT col_cstr_reference_table_column_match_full_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) MATCH FULL
+CREATE TABLE col_cstr_reference_table_column_match_simple(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) MATCH SIMPLE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_match_simple", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_match_simple (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_match_simple_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name)"}], "identity": {"objname": "col_cstr_reference_table_column_match_simple", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_match_simple ADD CONSTRAINT col_cstr_reference_table_column_match_simple_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name)
+-- [ ON DELETE referential_action ] 
+CREATE TABLE col_cstr_reference_table_column_on_delete_no_action(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE NO ACTION
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_on_delete_no_action", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_on_delete_no_action (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_on_delete_no_action_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name)"}], "identity": {"objname": "col_cstr_reference_table_column_on_delete_no_action", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_on_delete_no_action ADD CONSTRAINT col_cstr_reference_table_column_on_delete_no_action_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name)
+CREATE TABLE col_cstr_reference_table_column_on_delete_restrict(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE RESTRICT
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_on_delete_restrict", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_on_delete_restrict (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_on_delete_restrict_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON DELETE RESTRICT"}], "identity": {"objname": "col_cstr_reference_table_column_on_delete_restrict", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_on_delete_restrict ADD CONSTRAINT col_cstr_reference_table_column_on_delete_restrict_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON DELETE RESTRICT
+CREATE TABLE col_cstr_reference_table_column_on_delete_cascade(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE CASCADE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_on_delete_cascade", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_on_delete_cascade (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_on_delete_cascade_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON DELETE CASCADE"}], "identity": {"objname": "col_cstr_reference_table_column_on_delete_cascade", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_on_delete_cascade ADD CONSTRAINT col_cstr_reference_table_column_on_delete_cascade_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON DELETE CASCADE
+CREATE TABLE col_cstr_reference_table_column_on_delete_set_null(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE SET NULL
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_on_delete_set_null", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_on_delete_set_null (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_on_delete_set_null_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON DELETE SET NULL"}], "identity": {"objname": "col_cstr_reference_table_column_on_delete_set_null", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_on_delete_set_null ADD CONSTRAINT col_cstr_reference_table_column_on_delete_set_null_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON DELETE SET NULL
+CREATE TABLE col_cstr_reference_table_column_on_delete_set_null_with_column(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE SET NULL (name),
+    foo varchar REFERENCES col_cstr_primary_key (name) ON DELETE SET NULL (foo)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_on_delete_set_null_with_column", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "foo", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_on_delete_set_null_with_column (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , foo pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_on_delete_set_null_wi_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON DELETE SET NULL (name)"}, {"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_on_delete_set_null_wit_foo_fkey", "type": "add constraint", "definition": "FOREIGN KEY (foo) REFERENCES public.col_cstr_primary_key(name) ON DELETE SET NULL (foo)"}], "identity": {"objname": "col_cstr_reference_table_column_on_delete_set_null_with_column", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_on_delete_set_null_with_column ADD CONSTRAINT col_cstr_reference_table_column_on_delete_set_null_wi_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON DELETE SET NULL (name), ADD CONSTRAINT col_cstr_reference_table_column_on_delete_set_null_wit_foo_fkey FOREIGN KEY (foo) REFERENCES public.col_cstr_primary_key(name) ON DELETE SET NULL (foo)
+CREATE TABLE col_cstr_reference_table_column_on_delete_set_default(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE SET DEFAULT
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_on_delete_set_default", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_on_delete_set_default (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_on_delete_set_default_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON DELETE SET DEFAULT"}], "identity": {"objname": "col_cstr_reference_table_column_on_delete_set_default", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_on_delete_set_default ADD CONSTRAINT col_cstr_reference_table_column_on_delete_set_default_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON DELETE SET DEFAULT
+CREATE TABLE col_cstr_reference_table_column_on_delete_set_default_with_col(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE SET DEFAULT (name)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_on_delete_set_default_with_col", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_on_delete_set_default_with_col (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_on_delete_set_defaul_name_fkey1", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON DELETE SET DEFAULT (name)"}], "identity": {"objname": "col_cstr_reference_table_column_on_delete_set_default_with_col", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_on_delete_set_default_with_col ADD CONSTRAINT col_cstr_reference_table_column_on_delete_set_defaul_name_fkey1 FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON DELETE SET DEFAULT (name)
+-- [ ON UPDATE referential_action ]
+CREATE TABLE col_cstr_reference_table_column_on_update_no_action(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON UPDATE NO ACTION
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_on_update_no_action", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_on_update_no_action (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_on_update_no_action_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name)"}], "identity": {"objname": "col_cstr_reference_table_column_on_update_no_action", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_on_update_no_action ADD CONSTRAINT col_cstr_reference_table_column_on_update_no_action_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name)
+CREATE TABLE col_cstr_reference_table_column_on_update_restrict(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON UPDATE RESTRICT
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_on_update_restrict", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_on_update_restrict (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_on_update_restrict_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON UPDATE RESTRICT"}], "identity": {"objname": "col_cstr_reference_table_column_on_update_restrict", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_on_update_restrict ADD CONSTRAINT col_cstr_reference_table_column_on_update_restrict_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON UPDATE RESTRICT
+CREATE TABLE col_cstr_reference_table_column_on_update_cascade(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON UPDATE CASCADE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_on_update_cascade", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_on_update_cascade (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_on_update_cascade_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON UPDATE CASCADE"}], "identity": {"objname": "col_cstr_reference_table_column_on_update_cascade", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_on_update_cascade ADD CONSTRAINT col_cstr_reference_table_column_on_update_cascade_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON UPDATE CASCADE
+CREATE TABLE col_cstr_reference_table_column_on_update_set_null(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON UPDATE SET NULL
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_on_update_set_null", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_on_update_set_null (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_on_update_set_null_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON UPDATE SET NULL"}], "identity": {"objname": "col_cstr_reference_table_column_on_update_set_null", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_on_update_set_null ADD CONSTRAINT col_cstr_reference_table_column_on_update_set_null_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON UPDATE SET NULL
+CREATE TABLE col_cstr_reference_table_column_on_update_set_default(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON UPDATE SET DEFAULT
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_on_update_set_default", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_on_update_set_default (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_on_update_set_default_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON UPDATE SET DEFAULT"}], "identity": {"objname": "col_cstr_reference_table_column_on_update_set_default", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_on_update_set_default ADD CONSTRAINT col_cstr_reference_table_column_on_update_set_default_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) ON UPDATE SET DEFAULT
+-- complex combinations
+CREATE TABLE col_cstr_reference_table_column_complex_combination1(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) MATCH FULL ON DELETE NO ACTION ON UPDATE NO ACTION
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_complex_combination1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_complex_combination1 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_complex_combination1_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) MATCH FULL"}], "identity": {"objname": "col_cstr_reference_table_column_complex_combination1", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_complex_combination1 ADD CONSTRAINT col_cstr_reference_table_column_complex_combination1_name_fkey FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) MATCH FULL
+CREATE TABLE col_cstr_reference_table_column_complex_combination2(
+    id int REFERENCES col_cstr_primary_key MATCH FULL ON DELETE SET DEFAULT ON UPDATE SET NULL,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_reference_table_column_complex_combination2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_reference_table_column_complex_combination2 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_reference_table_column_complex_combination2_id_fkey", "type": "add constraint", "definition": "FOREIGN KEY (id) REFERENCES public.col_cstr_primary_key(id) MATCH FULL ON UPDATE SET NULL ON DELETE SET DEFAULT"}], "identity": {"objname": "col_cstr_reference_table_column_complex_combination2", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_reference_table_column_complex_combination2 ADD CONSTRAINT col_cstr_reference_table_column_complex_combination2_id_fkey FOREIGN KEY (id) REFERENCES public.col_cstr_primary_key(id) MATCH FULL ON UPDATE SET NULL ON DELETE SET DEFAULT
+-- [ DEFERRABLE | NOT DEFERRABLE ]
+CREATE TABLE col_cstr_deferable(
+    id int,
+    name varchar UNIQUE DEFERRABLE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_deferable", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_deferable_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (name) DEFERRABLE"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_deferable (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT col_cstr_deferable_name_key UNIQUE (name) DEFERRABLE)      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE col_cstr_not_deferable(
+    id int PRIMARY KEY NOT DEFERRABLE,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_not_deferable", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_not_deferable_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_not_deferable (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT col_cstr_not_deferable_pkey PRIMARY KEY (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
+CREATE TABLE col_cstr_initially_deferred(
+    id int PRIMARY KEY INITIALLY DEFERRED,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_initially_deferred", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_initially_deferred_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id) DEFERRABLE INITIALLY DEFERRED"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_initially_deferred (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT col_cstr_initially_deferred_pkey PRIMARY KEY (id) DEFERRABLE INITIALLY DEFERRED)      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE col_cstr_initially_immediate(
+    id int,
+    name varchar UNIQUE INITIALLY IMMEDIATE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_initially_immediate", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "col_cstr_initially_immediate_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (name)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_initially_immediate (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT col_cstr_initially_immediate_name_key UNIQUE (name))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- complex combination
+CREATE TABLE col_cstr_complex_combination(
+    id int,
+    name varchar CONSTRAINT name_constraint REFERENCES col_cstr_primary_key (name) MATCH FULL ON DELETE SET DEFAULT ON UPDATE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "col_cstr_complex_combination", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.col_cstr_complex_combination (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "name_constraint", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) MATCH FULL ON UPDATE SET NULL ON DELETE SET DEFAULT"}], "identity": {"objname": "col_cstr_complex_combination", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.col_cstr_complex_combination ADD CONSTRAINT name_constraint FOREIGN KEY (name) REFERENCES public.col_cstr_primary_key(name) MATCH FULL ON UPDATE SET NULL ON DELETE SET DEFAULT
+-- part 4: table constraints
+-- [ CONSTRAINT constraint_name ]
+-- { CHECK ( expression ) [ NO INHERIT ] |
+CREATE TABLE tbl_cstr_check_1(
+    CONSTRAINT id_constraint CHECK (id > 10),
+    id int,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_check_1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "id_constraint", "type": "constraint", "contype": "check", "definition": "CHECK ((id OPERATOR(pg_catalog.>) 10))"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_check_1 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT id_constraint CHECK ((id OPERATOR(pg_catalog.>) 10)))      
+CREATE TABLE tbl_cstr_check_2(
+    id int,
+    name varchar,
+    CONSTRAINT table_check CHECK (id > 10) NO INHERIT
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_check_2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "table_check", "type": "constraint", "contype": "check", "definition": "CHECK ((id OPERATOR(pg_catalog.>) 10)) NO INHERIT"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_check_2 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT table_check CHECK ((id OPERATOR(pg_catalog.>) 10)) NO INHERIT)      
+CREATE TABLE tbl_cstr_check_no_inherit(
+    id int,
+    name varchar,
+    CHECK (id > 10) NO INHERIT
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_check_no_inherit", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_check_no_inherit_id_check", "type": "constraint", "contype": "check", "definition": "CHECK ((id OPERATOR(pg_catalog.>) 10)) NO INHERIT"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_check_no_inherit (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_check_no_inherit_id_check CHECK ((id OPERATOR(pg_catalog.>) 10)) NO INHERIT)      
+--   UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] ) [ INCLUDE ( column_name [, ...]) ] |
+CREATE TABLE tbl_cstr_unique(
+    id int,
+    name varchar,
+    UNIQUE (id)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_unique", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_unique_id_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_unique (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_unique_id_key UNIQUE (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_unique_multicols(
+    id int,
+    name varchar,
+    UNIQUE (id, name)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_unique_multicols", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_unique_multicols_id_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id, name)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_unique_multicols (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_unique_multicols_id_name_key UNIQUE (id, name))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_unique_nulls_distinct(
+    id int,
+    name varchar,
+    UNIQUE NULLS DISTINCT (id)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_unique_nulls_distinct", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_unique_nulls_distinct_id_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_unique_nulls_distinct (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_unique_nulls_distinct_id_key UNIQUE (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_unique_nulls_not_distinct(
+    id int,
+    name varchar,
+    UNIQUE NULLS NOT DISTINCT (id, name)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_unique_nulls_not_distinct", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_unique_nulls_not_distinct_id_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE NULLS NOT DISTINCT (id, name)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_unique_nulls_not_distinct (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_unique_nulls_not_distinct_id_name_key UNIQUE NULLS NOT DISTINCT (id, name))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_unique_nulls_distinct_include(
+    id int,
+    name varchar,
+    UNIQUE NULLS DISTINCT (id) INCLUDE (name)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_unique_nulls_distinct_include", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_unique_nulls_distinct_include_id_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id) INCLUDE (name)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_unique_nulls_distinct_include (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_unique_nulls_distinct_include_id_name_key UNIQUE (id) INCLUDE (name))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_unique_nulls_distinct_include_multi(
+    id int,
+    name varchar,
+    info varchar,
+    UNIQUE NULLS DISTINCT (id) INCLUDE (name, info)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_unique_nulls_distinct_include_multi", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "info", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_unique_nulls_distinct_include_multi_id_name_info_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id) INCLUDE (name, info)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_unique_nulls_distinct_include_multi (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , info pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_unique_nulls_distinct_include_multi_id_name_info_key UNIQUE (id) INCLUDE (name, info))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- PRIMARY KEY ( column_name [, ... ] ) [ INCLUDE ( column_name [, ...]) ] |
+CREATE TABLE tbl_cstr_primary_key(
+    id int,
+    name varchar,
+    PRIMARY KEY (id)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_primary_key", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_primary_key_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_primary_key (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_primary_key_pkey PRIMARY KEY (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_primary_key_multicols(
+    id int,
+    name varchar,
+    PRIMARY KEY (id, name)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_primary_key_multicols", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_primary_key_multicols_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id, name)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_primary_key_multicols (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_primary_key_multicols_pkey PRIMARY KEY (id, name))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_primary_key_include(
+    id int,
+    name varchar,
+    PRIMARY KEY (id) INCLUDE (name)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_primary_key_include", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_primary_key_include_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id) INCLUDE (name)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_primary_key_include (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_primary_key_include_pkey PRIMARY KEY (id) INCLUDE (name))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_primary_key_include_multicols(
+    id int,
+    name varchar,
+    info varchar,
+    PRIMARY KEY (id) INCLUDE (name, info)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_primary_key_include_multicols", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "info", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_primary_key_include_multicols_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id) INCLUDE (name, info)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_primary_key_include_multicols (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , info pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_primary_key_include_multicols_pkey PRIMARY KEY (id) INCLUDE (name, info))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+--   EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] |
+CREATE TABLE tbl_cstr_exclude(
+    id int,
+    name varchar,
+    EXCLUDE (name WITH =)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_exclude", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_exclude_name_excl", "type": "constraint", "contype": "exclusion", "definition": "EXCLUDE USING btree (name WITH OPERATOR(pg_catalog.=))"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_exclude (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_exclude_name_excl EXCLUDE USING btree (name WITH OPERATOR(pg_catalog.=)))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_exclude_multi(
+    id int,
+    name varchar,
+    EXCLUDE ((id*10) with =, name WITH =)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_exclude_multi", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_exclude_multi_expr_name_excl", "type": "constraint", "contype": "exclusion", "definition": "EXCLUDE USING btree (((id OPERATOR(pg_catalog.*) 10)) WITH OPERATOR(pg_catalog.=), name WITH OPERATOR(pg_catalog.=))"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_exclude_multi (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_exclude_multi_expr_name_excl EXCLUDE USING btree (((id OPERATOR(pg_catalog.*) 10)) WITH OPERATOR(pg_catalog.=), name WITH OPERATOR(pg_catalog.=)))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_exclude_index_method(
+    id int,
+    name varchar,
+    EXCLUDE USING btree ((id*10) with =, name WITH =)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_exclude_index_method", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_exclude_index_method_expr_name_excl", "type": "constraint", "contype": "exclusion", "definition": "EXCLUDE USING btree (((id OPERATOR(pg_catalog.*) 10)) WITH OPERATOR(pg_catalog.=), name WITH OPERATOR(pg_catalog.=))"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_exclude_index_method (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_exclude_index_method_expr_name_excl EXCLUDE USING btree (((id OPERATOR(pg_catalog.*) 10)) WITH OPERATOR(pg_catalog.=), name WITH OPERATOR(pg_catalog.=)))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- [ INCLUDE ( column_name [, ... ] ) ]
+CREATE TABLE tbl_cstr_exclude_with_index_params_include_1(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) INCLUDE (name)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_exclude_with_index_params_include_1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_exclude_with_index_params_include_1_id_name_excl", "type": "constraint", "contype": "exclusion", "definition": "EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=)) INCLUDE (name)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_exclude_with_index_params_include_1 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_exclude_with_index_params_include_1_id_name_excl EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=)) INCLUDE (name))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_exclude_with_index_params_include_2(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) INCLUDE (id, name)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_exclude_with_index_params_include_2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_exclude_with_index_params_include_2_id_id1_name_excl", "type": "constraint", "contype": "exclusion", "definition": "EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=)) INCLUDE (id, name)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_exclude_with_index_params_include_2 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_exclude_with_index_params_include_2_id_id1_name_excl EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=)) INCLUDE (id, name))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- [ WITH ( storage_parameter [= value] [, ... ] ) ]
+CREATE TABLE tbl_cstr_exclude_with_index_params_storage_1(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) WITH (fillfactor = 20)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_exclude_with_index_params_storage_1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_exclude_with_index_params_storage_1_id_excl", "type": "constraint", "contype": "exclusion", "definition": "EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=)) WITH (fillfactor='20')"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_exclude_with_index_params_storage_1 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_exclude_with_index_params_storage_1_id_excl EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=)) WITH (fillfactor='20'))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_exclude_with_index_params_storage_2(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) WITH (fillfactor = 20, deduplicate_items = false)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_exclude_with_index_params_storage_2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_exclude_with_index_params_storage_2_id_excl", "type": "constraint", "contype": "exclusion", "definition": "EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=)) WITH (fillfactor='20', deduplicate_items='false')"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_exclude_with_index_params_storage_2 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_exclude_with_index_params_storage_2_id_excl EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=)) WITH (fillfactor='20', deduplicate_items='false'))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- [ USING INDEX TABLESPACE tablespace_name ]
+CREATE TABLE tbl_cstr_exclude_with_index_params_tablespace(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) USING INDEX TABLESPACE pg_default
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_exclude_with_index_params_tablespace", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_exclude_with_index_params_tablespace_id_excl", "type": "constraint", "contype": "exclusion", "definition": "EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=))"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_exclude_with_index_params_tablespace (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_exclude_with_index_params_tablespace_id_excl EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=)))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- index_parameters complex combination
+CREATE TABLE tbl_cstr_exclude_with_index_params_complex(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) INCLUDE (id, name) WITH (fillfactor = 20, deduplicate_items = false) USING INDEX TABLESPACE pg_default
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_exclude_with_index_params_complex", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_exclude_with_index_params_complex_id_id1_name_excl", "type": "constraint", "contype": "exclusion", "definition": "EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=)) INCLUDE (id, name) WITH (fillfactor='20', deduplicate_items='false')"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_exclude_with_index_params_complex (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_exclude_with_index_params_complex_id_id1_name_excl EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=)) INCLUDE (id, name) WITH (fillfactor='20', deduplicate_items='false'))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- [ WHERE ( predicate ) ]
+CREATE TABLE tbl_cstr_exclude_with_predicate(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) WHERE (name<>'foo')
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_exclude_with_predicate", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_exclude_with_predicate_id_excl", "type": "constraint", "contype": "exclusion", "definition": "EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=)) WHERE (((name)::pg_catalog.text OPERATOR(pg_catalog.<>) 'foo'::pg_catalog.text))"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_exclude_with_predicate (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_exclude_with_predicate_id_excl EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=)) WHERE (((name)::pg_catalog.text OPERATOR(pg_catalog.<>) 'foo'::pg_catalog.text)))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- complex combination for table constraint clauses
+CREATE TABLE tbl_cstr_exclude_complex_combination(
+    id int,
+    name varchar,
+    EXCLUDE USING btree (id WITH =, name WITH =) INCLUDE (id, name) WITH (fillfactor = 20, deduplicate_items = false) USING INDEX TABLESPACE pg_default WHERE (name<>'foo')
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_exclude_complex_combination", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_exclude_complex_combination_id_name_id1_name1_excl", "type": "constraint", "contype": "exclusion", "definition": "EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=), name WITH OPERATOR(pg_catalog.=)) INCLUDE (id, name) WITH (fillfactor='20', deduplicate_items='false') WHERE (((name)::pg_catalog.text OPERATOR(pg_catalog.<>) 'foo'::pg_catalog.text))"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_exclude_complex_combination (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_exclude_complex_combination_id_name_id1_name1_excl EXCLUDE USING btree (id WITH OPERATOR(pg_catalog.=), name WITH OPERATOR(pg_catalog.=)) INCLUDE (id, name) WITH (fillfactor='20', deduplicate_items='false') WHERE (((name)::pg_catalog.text OPERATOR(pg_catalog.<>) 'foo'::pg_catalog.text)))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ]
+--     [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
+CREATE TABLE tbl_cstr_foreign_table(
+    id int PRIMARY KEY,
+    name varchar UNIQUE,
+    UNIQUE (id, name)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_foreign_table", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_foreign_table_id_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id, name)"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_foreign_table_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (name)"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_foreign_table_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_foreign_table (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_foreign_table_id_name_key UNIQUE (id, name), CONSTRAINT tbl_cstr_foreign_table_name_key UNIQUE (name), CONSTRAINT tbl_cstr_foreign_table_pkey PRIMARY KEY (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_foreign_key_simple_1(
+    id int,
+    name varchar,
+    FOREIGN KEY (id) REFERENCES tbl_cstr_foreign_table
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_foreign_key_simple_1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_foreign_key_simple_1 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_foreign_key_simple_1_id_fkey", "type": "add constraint", "definition": "FOREIGN KEY (id) REFERENCES public.tbl_cstr_foreign_table(id)"}], "identity": {"objname": "tbl_cstr_foreign_key_simple_1", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.tbl_cstr_foreign_key_simple_1 ADD CONSTRAINT tbl_cstr_foreign_key_simple_1_id_fkey FOREIGN KEY (id) REFERENCES public.tbl_cstr_foreign_table(id)
+CREATE TABLE tbl_cstr_foreign_key_simple_2(
+    id int,
+    name varchar,
+    FOREIGN KEY (id) REFERENCES tbl_cstr_foreign_table(id)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_foreign_key_simple_2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_foreign_key_simple_2 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_foreign_key_simple_2_id_fkey", "type": "add constraint", "definition": "FOREIGN KEY (id) REFERENCES public.tbl_cstr_foreign_table(id)"}], "identity": {"objname": "tbl_cstr_foreign_key_simple_2", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.tbl_cstr_foreign_key_simple_2 ADD CONSTRAINT tbl_cstr_foreign_key_simple_2_id_fkey FOREIGN KEY (id) REFERENCES public.tbl_cstr_foreign_table(id)
+CREATE TABLE tbl_cstr_foreign_key_multiple_keys(
+    id int,
+    name varchar,
+    FOREIGN KEY (id, name) REFERENCES tbl_cstr_foreign_table (id, name)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_foreign_key_multiple_keys", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_foreign_key_multiple_keys (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_foreign_key_multiple_keys_id_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (id, name) REFERENCES public.tbl_cstr_foreign_table(id, name)"}], "identity": {"objname": "tbl_cstr_foreign_key_multiple_keys", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.tbl_cstr_foreign_key_multiple_keys ADD CONSTRAINT tbl_cstr_foreign_key_multiple_keys_id_name_fkey FOREIGN KEY (id, name) REFERENCES public.tbl_cstr_foreign_table(id, name)
+-- some combinations from REFERENCES clause, which is already tested in part 3
+CREATE TABLE tbl_cstr_reference_table_complex_combination1(
+    id int,
+    name varchar,
+    FOREIGN KEY (name) REFERENCES tbl_cstr_foreign_table (name) MATCH SIMPLE ON DELETE CASCADE ON UPDATE SET NULL
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_reference_table_complex_combination1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_reference_table_complex_combination1 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_reference_table_complex_combination1_name_fkey", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.tbl_cstr_foreign_table(name) ON UPDATE SET NULL ON DELETE CASCADE"}], "identity": {"objname": "tbl_cstr_reference_table_complex_combination1", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.tbl_cstr_reference_table_complex_combination1 ADD CONSTRAINT tbl_cstr_reference_table_complex_combination1_name_fkey FOREIGN KEY (name) REFERENCES public.tbl_cstr_foreign_table(name) ON UPDATE SET NULL ON DELETE CASCADE
+CREATE TABLE tbl_cstr_reference_table_complex_combination2(
+    id int,
+    name varchar,
+    CONSTRAINT tbl_cstr FOREIGN KEY (id, name) REFERENCES tbl_cstr_foreign_table (id, name) ON DELETE SET NULL (id, name) ON UPDATE SET DEFAULT
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_reference_table_complex_combination2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_reference_table_complex_combination2 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr", "type": "add constraint", "definition": "FOREIGN KEY (id, name) REFERENCES public.tbl_cstr_foreign_table(id, name) ON UPDATE SET DEFAULT ON DELETE SET NULL (id, name)"}], "identity": {"objname": "tbl_cstr_reference_table_complex_combination2", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.tbl_cstr_reference_table_complex_combination2 ADD CONSTRAINT tbl_cstr FOREIGN KEY (id, name) REFERENCES public.tbl_cstr_foreign_table(id, name) ON UPDATE SET DEFAULT ON DELETE SET NULL (id, name)
+-- [ DEFERRABLE | NOT DEFERRABLE ]
+CREATE TABLE tbl_cstr_reference_table_column_deferable(
+    id int,
+    name varchar,
+    UNIQUE (id, name) DEFERRABLE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_reference_table_column_deferable", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_reference_table_column_deferable_id_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id, name) DEFERRABLE"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_reference_table_column_deferable (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_reference_table_column_deferable_id_name_key UNIQUE (id, name) DEFERRABLE)      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_reference_table_column_not_deferable(
+    id int,
+    name varchar,
+    PRIMARY KEY (id) NOT DEFERRABLE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_reference_table_column_not_deferable", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_reference_table_column_not_deferable_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_reference_table_column_not_deferable (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_reference_table_column_not_deferable_pkey PRIMARY KEY (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
+CREATE TABLE tbl_cstr_reference_table_column_initially_deferred(
+    id int,
+    name varchar,
+    UNIQUE (id, name) INITIALLY DEFERRED
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_reference_table_column_initially_deferred", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_reference_table_column_initially_deferred_id_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (id, name) DEFERRABLE INITIALLY DEFERRED"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_reference_table_column_initially_deferred (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_reference_table_column_initially_deferred_id_name_key UNIQUE (id, name) DEFERRABLE INITIALLY DEFERRED)      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE tbl_cstr_reference_table_column_initially_immediate(
+    id int,
+    name varchar,
+    PRIMARY KEY (id) INITIALLY IMMEDIATE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_reference_table_column_initially_immediate", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr_reference_table_column_initially_immediate_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_reference_table_column_initially_immediate (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr_reference_table_column_initially_immediate_pkey PRIMARY KEY (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- complex combinations
+CREATE TABLE tbl_cstr_reference_table_column_complex_combination1(
+    id int,
+    name varchar,
+    CONSTRAINT tbl_cstr FOREIGN KEY (name) REFERENCES tbl_cstr_foreign_table (name) MATCH FULL ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_reference_table_column_complex_combination1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_reference_table_column_complex_combination1 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr", "type": "add constraint", "definition": "FOREIGN KEY (name) REFERENCES public.tbl_cstr_foreign_table(name) MATCH FULL DEFERRABLE INITIALLY DEFERRED"}], "identity": {"objname": "tbl_cstr_reference_table_column_complex_combination1", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.tbl_cstr_reference_table_column_complex_combination1 ADD CONSTRAINT tbl_cstr FOREIGN KEY (name) REFERENCES public.tbl_cstr_foreign_table(name) MATCH FULL DEFERRABLE INITIALLY DEFERRED
+CREATE TABLE tbl_cstr_reference_table_column_complex_combination2(
+    id int,
+    name varchar,
+    CONSTRAINT tbl_cstr PRIMARY KEY (id, name) NOT DEFERRABLE INITIALLY IMMEDIATE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "tbl_cstr_reference_table_column_complex_combination2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "tbl_cstr", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id, name)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.tbl_cstr_reference_table_column_complex_combination2 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT tbl_cstr PRIMARY KEY (id, name))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
diff --git a/src/test/modules/test_ddl_deparse_regress/expected/create_extension.out b/src/test/modules/test_ddl_deparse_regress/expected/create_extension.out
new file mode 100644
index 0000000..06ccc62
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/expected/create_extension.out
@@ -0,0 +1,6 @@
+---
+--- CREATE_EXTENSION
+---
+CREATE EXTENSION pg_stat_statements;
+NOTICE:  deparsed json: {"fmt": "CREATE EXTENSION %{if_not_exists}s %{name}I %{options: }s", "name": "pg_stat_statements", "options": [{"fmt": "SCHEMA %{schema}I", "type": "schema", "schema": "public"}], "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE EXTENSION  pg_stat_statements SCHEMA public
diff --git a/src/test/modules/test_ddl_deparse_regress/expected/create_schema.out b/src/test/modules/test_ddl_deparse_regress/expected/create_schema.out
new file mode 100644
index 0000000..ea6e86a
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/expected/create_schema.out
@@ -0,0 +1,22 @@
+--
+-- CREATE_SCHEMA
+--
+CREATE SCHEMA foo;
+NOTICE:  deparsed json: {"fmt": "CREATE SCHEMA %{if_not_exists}s %{name}I %{authorization}s", "name": "foo", "authorization": {"fmt": "AUTHORIZATION %{authorization_role}I", "present": false, "authorization_role": null}, "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE SCHEMA  foo 
+CREATE SCHEMA IF NOT EXISTS bar;
+NOTICE:  deparsed json: {"fmt": "CREATE SCHEMA %{if_not_exists}s %{name}I %{authorization}s", "name": "bar", "authorization": {"fmt": "AUTHORIZATION %{authorization_role}I", "present": false, "authorization_role": null}, "if_not_exists": "IF NOT EXISTS"}
+NOTICE:  re-formed command: CREATE SCHEMA IF NOT EXISTS bar 
+CREATE SCHEMA baz;
+NOTICE:  deparsed json: {"fmt": "CREATE SCHEMA %{if_not_exists}s %{name}I %{authorization}s", "name": "baz", "authorization": {"fmt": "AUTHORIZATION %{authorization_role}I", "present": false, "authorization_role": null}, "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE SCHEMA  baz 
+-- Will not be created, and will not be handled by the
+-- event trigger
+CREATE SCHEMA IF NOT EXISTS baz;
+NOTICE:  schema "baz" already exists, skipping
+CREATE SCHEMA element_test
+  CREATE TABLE foo (id int)
+NOTICE:  deparsed json: {"fmt": "CREATE SCHEMA %{if_not_exists}s %{name}I %{authorization}s", "name": "element_test", "authorization": {"fmt": "AUTHORIZATION %{authorization_role}I", "present": false, "authorization_role": null}, "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE SCHEMA  element_test 
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "foo", "schemaname": "element_test"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  element_test.foo (id pg_catalog.int4 STORAGE plain     )      
diff --git a/src/test/modules/test_ddl_deparse_regress/expected/create_table.out b/src/test/modules/test_ddl_deparse_regress/expected/create_table.out
new file mode 100644
index 0000000..bb21f09
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/expected/create_table.out
@@ -0,0 +1,599 @@
+-- part 1: shared prefixes 
+-- [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ]
+CREATE TABLE part1_simple_table(
+    id int,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part1_simple_table", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part1_simple_table (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TEMPORARY TABLE part1_temp_table0(
+    id int,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part1_temp_table0", "schemaname": "pg_temp"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "TEMPORARY", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE TEMPORARY TABLE  pg_temp.part1_temp_table0 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TEMP TABLE part1_temp_table(
+    id int,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part1_temp_table", "schemaname": "pg_temp"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "TEMPORARY", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE TEMPORARY TABLE  pg_temp.part1_temp_table (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+-- GLOBAL TEMP TATBLE is deprecated, expect warning message and create local temp table
+CREATE GLOBAL TEMP TABLE part1_global_temp_table(
+    id int,
+    name varchar
+);
+WARNING:  GLOBAL is deprecated in temporary table creation
+LINE 1: CREATE GLOBAL TEMP TABLE part1_global_temp_table(
+               ^
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part1_global_temp_table", "schemaname": "pg_temp"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "TEMPORARY", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE TEMPORARY TABLE  pg_temp.part1_global_temp_table (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE LOCAL TEMP TABLE part1_local_temp_table(
+    id int,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part1_local_temp_table", "schemaname": "pg_temp"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "TEMPORARY", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE TEMPORARY TABLE  pg_temp.part1_local_temp_table (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE UNLOGGED TABLE part1_unlogged_table(
+    id int,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part1_unlogged_table", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "UNLOGGED", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE UNLOGGED TABLE  public.part1_unlogged_table (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+-- [ IF NOT EXISTS ]
+CREATE TABLE IF NOT EXISTS part1_simple_table(
+    id int,
+    name varchar
+);
+NOTICE:  relation "part1_simple_table" already exists, skipping
+CREATE TABLE IF NOT EXISTS part1_local_temp_table_not_exists(
+    id int,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part1_local_temp_table_not_exists", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "IF NOT EXISTS", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE IF NOT EXISTS public.part1_local_temp_table_not_exists (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+-- part 2: shared suffixes
+-- [ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]
+CREATE TABLE part2_partition_by_range_simple(
+    id int, 
+    name varchar
+) PARTITION BY RANGE (id);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_partition_by_range_simple", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "RANGE (id)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part2_partition_by_range_simple (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )  PARTITION BY RANGE (id)    
+CREATE TABLE part2_partition_by_list_simple(
+    id int, 
+    name varchar
+) PARTITION BY LIST (id);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_partition_by_list_simple", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "LIST (id)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part2_partition_by_list_simple (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )  PARTITION BY LIST (id)    
+CREATE TABLE part2_partition_by_hash_simple(
+    id int, 
+    name varchar
+) PARTITION BY HASH (id);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_partition_by_hash_simple", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "HASH (id)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part2_partition_by_hash_simple (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )  PARTITION BY HASH (id)    
+CREATE TABLE part2_partition_with_expression(
+    id int,
+    name varchar
+) PARTITION BY RANGE ((id * 190), name);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_partition_with_expression", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "RANGE (((id OPERATOR(pg_catalog.*) 190)), name)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part2_partition_with_expression (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )  PARTITION BY RANGE (((id OPERATOR(pg_catalog.*) 190)), name)    
+CREATE TABLE part2_partition_with_collation(
+    id int,
+    name varchar
+) PARTITION BY LIST (name COLLATE "fr_FR");
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_partition_with_collation", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "LIST (name COLLATE pg_catalog.\"fr_FR\")"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part2_partition_with_collation (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )  PARTITION BY LIST (name COLLATE pg_catalog."fr_FR")    
+CREATE TABLE part2_partition_with_opclass(
+    id int,
+    name varchar
+) PARTITION BY HASH (id int4_ops, name varchar_ops);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_partition_with_opclass", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "HASH (id, name pg_catalog.varchar_ops)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part2_partition_with_opclass (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )  PARTITION BY HASH (id, name pg_catalog.varchar_ops)    
+CREATE TABLE part2_partition_with_collation_opclass(
+    id int,
+    name varchar
+) PARTITION BY RANGE ((id * 10) int4_ops, name COLLATE "fr_FR" varchar_ops);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_partition_with_collation_opclass", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "RANGE (((id OPERATOR(pg_catalog.*) 10)), name COLLATE pg_catalog.\"fr_FR\" pg_catalog.varchar_ops)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part2_partition_with_collation_opclass (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )  PARTITION BY RANGE (((id OPERATOR(pg_catalog.*) 10)), name COLLATE pg_catalog."fr_FR" pg_catalog.varchar_ops)    
+-- [ USING method ]
+-- default method
+CREATE TABLE part2_using_default_access_method(
+    id int,
+    name varchar
+) USING heap;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_using_default_access_method", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "access_method": "heap"}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part2_using_default_access_method (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )   USING heap   
+-- [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ]
+CREATE TABLE part2_without_oids(
+    id int,
+    name varchar
+) WITHOUT OIDS;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_without_oids", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part2_without_oids (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part2_with_one_storage_param(
+    id int,
+    name varchar
+) WITH (fillfactor = 20);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_with_one_storage_param", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH (%{with:, }s)", "with": [{"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "fillfactor"}, "value": "20"}]}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part2_with_one_storage_param (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )    WITH (fillfactor = '20')  
+CREATE TABLE part2_with_multiple_storage_params(
+    id int,
+    name varchar
+) WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_with_multiple_storage_params", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH (%{with:, }s)", "with": [{"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_index_cleanup"}, "value": "on"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "autovacuum_vacuum_scale_factor"}, "value": "0.2"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_truncate"}, "value": "true"}]}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part2_with_multiple_storage_params (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )    WITH (vacuum_index_cleanup = 'on', autovacuum_vacuum_scale_factor = '0.2', vacuum_truncate = 'true')  
+-- [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
+CREATE TEMP TABLE part2_on_commit_preserve_rows(
+    id int,
+    name varchar
+) ON COMMIT PRESERVE ROWS;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_on_commit_preserve_rows", "schemaname": "pg_temp"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "on_commit_value": "PRESERVE ROWS"}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "TEMPORARY", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE TEMPORARY TABLE  pg_temp.part2_on_commit_preserve_rows (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )     ON COMMIT PRESERVE ROWS 
+CREATE TEMP TABLE part2_on_commit_delete_rows(
+    id int,
+    name varchar
+) ON COMMIT DELETE ROWS;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_on_commit_delete_rows", "schemaname": "pg_temp"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "on_commit_value": "DELETE ROWS"}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "TEMPORARY", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE TEMPORARY TABLE  pg_temp.part2_on_commit_delete_rows (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )     ON COMMIT DELETE ROWS 
+CREATE TEMPORARY TABLE part2_on_commit_drop(
+    id int,
+    name varchar
+) ON COMMIT DROP;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_on_commit_drop", "schemaname": "pg_temp"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "on_commit_value": "DROP"}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "TEMPORARY", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE TEMPORARY TABLE  pg_temp.part2_on_commit_drop (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )     ON COMMIT DROP 
+-- [ TABLESPACE tablespace_name ]
+CREATE TABLE part2_tablespace_pg_default(
+    id int,
+    name varchar
+) TABLESPACE pg_default;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_tablespace_pg_default", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "tablespace": "pg_default"}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part2_tablespace_pg_default (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      TABLESPACE pg_default
+-- some complex combinations from the components above
+CREATE TEMPORARY TABLE part2_combination_1(
+    id int,
+    name varchar
+) PARTITION BY RANGE (id) ON COMMIT PRESERVE ROWS;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_combination_1", "schemaname": "pg_temp"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "on_commit_value": "PRESERVE ROWS"}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "TEMPORARY", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "RANGE (id)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE TEMPORARY TABLE  pg_temp.part2_combination_1 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )  PARTITION BY RANGE (id)   ON COMMIT PRESERVE ROWS 
+CREATE LOCAL TEMP TABLE part2_combination_2(
+    id int,
+    name varchar
+) USING heap WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true) ON COMMIT PRESERVE ROWS TABLESPACE pg_default;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_combination_2", "schemaname": "pg_temp"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "on_commit_value": "PRESERVE ROWS"}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "tablespace": "pg_default"}, "persistence": "TEMPORARY", "with_clause": {"fmt": "WITH (%{with:, }s)", "with": [{"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_index_cleanup"}, "value": "on"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "autovacuum_vacuum_scale_factor"}, "value": "0.2"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_truncate"}, "value": "true"}]}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "access_method": "heap"}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE TEMPORARY TABLE  pg_temp.part2_combination_2 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )   USING heap WITH (vacuum_index_cleanup = 'on', autovacuum_vacuum_scale_factor = '0.2', vacuum_truncate = 'true') ON COMMIT PRESERVE ROWS TABLESPACE pg_default
+CREATE TABLE part2_combination_3(
+    id int,
+    name varchar
+) USING heap WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true) TABLESPACE pg_default;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part2_combination_3", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "tablespace": "pg_default"}, "persistence": "", "with_clause": {"fmt": "WITH (%{with:, }s)", "with": [{"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_index_cleanup"}, "value": "on"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "autovacuum_vacuum_scale_factor"}, "value": "0.2"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_truncate"}, "value": "true"}]}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "access_method": "heap"}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part2_combination_3 (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )   USING heap WITH (vacuum_index_cleanup = 'on', autovacuum_vacuum_scale_factor = '0.2', vacuum_truncate = 'true')  TABLESPACE pg_default
+-- part 5: LIKE source_table [ like_option ... ]
+CREATE TABLE part5_source_table(
+    id int,
+    name varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_source_table", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_source_table (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_source_table2(
+    id2 int,
+    name2 varchar
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_source_table2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id2", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name2", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_source_table2 (id2 pg_catalog.int4 STORAGE plain     , name2 pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_like_simple(
+    LIKE part5_source_table
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_like_simple", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_like_simple (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+-- { INCLUDING | EXCLUDING } { COMMENTS | COMPRESSION | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }
+CREATE TABLE part5_including_all(
+    LIKE part5_source_table INCLUDING ALL
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_including_all", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_including_all (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_including_comments(
+    LIKE part5_source_table INCLUDING COMMENTS
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_including_comments", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_including_comments (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_including_compression(
+    LIKE part5_source_table INCLUDING COMPRESSION
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_including_compression", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_including_compression (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_including_defaults(
+    LIKE part5_source_table INCLUDING DEFAULTS
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_including_defaults", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_including_defaults (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_including_generated(
+    LIKE part5_source_table INCLUDING GENERATED
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_including_generated", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_including_generated (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_including_identity(
+    LIKE part5_source_table INCLUDING IDENTITY
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_including_identity", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_including_identity (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_including_indexes(
+    LIKE part5_source_table INCLUDING INDEXES
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_including_indexes", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_including_indexes (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_including_statistics(
+    LIKE part5_source_table INCLUDING STATISTICS
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_including_statistics", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_including_statistics (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_including_storage(
+    LIKE part5_source_table INCLUDING STORAGE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_including_storage", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_including_storage (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_excluding_all(
+    LIKE part5_source_table EXCLUDING ALL
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_excluding_all", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_excluding_all (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_excluding_comments(
+    LIKE part5_source_table EXCLUDING COMMENTS
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_excluding_comments", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_excluding_comments (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_excluding_compression(
+    LIKE part5_source_table EXCLUDING COMPRESSION
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_excluding_compression", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_excluding_compression (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_excluding_defaults(
+    LIKE part5_source_table EXCLUDING DEFAULTS
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_excluding_defaults", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_excluding_defaults (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_excluding_generated(
+    LIKE part5_source_table EXCLUDING GENERATED
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_excluding_generated", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_excluding_generated (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_excluding_identity(
+    LIKE part5_source_table EXCLUDING IDENTITY
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_excluding_identity", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_excluding_identity (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_excluding_indexes(
+    LIKE part5_source_table EXCLUDING INDEXES
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_excluding_indexes", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_excluding_indexes (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_excluding_statistics(
+    LIKE part5_source_table EXCLUDING STATISTICS
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_excluding_statistics", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_excluding_statistics (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_excluding_storage(
+    LIKE part5_source_table EXCLUDING STORAGE
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_excluding_storage", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_excluding_storage (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )      
+CREATE TABLE part5_like_list(
+    LIKE part5_source_table,
+    info text,
+    LIKE part5_source_table2 INCLUDING ALL,
+    CONSTRAINT primary_key_constraint PRIMARY KEY (id)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part5_like_list", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "info", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id2", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name2", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "primary_key_constraint", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part5_like_list (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , info pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , id2 pg_catalog.int4 STORAGE plain     , name2 pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT primary_key_constraint PRIMARY KEY (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- part 6: partition specification
+-- PARTITION OF parent_table { FOR VALUES partition_bound_spec | DEFAULT }
+CREATE TABLE part6_parent_table_range(
+    id int,
+    name varchar
+) PARTITION BY RANGE (id);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part6_parent_table_range", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "RANGE (id)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part6_parent_table_range (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )  PARTITION BY RANGE (id)    
+CREATE TABLE part6_parent_table_list(
+    id int,
+    name varchar
+) PARTITION BY LIST (id);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part6_parent_table_list", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "LIST (id)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part6_parent_table_list (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )  PARTITION BY LIST (id)    
+CREATE TABLE part6_parent_table_hash(
+    id int,
+    name varchar
+) PARTITION BY HASH (id);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part6_parent_table_hash", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "HASH (id)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part6_parent_table_hash (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   )  PARTITION BY HASH (id)    
+CREATE TABLE part6_partition_default PARTITION OF part6_parent_table_range DEFAULT;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D PARTITION OF %{parent_identity}D %{table_elements}s %{partition_bound}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part6_partition_default", "schemaname": "public"}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": {"fmt": "", "present": false}, "parent_identity": {"objname": "part6_parent_table_range", "schemaname": "public"}, "partition_bound": "DEFAULT"}
+NOTICE:  re-formed command: CREATE  TABLE  public.part6_partition_default PARTITION OF public.part6_parent_table_range  DEFAULT     
+-- FROM ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] )
+--  TO ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) |
+CREATE TABLE part6_partition_spec_range1 PARTITION OF part6_parent_table_range
+FOR VALUES FROM (MINVALUE) TO (2);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D PARTITION OF %{parent_identity}D %{table_elements}s %{partition_bound}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part6_partition_spec_range1", "schemaname": "public"}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": {"fmt": "", "present": false}, "parent_identity": {"objname": "part6_parent_table_range", "schemaname": "public"}, "partition_bound": "FOR VALUES FROM (MINVALUE) TO (2)"}
+NOTICE:  re-formed command: CREATE  TABLE  public.part6_partition_spec_range1 PARTITION OF public.part6_parent_table_range  FOR VALUES FROM (MINVALUE) TO (2)     
+CREATE TABLE part6_partition_spec_range2 PARTITION OF part6_parent_table_range
+FOR VALUES FROM (3) TO (MAXVALUE);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D PARTITION OF %{parent_identity}D %{table_elements}s %{partition_bound}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part6_partition_spec_range2", "schemaname": "public"}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": {"fmt": "", "present": false}, "parent_identity": {"objname": "part6_parent_table_range", "schemaname": "public"}, "partition_bound": "FOR VALUES FROM (3) TO (MAXVALUE)"}
+NOTICE:  re-formed command: CREATE  TABLE  public.part6_partition_spec_range2 PARTITION OF public.part6_parent_table_range  FOR VALUES FROM (3) TO (MAXVALUE)     
+-- IN ( partition_bound_expr [, ...] ) |
+CREATE TABLE part6_partition_spec_list PARTITION OF part6_parent_table_list
+FOR VALUES IN (1, (1+2), (4+5));
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D PARTITION OF %{parent_identity}D %{table_elements}s %{partition_bound}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part6_partition_spec_list", "schemaname": "public"}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": {"fmt": "", "present": false}, "parent_identity": {"objname": "part6_parent_table_list", "schemaname": "public"}, "partition_bound": "FOR VALUES IN (1, 3, 9)"}
+NOTICE:  re-formed command: CREATE  TABLE  public.part6_partition_spec_list PARTITION OF public.part6_parent_table_list  FOR VALUES IN (1, 3, 9)     
+-- WITH ( MODULUS numeric_literal, REMAINDER numeric_literal )
+CREATE TABLE part6_partition_spec_hash PARTITION OF part6_parent_table_hash
+FOR VALUES WITH (MODULUS 10, REMAINDER 2);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D PARTITION OF %{parent_identity}D %{table_elements}s %{partition_bound}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part6_partition_spec_hash", "schemaname": "public"}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": {"fmt": "", "present": false}, "parent_identity": {"objname": "part6_parent_table_hash", "schemaname": "public"}, "partition_bound": "FOR VALUES WITH (modulus 10, remainder 2)"}
+NOTICE:  re-formed command: CREATE  TABLE  public.part6_partition_spec_hash PARTITION OF public.part6_parent_table_hash  FOR VALUES WITH (modulus 10, remainder 2)     
+-- part7: create table
+-- all data types
+CREATE TABLE part7_source_table(
+    src_id int
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part7_source_table", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "src_id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part7_source_table (src_id pg_catalog.int4 STORAGE plain     )      
+CREATE TABLE part7_data_types(
+    var1 int8,
+    var2 serial8,
+    var3 bit,
+    var4 bit[5],
+    var5 varbit,
+    var6 varbit[5],
+    var7 bool,
+    var8 box,
+    var9 bytea,
+    var10 char,
+    var11 char[8],
+    var12 varchar,
+    var13 varchar[5],
+    var14 cidr,
+    var15 circle,
+    var16 date,
+    var17 double precision,
+    var18 inet,
+    var19 int,
+    var20 int4,
+    var21 interval,
+    var22 json,
+    var23 jsonb,
+    var24 line,
+    var25 lseg,
+    var26 macaddr,
+    var27 money,
+    var28 decimal,
+    var29 decimal(3,1),
+    var30 path,
+    var31 pg_lsn,
+    var32 pg_snapshot,
+    var33 point,
+    var34 polygon,
+    var35 float4,
+    var36 int2,
+    var37 serial2,
+    var38 serial4,
+    var39 text,
+    var40 time,
+    var41 time(3),
+    var42 timetz,
+    var43 timetz(3),
+    var44 timestamp,
+    var45 timestamp(3),
+    var46 timestamptz,
+    var47 timestamptz(3),
+    var48 tsquery,
+    var49 tsvector,
+    var50 txid_snapshot,
+    var51 uuid,
+    var52 xml
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s SEQUENCE %{if_not_exists}s %{identity}D %{definition: }s", "identity": {"objname": "part7_data_types_var2_seq", "schemaname": "public"}, "definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "9223372036854775807", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}, {"fmt": "AS %{seqtype}T", "seqtype": {"typmod": "", "typarray": false, "typename": "int8", "schemaname": "pg_catalog"}}], "persistence": "", "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE  SEQUENCE  public.part7_data_types_var2_seq CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START WITH 1 RESTART 1 AS pg_catalog.int8
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s SEQUENCE %{if_not_exists}s %{identity}D %{definition: }s", "identity": {"objname": "part7_data_types_var37_seq", "schemaname": "public"}, "definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "32767", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}, {"fmt": "AS %{seqtype}T", "seqtype": {"typmod": "", "typarray": false, "typename": "int2", "schemaname": "pg_catalog"}}], "persistence": "", "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE  SEQUENCE  public.part7_data_types_var37_seq CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 32767 START WITH 1 RESTART 1 AS pg_catalog.int2
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s SEQUENCE %{if_not_exists}s %{identity}D %{definition: }s", "identity": {"objname": "part7_data_types_var38_seq", "schemaname": "public"}, "definition": [{"fmt": "CACHE %{value}s", "value": "1", "clause": "cache"}, {"no": "NO", "fmt": "%{no}s CYCLE", "clause": "cycle"}, {"fmt": "INCREMENT BY %{value}s", "value": "1", "clause": "seqincrement"}, {"fmt": "MINVALUE %{value}s", "value": "1", "clause": "minvalue"}, {"fmt": "MAXVALUE %{value}s", "value": "2147483647", "clause": "maxvalue"}, {"fmt": "START WITH %{value}s", "value": "1", "clause": "start"}, {"fmt": "RESTART %{value}s", "value": "1", "clause": "restart"}, {"fmt": "AS %{seqtype}T", "seqtype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}}], "persistence": "", "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE  SEQUENCE  public.part7_data_types_var38_seq CACHE 1 NO CYCLE INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 RESTART 1 AS pg_catalog.int4
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part7_data_types", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var1", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int8", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var2", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int8", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT %{default}s", "default": "pg_catalog.nextval('public.part7_data_types_var2_seq'::pg_catalog.regclass)"}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var3", "type": "column", "coltype": {"typmod": "(1)", "typarray": false, "typename": "bit", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var4", "type": "column", "coltype": {"typmod": "(1)", "typarray": true, "typename": "bit", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var5", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varbit", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var6", "type": "column", "coltype": {"typmod": "", "typarray": true, "typename": "varbit", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var7", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "bool", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var8", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "box", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var9", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "bytea", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var10", "type": "column", "coltype": {"typmod": "(1)", "typarray": false, "typename": "bpchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var11", "type": "column", "coltype": {"typmod": "(1)", "typarray": true, "typename": "bpchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var12", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var13", "type": "column", "coltype": {"typmod": "", "typarray": true, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var14", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "cidr", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "main", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var15", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "circle", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var16", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "date", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var17", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float8", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var18", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "inet", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "main", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var19", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var20", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var21", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "INTERVAL", "schemaname": ""}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var22", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "json", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var23", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "jsonb", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var24", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "line", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var25", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "lseg", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var26", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "macaddr", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var27", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "money", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var28", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "numeric", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "main", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var29", "type": "column", "coltype": {"typmod": "(3,1)", "typarray": false, "typename": "numeric", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "main", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var30", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "path", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var31", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "pg_lsn", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var32", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "pg_snapshot", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var33", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "point", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var34", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "polygon", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var35", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var36", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int2", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var37", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int2", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT %{default}s", "default": "pg_catalog.nextval('public.part7_data_types_var37_seq'::pg_catalog.regclass)"}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var38", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT %{default}s", "default": "pg_catalog.nextval('public.part7_data_types_var38_seq'::pg_catalog.regclass)"}, "not_null": "NOT NULL", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var39", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var40", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "TIME", "schemaname": ""}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var41", "type": "column", "coltype": {"typmod": "(3) without time zone", "typarray": false, "typename": "TIME", "schemaname": ""}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var42", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "TIME WITH TIME ZONE", "schemaname": ""}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var43", "type": "column", "coltype": {"typmod": "(3) with time zone", "typarray": false, "typename": "TIME", "schemaname": ""}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var44", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "TIMESTAMP", "schemaname": ""}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var45", "type": "column", "coltype": {"typmod": "(3) without time zone", "typarray": false, "typename": "TIMESTAMP", "schemaname": ""}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var46", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "TIMESTAMP WITH TIME ZONE", "schemaname": ""}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var47", "type": "column", "coltype": {"typmod": "(3) with time zone", "typarray": false, "typename": "TIMESTAMP", "schemaname": ""}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var48", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "tsquery", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var49", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "tsvector", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var50", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "txid_snapshot", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var51", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "uuid", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "var52", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "xml", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part7_data_types (var1 pg_catalog.int8 STORAGE plain     , var2 pg_catalog.int8 STORAGE plain   NOT NULL DEFAULT pg_catalog.nextval('public.part7_data_types_var2_seq'::pg_catalog.regclass) , var3 pg_catalog."bit"(1) STORAGE extended     , var4 pg_catalog."bit"(1)[] STORAGE extended     , var5 pg_catalog.varbit STORAGE extended     , var6 pg_catalog.varbit[] STORAGE extended     , var7 pg_catalog.bool STORAGE plain     , var8 pg_catalog.box STORAGE plain     , var9 pg_catalog.bytea STORAGE extended     , var10 pg_catalog.bpchar(1) STORAGE extended  COLLATE pg_catalog."default"   , var11 pg_catalog.bpchar(1)[] STORAGE extended  COLLATE pg_catalog."default"   , var12 pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , var13 pg_catalog."varchar"[] STORAGE extended  COLLATE pg_catalog."default"   , var14 pg_catalog.cidr STORAGE main     , var15 pg_catalog.circle STORAGE plain     , var16 pg_catalog.date STORAGE plain     , var17 pg_catalog.float8 STORAGE plain     , var18 pg_catalog.inet STORAGE main     , var19 pg_catalog.int4 STORAGE plain     , var20 pg_catalog.int4 STORAGE plain     , var21 INTERVAL STORAGE plain     , var22 pg_catalog.json STORAGE extended     , var23 pg_catalog.jsonb STORAGE extended     , var24 pg_catalog.line STORAGE plain     , var25 pg_catalog.lseg STORAGE plain     , var26 pg_catalog.macaddr STORAGE plain     , var27 pg_catalog.money STORAGE plain     , var28 pg_catalog."numeric" STORAGE main     , var29 pg_catalog."numeric"(3,1) STORAGE main     , var30 pg_catalog.path STORAGE extended     , var31 pg_catalog.pg_lsn STORAGE plain     , var32 pg_catalog.pg_snapshot STORAGE extended     , var33 pg_catalog.point STORAGE plain     , var34 pg_catalog.polygon STORAGE extended     , var35 pg_catalog.float4 STORAGE plain     , var36 pg_catalog.int2 STORAGE plain     , var37 pg_catalog.int2 STORAGE plain   NOT NULL DEFAULT pg_catalog.nextval('public.part7_data_types_var37_seq'::pg_catalog.regclass) , var38 pg_catalog.int4 STORAGE plain   NOT NULL DEFAULT pg_catalog.nextval('public.part7_data_types_var38_seq'::pg_catalog.regclass) , var39 pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , var40 TIME STORAGE plain     , var41 TIME(3) without time zone STORAGE plain     , var42 TIME WITH TIME ZONE STORAGE plain     , var43 TIME(3) with time zone STORAGE plain     , var44 TIMESTAMP STORAGE plain     , var45 TIMESTAMP(3) without time zone STORAGE plain     , var46 TIMESTAMP WITH TIME ZONE STORAGE plain     , var47 TIMESTAMP(3) with time zone STORAGE plain     , var48 pg_catalog.tsquery STORAGE plain     , var49 pg_catalog.tsvector STORAGE extended     , var50 pg_catalog.txid_snapshot STORAGE extended     , var51 pg_catalog.uuid STORAGE plain     , var52 pg_catalog.xml STORAGE extended     )      
+NOTICE:  deparsed json: {"fmt": "ALTER SEQUENCE %{identity}D %{definition: }s", "identity": {"objname": "part7_data_types_var2_seq", "schemaname": "public"}, "definition": [{"fmt": "OWNED BY %{owner}D", "owner": {"objname": "part7_data_types", "attrname": "var2", "schemaname": "public"}, "clause": "owned"}]}
+NOTICE:  re-formed command: ALTER SEQUENCE public.part7_data_types_var2_seq OWNED BY public.part7_data_types.var2
+NOTICE:  deparsed json: {"fmt": "ALTER SEQUENCE %{identity}D %{definition: }s", "identity": {"objname": "part7_data_types_var37_seq", "schemaname": "public"}, "definition": [{"fmt": "OWNED BY %{owner}D", "owner": {"objname": "part7_data_types", "attrname": "var37", "schemaname": "public"}, "clause": "owned"}]}
+NOTICE:  re-formed command: ALTER SEQUENCE public.part7_data_types_var37_seq OWNED BY public.part7_data_types.var37
+NOTICE:  deparsed json: {"fmt": "ALTER SEQUENCE %{identity}D %{definition: }s", "identity": {"objname": "part7_data_types_var38_seq", "schemaname": "public"}, "definition": [{"fmt": "OWNED BY %{owner}D", "owner": {"objname": "part7_data_types", "attrname": "var38", "schemaname": "public"}, "clause": "owned"}]}
+NOTICE:  re-formed command: ALTER SEQUENCE public.part7_data_types_var38_seq OWNED BY public.part7_data_types.var38
+CREATE TABLE part7_compression_collate(
+    str1 varchar COMPRESSION "pglz",
+    str2 varchar COLLATE "fr_FR"
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part7_compression_collate", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "str1", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "compression_method": "pglz"}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "str2", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "fr_FR", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part7_compression_collate (str1 pg_catalog."varchar" STORAGE extended COMPRESSION pglz COLLATE pg_catalog."default"   , str2 pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."fr_FR"   )      
+CREATE TABLE part7_inherits_parent(
+    id int,
+    name varchar
+)
+INHERITS (part7_data_types, part7_compression_collate);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part7_inherits_parent", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": [{"objname": "part7_data_types", "schemaname": "public"}, {"objname": "part7_compression_collate", "schemaname": "public"}]}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part7_inherits_parent (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   ) INHERITS (public.part7_data_types, public.part7_compression_collate)     
+CREATE TABLE part7_combine_all_clauses(
+    id varchar(5) COMPRESSION "pglz" COLLATE "fr_FR" CONSTRAINT id_constraint DEFAULT 'foo',
+    PRIMARY KEY (id),
+    LIKE part7_source_table,
+    name varchar
+)
+INHERITS (part7_data_types, part7_compression_collate)
+USING heap 
+WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true)
+TABLESPACE pg_default;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part7_combine_all_clauses", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": [{"objname": "part7_data_types", "schemaname": "public"}, {"objname": "part7_compression_collate", "schemaname": "public"}]}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "tablespace": "pg_default"}, "persistence": "", "with_clause": {"fmt": "WITH (%{with:, }s)", "with": [{"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_index_cleanup"}, "value": "on"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "autovacuum_vacuum_scale_factor"}, "value": "0.2"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_truncate"}, "value": "true"}]}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "access_method": "heap"}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "(5)", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT %{default}s", "default": "'foo'::character varying"}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "fr_FR", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "compression_method": "pglz"}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "src_id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "part7_combine_all_clauses_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part7_combine_all_clauses (id pg_catalog."varchar"(5) STORAGE extended COMPRESSION pglz COLLATE pg_catalog."fr_FR"  DEFAULT 'foo'::character varying , src_id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT part7_combine_all_clauses_pkey PRIMARY KEY (id)) INHERITS (public.part7_data_types, public.part7_compression_collate)  USING heap WITH (vacuum_index_cleanup = 'on', autovacuum_vacuum_scale_factor = '0.2', vacuum_truncate = 'true')  TABLESPACE pg_default
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TEMP TABLE part7_combine_all_clauses_temp(
+    id varchar(5) COMPRESSION "pglz" COLLATE "fr_FR" CONSTRAINT id_constraint DEFAULT 'foo',
+    PRIMARY KEY (id),
+    LIKE part7_source_table,
+    name varchar
+)
+INHERITS (part7_data_types, part7_compression_collate)
+USING heap 
+WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true)
+ON COMMIT DELETE ROWS
+TABLESPACE pg_default;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part7_combine_all_clauses_temp", "schemaname": "pg_temp"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": [{"objname": "part7_data_types", "schemaname": "public"}, {"objname": "part7_compression_collate", "schemaname": "public"}]}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "on_commit_value": "DELETE ROWS"}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "tablespace": "pg_default"}, "persistence": "TEMPORARY", "with_clause": {"fmt": "WITH (%{with:, }s)", "with": [{"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_index_cleanup"}, "value": "on"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "autovacuum_vacuum_scale_factor"}, "value": "0.2"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_truncate"}, "value": "true"}]}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "access_method": "heap"}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "(5)", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT %{default}s", "default": "'foo'::character varying"}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "fr_FR", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "compression_method": "pglz"}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "src_id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "part7_combine_all_clauses_temp_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}
+NOTICE:  re-formed command: CREATE TEMPORARY TABLE  pg_temp.part7_combine_all_clauses_temp (id pg_catalog."varchar"(5) STORAGE extended COMPRESSION pglz COLLATE pg_catalog."fr_FR"  DEFAULT 'foo'::character varying , src_id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT part7_combine_all_clauses_temp_pkey PRIMARY KEY (id)) INHERITS (public.part7_data_types, public.part7_compression_collate)  USING heap WITH (vacuum_index_cleanup = 'on', autovacuum_vacuum_scale_factor = '0.2', vacuum_truncate = 'true') ON COMMIT DELETE ROWS TABLESPACE pg_default
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- part8: create typed table
+CREATE TYPE part8_people_type AS (
+    id int,
+    name varchar,
+    height float4,
+    weight float4
+);
+NOTICE:  deparsed json: {"fmt": "CREATE TYPE %{identity}D AS (%{columns:, }s)", "columns": [{"fmt": "%{name}I %{coltype}T %{compression}s %{collation}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "collation": {"fmt": "COLLATE", "present": false}, "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}}, {"fmt": "%{name}I %{coltype}T %{compression}s %{collation}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}}, {"fmt": "%{name}I %{coltype}T %{compression}s %{collation}s", "name": "height", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "collation": {"fmt": "COLLATE", "present": false}, "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}}, {"fmt": "%{name}I %{coltype}T %{compression}s %{collation}s", "name": "weight", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "collation": {"fmt": "COLLATE", "present": false}, "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}}], "identity": {"objname": "part8_people_type", "schemaname": "public"}}
+NOTICE:  re-formed command: CREATE TYPE public.part8_people_type AS (id pg_catalog.int4  , name pg_catalog."varchar"  COLLATE pg_catalog."default", height pg_catalog.float4  , weight pg_catalog.float4  )
+CREATE TABLE part8_create_typed_table OF part8_people_type;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D OF %{of_type}T %{table_elements}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "of_type": {"typmod": "", "typarray": false, "typename": "part8_people_type", "schemaname": "public"}, "identity": {"objname": "part8_create_typed_table", "schemaname": "public"}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": {"fmt": "", "present": false}}
+NOTICE:  re-formed command: CREATE  TABLE  public.part8_create_typed_table OF public.part8_people_type      
+CREATE TABLE part8_create_typed_table_simple OF part8_people_type(
+    weight,
+    PRIMARY KEY (id)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D OF %{of_type}T %{table_elements}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "of_type": {"typmod": "", "typarray": false, "typename": "part8_people_type", "schemaname": "public"}, "identity": {"objname": "part8_create_typed_table_simple", "schemaname": "public"}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": {"fmt": "(%{elements:, }s)", "elements": [{"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "part8_create_typed_table_simple_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}}
+NOTICE:  re-formed command: CREATE  TABLE  public.part8_create_typed_table_simple OF public.part8_people_type (CONSTRAINT part8_create_typed_table_simple_pkey PRIMARY KEY (id))     
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET NOT NULL", "type": "set not null", "column": "id"}], "identity": {"objname": "part8_create_typed_table_simple", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.part8_create_typed_table_simple ALTER COLUMN id SET NOT NULL
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE part8_create_typed_table_with_options_constaints OF part8_people_type(
+    weight WITH OPTIONS NOT NULL,
+    name UNIQUE,
+    PRIMARY KEY (id)
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D OF %{of_type}T %{table_elements}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "of_type": {"typmod": "", "typarray": false, "typename": "part8_people_type", "schemaname": "public"}, "identity": {"objname": "part8_create_typed_table_with_options_constaints", "schemaname": "public"}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": {"fmt": "(%{elements:, }s)", "elements": [{"fmt": "%{name}I WITH OPTIONS %{not_null}s %{default}s", "name": "weight", "type": "column", "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "part8_create_typed_table_with_options_constaints_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (name)"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "part8_create_typed_table_with_options_constaints_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}}
+NOTICE:  re-formed command: CREATE  TABLE  public.part8_create_typed_table_with_options_constaints OF public.part8_people_type (weight WITH OPTIONS NOT NULL , CONSTRAINT part8_create_typed_table_with_options_constaints_name_key UNIQUE (name), CONSTRAINT part8_create_typed_table_with_options_constaints_pkey PRIMARY KEY (id))     
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET NOT NULL", "type": "set not null", "column": "id"}], "identity": {"objname": "part8_create_typed_table_with_options_constaints", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.part8_create_typed_table_with_options_constaints ALTER COLUMN id SET NOT NULL
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE part8_create_typed_table_complex_combinations OF part8_people_type(
+    weight WITH OPTIONS NOT NULL,
+    name UNIQUE,
+    PRIMARY KEY (id)
+)
+USING heap 
+WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true)
+TABLESPACE pg_default;
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D OF %{of_type}T %{table_elements}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "of_type": {"typmod": "", "typarray": false, "typename": "part8_people_type", "schemaname": "public"}, "identity": {"objname": "part8_create_typed_table_complex_combinations", "schemaname": "public"}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "tablespace": "pg_default"}, "persistence": "", "with_clause": {"fmt": "WITH (%{with:, }s)", "with": [{"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_index_cleanup"}, "value": "on"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "autovacuum_vacuum_scale_factor"}, "value": "0.2"}, {"fmt": "%{label}s = %{value}L", "label": {"fmt": "%{label}I", "label": "vacuum_truncate"}, "value": "true"}]}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "access_method": "heap"}, "if_not_exists": "", "table_elements": {"fmt": "(%{elements:, }s)", "elements": [{"fmt": "%{name}I WITH OPTIONS %{not_null}s %{default}s", "name": "weight", "type": "column", "default": {"fmt": "DEFAULT", "present": false}, "not_null": "NOT NULL"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "part8_create_typed_table_complex_combinations_name_key", "type": "constraint", "contype": "unique", "definition": "UNIQUE (name)"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "part8_create_typed_table_complex_combinations_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}}
+NOTICE:  re-formed command: CREATE  TABLE  public.part8_create_typed_table_complex_combinations OF public.part8_people_type (weight WITH OPTIONS NOT NULL , CONSTRAINT part8_create_typed_table_complex_combinations_name_key UNIQUE (name), CONSTRAINT part8_create_typed_table_complex_combinations_pkey PRIMARY KEY (id))  USING heap WITH (vacuum_index_cleanup = 'on', autovacuum_vacuum_scale_factor = '0.2', vacuum_truncate = 'true')  TABLESPACE pg_default
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET NOT NULL", "type": "set not null", "column": "id"}], "identity": {"objname": "part8_create_typed_table_complex_combinations", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.part8_create_typed_table_complex_combinations ALTER COLUMN id SET NOT NULL
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- part9: create table as a partition of parent table, FOR VALUES clause is tested in part 6
+CREATE TABLE part9_parent_table_range(
+    id int,
+    name varchar,
+    height float4,
+    weight float4
+) PARTITION BY RANGE (height);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part9_parent_table_range", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "RANGE (height)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "height", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "weight", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part9_parent_table_range (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , height pg_catalog.float4 STORAGE plain     , weight pg_catalog.float4 STORAGE plain     )  PARTITION BY RANGE (height)    
+CREATE TABLE part9_parent_table_list(
+    id int,
+    name varchar,
+    height float4,
+    weight float4
+) PARTITION BY LIST (name);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part9_parent_table_list", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "LIST (name)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "height", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "weight", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part9_parent_table_list (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , height pg_catalog.float4 STORAGE plain     , weight pg_catalog.float4 STORAGE plain     )  PARTITION BY LIST (name)    
+CREATE TABLE part9_parent_table_hash(
+    id int,
+    name varchar,
+    height float4,
+    weight float4
+) PARTITION BY HASH (id);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "part9_parent_table_hash", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "definition": "HASH (id)"}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "varchar", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "height", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "weight", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "float4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.part9_parent_table_hash (id pg_catalog.int4 STORAGE plain     , name pg_catalog."varchar" STORAGE extended  COLLATE pg_catalog."default"   , height pg_catalog.float4 STORAGE plain     , weight pg_catalog.float4 STORAGE plain     )  PARTITION BY HASH (id)    
+-- TOFIX
+-- CREATE TABLE part9_partition_with_options_constraintscd 
+-- PARTITION OF part9_parent_table_range (
+--     id PRIMARY KEY,
+--     name WITH OPTIONS NOT NULL,
+--     weight,
+--     CHECK (height > 0)
+-- )
+-- FOR VALUES FROM (MINVALUE) TO (2);
+-- TOFIX
+-- CREATE TABLE part9_partition_with_options_constraints_default
+-- PARTITION OF part9_parent_table_range (
+--     id PRIMARY KEY,
+--     name WITH OPTIONS NOT NULL,
+--     CHECK (height > 0)
+-- ) DEFAULT;
+-- TOFIX
+-- CREATE TABLE part9_partition_complex_combinations
+-- PARTITION OF part9_parent_table_range (
+--     id PRIMARY KEY,
+--     name WITH OPTIONS NOT NULL,
+--     CHECK (height > 0)
+-- )
+-- FOR VALUES FROM (3) TO (10)
+-- USING heap 
+-- WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true)
+-- TABLESPACE pg_default;
+-- copied from old create_table.sql
+-- Test TableLikeClause is handled properly
+CREATE TABLE ctlt1 (a text CHECK (length(a) > 2) PRIMARY KEY, b text);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "ctlt1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "a", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "b", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "ctlt1_a_check", "type": "constraint", "contype": "check", "definition": "CHECK ((pg_catalog.length(a) OPERATOR(pg_catalog.>) 2))"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "ctlt1_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (a)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.ctlt1 (a pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , b pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT ctlt1_a_check CHECK ((pg_catalog.length(a) OPERATOR(pg_catalog.>) 2)), CONSTRAINT ctlt1_pkey PRIMARY KEY (a))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+ALTER TABLE ctlt1 ALTER COLUMN a SET STORAGE MAIN;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET STORAGE %{storage}s", "type": "set storage", "column": "a", "storage": "main"}], "identity": {"objname": "ctlt1", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.ctlt1 ALTER COLUMN a SET STORAGE main
+ALTER TABLE ctlt1 ALTER COLUMN b SET STORAGE EXTERNAL;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I SET STORAGE %{storage}s", "type": "set storage", "column": "b", "storage": "external"}], "identity": {"objname": "ctlt1", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.ctlt1 ALTER COLUMN b SET STORAGE external
+CREATE TABLE ctlt1_like (LIKE ctlt1 INCLUDING ALL);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "ctlt1_like", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "a", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "main", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "b", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "external", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "ctlt1_a_check", "type": "constraint", "contype": "check", "definition": "CHECK ((pg_catalog.length(a) OPERATOR(pg_catalog.>) 2))"}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "ctlt1_like_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (a)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.ctlt1_like (a pg_catalog.text STORAGE main  COLLATE pg_catalog."default"   , b pg_catalog.text STORAGE external  COLLATE pg_catalog."default"   , CONSTRAINT ctlt1_a_check CHECK ((pg_catalog.length(a) OPERATOR(pg_catalog.>) 2)), CONSTRAINT ctlt1_like_pkey PRIMARY KEY (a))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+-- Test foreign key constraint is handled in a following ALTER TABLE ADD CONSTRAINT FOREIGN KEY REFERENCES subcommand
+CREATE TABLE product (id int PRIMARY KEY, name text);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "product", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "name", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "text", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE %{name}D", "name": {"objname": "default", "schemaname": "pg_catalog"}}, "colstorage": "extended", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "product_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.product (id pg_catalog.int4 STORAGE plain     , name pg_catalog.text STORAGE extended  COLLATE pg_catalog."default"   , CONSTRAINT product_pkey PRIMARY KEY (id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+CREATE TABLE orders2 (order_id int PRIMARY KEY, product_id int
+REFERENCES product (id));
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "orders2", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "order_id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "product_id", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "CONSTRAINT %{name}I %{definition}s", "name": "orders2_pkey", "type": "constraint", "contype": "primary key", "definition": "PRIMARY KEY (order_id)"}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.orders2 (order_id pg_catalog.int4 STORAGE plain     , product_id pg_catalog.int4 STORAGE plain     , CONSTRAINT orders2_pkey PRIMARY KEY (order_id))      
+NOTICE:  deparsed json: <NULL>
+NOTICE:  re-formed command: <NULL>
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ADD CONSTRAINT %{name}I %{definition}s", "name": "orders2_product_id_fkey", "type": "add constraint", "definition": "FOREIGN KEY (product_id) REFERENCES public.product(id)"}], "identity": {"objname": "orders2", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.orders2 ADD CONSTRAINT orders2_product_id_fkey FOREIGN KEY (product_id) REFERENCES public.product(id)
+-- Test CREATE and ALTER inherited table
+CREATE TABLE gtest30 (
+a int,
+b int GENERATED ALWAYS AS (a * 2) STORED
+);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D (%{table_elements:, }s) %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "gtest30", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": null, "present": false}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": "", "table_elements": [{"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "a", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS", "present": false}}, {"fmt": "%{name}I %{coltype}T STORAGE %{colstorage}s %{compression}s %{collation}s %{not_null}s %{default}s %{generated_column}s", "name": "b", "type": "column", "coltype": {"typmod": "", "typarray": false, "typename": "int4", "schemaname": "pg_catalog"}, "default": {"fmt": "DEFAULT", "present": false}, "not_null": "", "collation": {"fmt": "COLLATE", "present": false}, "colstorage": "plain", "compression": {"fmt": "COMPRESSION %{compression_method}I", "present": false, "compression_method": null}, "generated_column": {"fmt": "GENERATED ALWAYS AS (%{generation_expr}s) STORED", "generation_expr": "(a OPERATOR(pg_catalog.*) 2)"}}]}
+NOTICE:  re-formed command: CREATE  TABLE  public.gtest30 (a pg_catalog.int4 STORAGE plain     , b pg_catalog.int4 STORAGE plain     GENERATED ALWAYS AS ((a OPERATOR(pg_catalog.*) 2)) STORED)      
+CREATE TABLE gtest30_1 () INHERITS (gtest30);
+NOTICE:  deparsed json: {"fmt": "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D () %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s %{on_commit}s %{tablespace}s", "identity": {"objname": "gtest30_1", "schemaname": "public"}, "inherits": {"fmt": "INHERITS (%{parents:, }D)", "parents": [{"objname": "gtest30", "schemaname": "public"}]}, "on_commit": {"fmt": "ON COMMIT %{on_commit_value}s", "present": false, "on_commit_value": null}, "tablespace": {"fmt": "TABLESPACE %{tablespace}I", "present": false, "tablespace": null}, "persistence": "", "with_clause": {"fmt": "WITH", "present": false}, "partition_by": {"fmt": "PARTITION BY %{definition}s", "present": false, "definition": null}, "access_method": {"fmt": "USING %{access_method}I", "present": false, "access_method": null}, "if_not_exists": ""}
+NOTICE:  re-formed command: CREATE  TABLE  public.gtest30_1 () INHERITS (public.gtest30)     
+ALTER TABLE gtest30 ALTER COLUMN b DROP EXPRESSION;
+NOTICE:  deparsed json: {"fmt": "ALTER %{objtype}s %{identity}D %{subcmds:, }s", "objtype": "TABLE", "subcmds": [{"fmt": "ALTER COLUMN %{column}I DROP EXPRESSION %{if_exists}s", "type": "drop expression", "column": "b", "if_exists": ""}], "identity": {"objname": "gtest30", "schemaname": "public"}}
+NOTICE:  re-formed command: ALTER TABLE public.gtest30 ALTER COLUMN b DROP EXPRESSION 
diff --git a/src/test/modules/test_ddl_deparse_regress/expected/test_ddl_deparse.out b/src/test/modules/test_ddl_deparse_regress/expected/test_ddl_deparse.out
new file mode 100644
index 0000000..ab041b5
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/expected/test_ddl_deparse.out
@@ -0,0 +1,20 @@
+CREATE ROLE ddl_testing_role SUPERUSER;
+SET ROLE ddl_testing_role;
+CREATE EXTENSION test_ddl_deparse_regress;
+CREATE OR REPLACE FUNCTION test_ddl_deparse()
+  RETURNS event_trigger LANGUAGE plpgsql AS
+$$
+DECLARE
+	r record;
+	deparsed_json text;
+BEGIN
+	FOR r IN SELECT * FROM pg_event_trigger_ddl_commands()
+	LOOP
+		deparsed_json = pg_catalog.ddl_deparse_to_json(r.command);
+		RAISE NOTICE 'deparsed json: %', deparsed_json;
+		RAISE NOTICE 're-formed command: %', pg_catalog.ddl_deparse_expand_command(deparsed_json);
+	END LOOP;
+END;
+$$;
+CREATE EVENT TRIGGER test_ddl_deparse
+ON ddl_command_end EXECUTE PROCEDURE test_ddl_deparse();
diff --git a/src/test/modules/test_ddl_deparse_regress/meson.build b/src/test/modules/test_ddl_deparse_regress/meson.build
new file mode 100644
index 0000000..b2f4e1c
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/meson.build
@@ -0,0 +1,45 @@
+# FIXME: prevent install during main install, but not during test :/
+
+test_ddl_deparse_regress_sources = files(
+  'test_ddl_deparse_regress.c',
+)
+
+if host_system == 'windows'
+  test_ddl_deparse_regress_sources += rc_lib_gen.process(win32ver_rc, extra_args: [
+    '--NAME', 'test_ddl_deparse_regress',
+    '--FILEDESC', 'test_ddl_deparse_regress - regression testing for DDL deparsing',])
+endif
+
+test_ddl_deparse_regress = shared_module('test_ddl_deparse_regress',
+  test_ddl_deparse_regress_sources,
+  kwargs: pg_mod_args,
+)
+testprep_targets += test_ddl_deparse_regress
+
+install_data(
+  'test_ddl_deparse_regress.control',
+  'test_ddl_deparse_regress--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+tests += {
+  'name': 'test_ddl_deparse_regress',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'regress': {
+    'sql': [
+      'test_ddl_deparse',
+      'create_extension',
+      'create_schema',
+      'aggregate',
+      'create_table',
+      'constraints',
+      'alter_table'
+    ],
+  },
+  'tap': {
+    'tests': [
+      't/001_compare_dumped_results.pl',
+    ],
+  },
+}
diff --git a/src/test/modules/test_ddl_deparse_regress/sql/aggregate.sql b/src/test/modules/test_ddl_deparse_regress/sql/aggregate.sql
new file mode 100644
index 0000000..561b4e1
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/sql/aggregate.sql
@@ -0,0 +1,7 @@
+CREATE AGGREGATE newavg(int4) (
+   sfunc = int4_avg_accum, stype = _int8,
+   finalfunc = int8_avg,
+   initcond1 = '{0,0}'
+);
+
+DROP AGGREGATE newavg(int4);
diff --git a/src/test/modules/test_ddl_deparse_regress/sql/alter_table.sql b/src/test/modules/test_ddl_deparse_regress/sql/alter_table.sql
new file mode 100644
index 0000000..2761a2e
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/sql/alter_table.sql
@@ -0,0 +1,524 @@
+-- parent table defintion
+CREATE TABLE orders(
+    id int,
+    name varchar,
+    description text,
+    price float4,
+    quantity int,
+    purchase_date date
+);
+
+-- ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
+--     action [, ... ]
+CREATE TABLE parent_table(
+    LIKE orders
+);
+CREATE TABLE test_only () INHERITS (parent_table);
+ALTER TABLE test_only ADD col1 int;
+ALTER TABLE IF EXISTS fake_table ADD col2 int;
+
+-- ALTER TABLE IF EXISTS ONLY parent_table ADD PRIMARY KEY (id);
+ALTER TABLE IF EXISTS parent_table * ADD CHECK (id > 10);
+
+-- ADD [ COLUMN ] [ IF NOT EXISTS ] column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
+CREATE TABLE test_add_column(
+    LIKE orders
+);
+ALTER TABLE test_add_column ADD col1 int;
+ALTER TABLE test_add_column ADD COLUMN col2 int;
+ALTER TABLE test_add_column ADD COLUMN IF NOT EXISTS col2 varchar;
+ALTER TABLE test_add_column ADD col3 varchar COLLATE "fr_FR";
+ALTER TABLE test_add_column ADD col4 int CHECK (col4 > 100) UNIQUE;
+ALTER TABLE test_add_column ADD COLUMN IF NOT EXISTS col5 text COLLATE "es_ES" DEFAULT 'foo' NOT NULL;
+
+-- DROP [ COLUMN ] [ IF EXISTS ] column_name [ RESTRICT | CASCADE ]
+CREATE TABLE test_drop_column(
+    LIKE orders,
+    UNIQUE (id),
+    UNIQUE (name)
+);
+CREATE TABLE foreign_table(
+    id int REFERENCES test_drop_column (id),
+    name varchar REFERENCES test_drop_column (name)
+);
+ALTER TABLE test_drop_column DROP price;
+ALTER TABLE test_drop_column DROP COLUMN quantity;
+
+ALTER TABLE test_drop_column DROP IF EXISTS description RESTRICT;
+-- TOFIX
+-- ALTER TABLE test_drop_column DROP IF EXISTS name CASCADE;
+
+-- ALTER [ COLUMN ] column_name [ SET DATA ] TYPE data_type [ COLLATE collation ] [ USING expression ]
+CREATE TABLE test_alter_type(
+    LIKE orders
+);
+ALTER TABLE test_alter_type ALTER price TYPE int;
+ALTER TABLE test_alter_type ALTER COLUMN purchase_date TYPE text COLLATE "fr_FR";
+ALTER TABLE test_alter_type ALTER COLUMN quantity SET DATA TYPE float4;
+ALTER TABLE test_alter_type ALTER name TYPE int USING id::integer;
+
+
+-- ALTER [ COLUMN ] column_name SET DEFAULT expression
+CREATE TABLE test_alter_set_default(
+    LIKE orders
+);
+ALTER TABLE test_alter_set_default ALTER price SET DEFAULT 100;
+ALTER TABLE test_alter_set_default ALTER COLUMN quantity SET DEFAULT 10;
+
+-- ALTER [ COLUMN ] column_name DROP DEFAULT
+CREATE TABLE test_drop_default(
+    LIKE orders,
+    default_price float4 DEFAULT 10.0,
+    default_name varchar DEFAULT 'foo'
+);
+ALTER TABLE test_drop_default ALTER default_price DROP DEFAULT;
+ALTER TABLE test_drop_default ALTER COLUMN default_name DROP DEFAULT;
+
+-- ALTER [ COLUMN ] column_name { SET | DROP } NOT NULL
+CREATE TABLE test_set_not_null(
+    LIKE orders,
+    size int NOT NULL
+);
+ALTER TABLE test_set_not_null ALTER COLUMN id SET NOT NULL;
+ALTER TABLE test_set_not_null ALTER size DROP NOT NULL;
+
+-- ALTER [ COLUMN ] column_name DROP EXPRESSION [ IF EXISTS ]
+CREATE TABLE test_drop_expression(
+    LIKE orders,
+    new_id int GENERATED ALWAYS AS ( 3 * ID ) STORED
+);
+ALTER TABLE test_drop_expression ALTER new_id DROP EXPRESSION;
+ALTER TABLE test_drop_expression ALTER id DROP EXPRESSION IF EXISTS;
+
+-- ALTER [ COLUMN ] column_name ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]
+CREATE TABLE test_add_generated(
+    LIKE orders,
+    col1 int NOT NULL,
+    col2 int NOT NULL,
+    col3 int NOT NULL
+);
+ALTER TABLE test_add_generated ALTER col1 ADD GENERATED ALWAYS AS IDENTITY;
+ALTER TABLE test_add_generated ALTER COLUMN col2 ADD GENERATED BY DEFAULT AS IDENTITY;
+ALTER TABLE test_add_generated ALTER col3 ADD GENERATED BY DEFAULT AS IDENTITY ( INCREMENT BY 10 );
+
+-- ALTER [ COLUMN ] column_name { SET GENERATED { ALWAYS | BY DEFAULT } | SET sequence_option | RESTART [ [ WITH ] restart ] } [...]
+CREATE TABLE test_set_generated(
+    id1 int GENERATED BY DEFAULT AS IDENTITY,
+    id2 int GENERATED ALWAYS AS IDENTITY,
+    id3 int GENERATED ALWAYS AS IDENTITY,
+    id4 int GENERATED ALWAYS AS IDENTITY,
+    id5 int GENERATED ALWAYS AS IDENTITY,
+    id6 int GENERATED ALWAYS AS IDENTITY,
+    id7 int GENERATED ALWAYS AS IDENTITY
+);
+ALTER TABLE test_set_generated ALTER id1 SET GENERATED ALWAYS;
+ALTER TABLE test_set_generated ALTER id2 SET GENERATED BY DEFAULT;
+ALTER TABLE test_set_generated ALTER id3 SET INCREMENT BY 10;
+ALTER TABLE test_set_generated ALTER id4 RESTART;
+ALTER TABLE test_set_generated ALTER id5 RESTART WITH 101;
+ALTER TABLE test_set_generated ALTER id6 RESTART WITH 201;
+ALTER TABLE test_set_generated ALTER COLUMN id7 SET GENERATED BY DEFAULT SET INCREMENT BY 100 RESTART WITH 301;
+
+-- ALTER [ COLUMN ] column_name DROP IDENTITY [ IF EXISTS ]
+CREATE TABLE test_drop_identity(
+    id int,
+    id_generated int GENERATED ALWAYS AS IDENTITY
+);
+ALTER TABLE test_drop_identity ALTER id_generated DROP IDENTITY;
+ALTER TABLE test_drop_identity ALTER id DROP IDENTITY IF EXISTS;
+
+-- ALTER [ COLUMN ] column_name SET STATISTICS integer
+CREATE TABLE test_set_statistics(
+    LIKE orders
+);
+ALTER TABLE test_set_statistics ALTER id SET STATISTICS 1;
+
+-- ALTER [ COLUMN ] column_name SET ( attribute_option = value [, ... ] )
+CREATE TABLE test_set_attribute(
+    LIKE orders
+);
+ALTER TABLE test_set_attribute ALTER name SET (n_distinct = 102);
+ALTER TABLE test_set_attribute ALTER id SET (n_distinct_inherited = 99, n_distinct = 9);
+
+-- ALTER [ COLUMN ] column_name RESET ( attribute_option [, ... ] )
+CREATE TABLE test_reset_attribute(
+    LIKE orders
+);
+ALTER TABLE test_reset_attribute ALTER name RESET (n_distinct);
+ALTER TABLE test_reset_attribute ALTER id RESET (n_distinct, n_distinct_inherited);
+
+-- ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }
+CREATE TABLE test_set_storage(
+    LIKE orders,
+    product_name text
+);
+ALTER TABLE test_set_storage ALTER id SET STORAGE PLAIN;
+ALTER TABLE test_set_storage ALTER name SET STORAGE EXTERNAL;
+ALTER TABLE test_set_storage ALTER description SET STORAGE EXTENDED;
+ALTER TABLE test_set_storage ALTER product_name SET STORAGE MAIN;
+
+-- ALTER [ COLUMN ] column_name SET COMPRESSION compression_method
+CREATE TABLE test_set_compression(
+    LIKE orders
+);
+ALTER TABLE test_set_compression ALTER name SET COMPRESSION "lz4";
+ALTER TABLE test_set_compression ALTER COLUMN description SET COMPRESSION "lz4";
+
+-- ADD table_constraint [ NOT VALID ]
+CREATE TABLE test_add_table_constraint(
+    LIKE orders
+);
+ALTER TABLE test_add_table_constraint ADD PRIMARY KEY (id);
+ALTER TABLE test_add_table_constraint ADD CONSTRAINT max_name_len CHECK (length(name) < 4) NOT VALID;
+ALTER TABLE test_add_table_constraint ADD CHECK (id < 10);
+
+-- ADD table_constraint_using_index
+CREATE TABLE test_add_constraint_using_index(
+    id1 int,
+    id2 int,
+    id3 int,
+    id4 int,
+    id5 int,
+    id6 int,
+    id7 int
+);
+CREATE UNIQUE INDEX test_add_constraint_used_index1 ON test_add_constraint_using_index (id1);
+ALTER TABLE test_add_constraint_using_index ADD UNIQUE USING INDEX test_add_constraint_used_index1;
+CREATE UNIQUE INDEX test_add_constraint_used_index2 ON test_add_constraint_using_index (id2);
+--TOFIX
+-- ALTER TABLE test_add_constraint_using_index ADD CONSTRAINT primary_constraint_using_index PRIMARY KEY USING INDEX test_add_constraint_used_index2;
+CREATE UNIQUE INDEX test_add_constraint_used_index3 ON test_add_constraint_using_index (id3);
+ALTER TABLE test_add_constraint_using_index ADD UNIQUE USING INDEX test_add_constraint_used_index3 DEFERRABLE;
+CREATE UNIQUE INDEX test_add_constraint_used_index4 ON test_add_constraint_using_index (id4);
+ALTER TABLE test_add_constraint_using_index ADD UNIQUE USING INDEX test_add_constraint_used_index4 NOT DEFERRABLE;
+CREATE UNIQUE INDEX test_add_constraint_used_index5 ON test_add_constraint_using_index (id5);
+ALTER TABLE test_add_constraint_using_index ADD UNIQUE USING INDEX test_add_constraint_used_index5 INITIALLY DEFERRED;
+CREATE UNIQUE INDEX test_add_constraint_used_index6 ON test_add_constraint_using_index (id6);
+ALTER TABLE test_add_constraint_using_index ADD UNIQUE USING INDEX test_add_constraint_used_index6 INITIALLY IMMEDIATE;
+CREATE UNIQUE INDEX test_add_constraint_used_index7 ON test_add_constraint_using_index (id7);
+ALTER TABLE test_add_constraint_using_index ADD UNIQUE USING INDEX test_add_constraint_used_index7 DEFERRABLE INITIALLY DEFERRED;
+
+-- ALTER CONSTRAINT constraint_name [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
+CREATE TABLE test_alter_constraint_referenced(
+    id1 int UNIQUE,
+    id2 int UNIQUE,
+    id3 int UNIQUE,
+    id4 int UNIQUE
+);
+CREATE TABLE test_alter_constraint(
+    id1 int,
+    id2 int,
+    id3 int,
+    id4 int,
+    id5 int,
+    CONSTRAINT alter_cstr1 FOREIGN KEY (id1) REFERENCES test_alter_constraint_referenced (id1) DEFERRABLE INITIALLY DEFERRED,
+    CONSTRAINT alter_cstr2 FOREIGN KEY (id2) REFERENCES test_alter_constraint_referenced (id2) NOT DEFERRABLE,
+    CONSTRAINT alter_cstr3 FOREIGN KEY (id3) REFERENCES test_alter_constraint_referenced (id3) DEFERRABLE INITIALLY DEFERRED,
+    CONSTRAINT alter_cstr4 FOREIGN KEY (id4) REFERENCES test_alter_constraint_referenced (id4) DEFERRABLE INITIALLY IMMEDIATE
+);
+ALTER TABLE test_alter_constraint ALTER CONSTRAINT alter_cstr1 NOT DEFERRABLE;
+ALTER TABLE test_alter_constraint ALTER CONSTRAINT alter_cstr2 DEFERRABLE;
+ALTER TABLE test_alter_constraint ALTER CONSTRAINT alter_cstr3 DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE test_alter_constraint ALTER CONSTRAINT alter_cstr4 DEFERRABLE INITIALLY DEFERRED;
+
+-- VALIDATE CONSTRAINT constraint_name
+CREATE TABLE test_validate_constraint(
+    LIKE orders
+);
+ALTER TABLE test_validate_constraint ADD CONSTRAINT test_validate_constraint_cstr CHECK (length(name) < 10) NOT VALID;
+ALTER TABLE test_validate_constraint VALIDATE CONSTRAINT test_validate_constraint_cstr;
+
+-- DROP CONSTRAINT [ IF EXISTS ]  constraint_name [ RESTRICT | CASCADE ]
+CREATE TABLE test_drop_constraint(
+    LIKE orders,
+    CONSTRAINT test_drop_constraint_check CHECK (id < 100),
+    CONSTRAINT test_drop_constraint_uniq UNIQUE (id)
+);
+CREATE TABLE test_drop_constraint_reference(
+    id int REFERENCES test_drop_constraint (id),
+    name varchar,
+    CONSTRAINT test_drop_constraint_reference_cstr1 CHECK (length(name) < 10)
+);
+ALTER TABLE test_drop_constraint_reference DROP CONSTRAINT test_drop_constraint_reference_cstr1;
+ALTER TABLE test_drop_constraint DROP CONSTRAINT test_drop_constraint_check RESTRICT;
+ALTER TABLE test_drop_constraint DROP CONSTRAINT IF EXISTS test_drop_constraint_check RESTRICT;
+-- TOFIX
+-- ALTER TABLE test_drop_constraint DROP CONSTRAINT test_drop_constraint_uniq CASCADE;
+
+-- TODO: This should be tested with TRIGGER related testing
+-- DISABLE TRIGGER [ trigger_name | ALL | USER ]
+-- ENABLE TRIGGER [ trigger_name | ALL | USER ]
+-- ENABLE REPLICA TRIGGER trigger_name
+-- ENABLE ALWAYS TRIGGER trigger_name
+
+-- DISABLE RULE rewrite_rule_name
+CREATE TABLE test_disable_rule(
+    LIKE orders
+);
+CREATE RULE sample_rule1 AS
+    ON UPDATE TO test_disable_rule
+    DO INSTEAD
+        SELECT * FROM test_disable_rule;
+ALTER TABLE test_disable_rule DISABLE RULE sample_rule1;
+
+-- ENABLE RULE rewrite_rule_name
+CREATE TABLE test_enable_rule(
+    LIKE orders
+);
+CREATE RULE sample_rule2 AS
+    ON UPDATE TO test_enable_rule
+    DO INSTEAD
+        SELECT * FROM test_enable_rule;
+ALTER TABLE test_enable_rule DISABLE RULE sample_rule2;
+ALTER TABLE test_enable_rule ENABLE RULE sample_rule2;
+
+-- ENABLE REPLICA RULE rewrite_rule_name
+CREATE TABLE test_enable_replica_rule(
+    LIKE orders
+);
+CREATE RULE sample_rule_enable_replica AS
+    ON UPDATE TO test_enable_replica_rule
+    DO INSTEAD
+        SELECT * FROM test_enable_replica_rule;
+ALTER TABLE test_enable_replica_rule ENABLE REPLICA RULE sample_rule_enable_replica;
+
+-- ENABLE ALWAYS RULE rewrite_rule_name
+CREATE TABLE test_enable_always_rule(
+    LIKE orders
+);
+CREATE RULE sample_rule_enable_always AS
+    ON UPDATE TO test_enable_always_rule
+    DO INSTEAD
+        SELECT * FROM test_enable_always_rule;
+ALTER TABLE test_enable_always_rule ENABLE REPLICA RULE sample_rule_enable_always;
+
+-- DISABLE ROW LEVEL SECURITY
+CREATE TABLE test_disable_row_security(
+    LIKE orders
+);
+ALTER TABLE test_disable_row_security DISABLE ROW LEVEL SECURITY;
+
+-- ENABLE ROW LEVEL SECURITY
+CREATE TABLE test_enable_row_security(
+    LIKE orders
+);
+ALTER TABLE test_enable_row_security ENABLE ROW LEVEL SECURITY;
+
+-- FORCE ROW LEVEL SECURITY
+CREATE TABLE test_force_row_security(
+    LIKE orders
+);
+ALTER TABLE test_force_row_security FORCE ROW LEVEL SECURITY;
+
+-- NO FORCE ROW LEVEL SECURITY
+CREATE TABLE test_no_force_row_security(
+    LIKE orders
+);
+ALTER TABLE test_no_force_row_security NO FORCE ROW LEVEL SECURITY;
+
+-- CLUSTER ON index_name
+CREATE TABLE test_cluster(
+    LIKE orders,
+    PRIMARY KEY (id)
+);
+ALTER TABLE test_cluster CLUSTER ON test_cluster_pkey;
+
+-- SET WITHOUT CLUSTER
+CREATE TABLE test_without_cluster(
+    LIKE orders,
+    PRIMARY KEY (id)
+);
+ALTER TABLE test_without_cluster CLUSTER ON test_without_cluster_pkey;
+ALTER TABLE test_without_cluster SET WITHOUT CLUSTER;
+
+-- SET WITHOUT OIDS
+CREATE TABLE test_set_without_oids(
+    LIKE orders
+);
+ALTER TABLE test_set_without_oids SET WITHOUT OIDS;
+
+-- SET ACCESS METHOD new_access_method
+CREATE TABLE test_set_access_method(
+    LIKE orders
+);
+ALTER TABLE test_set_access_method SET ACCESS METHOD heap;
+
+-- SET TABLESPACE new_tablespace
+CREATE TABLE test_set_tablespace(
+    LIKE orders
+);
+ALTER TABLE test_set_tablespace SET TABLESPACE pg_default;
+
+-- SET { LOGGED | UNLOGGED }
+CREATE TABLE test_set_logged(
+    LIKE orders
+);
+ALTER TABLE test_set_logged SET LOGGED;
+CREATE TABLE test_set_unlogged(
+    LIKE orders
+);
+ALTER TABLE test_set_unlogged SET UNLOGGED;
+
+-- SET ( storage_parameter [= value] [, ... ] )
+CREATE TABLE test_set_storage_params1(
+    LIKE orders
+);
+ALTER TABLE test_set_storage_params1 SET (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true);
+CREATE TABLE test_set_storage_params2(
+    LIKE orders
+);
+ALTER TABLE test_set_storage_params2 SET (vacuum_index_cleanup = ON);
+
+-- RESET ( storage_parameter [, ... ] )
+CREATE TABLE test_reset_storage_params1(
+    LIKE orders
+);
+ALTER TABLE test_set_storage_params1 SET (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true);
+ALTER TABLE test_reset_storage_params1 RESET (vacuum_index_cleanup, autovacuum_vacuum_scale_factor, vacuum_truncate);
+CREATE TABLE test_reset_storage_params2(
+    LIKE orders
+);
+ALTER TABLE test_set_storage_params2 SET (vacuum_index_cleanup = ON);
+ALTER TABLE test_reset_storage_params2 RESET (vacuum_index_cleanup);
+
+-- INHERIT parent_table
+CREATE TABLE test_inherit_parent(
+    parent_id int
+);
+CREATE TABLE test_inherit_child(
+    parent_id int,
+    LIKE orders
+);
+ALTER TABLE test_inherit_child INHERIT test_inherit_parent;
+
+-- NO INHERIT parent_table
+CREATE TABLE test_no_inherit_parent(
+    parent_id int
+);
+CREATE TABLE test_no_inherit_child(
+    LIKE orders
+) INHERITS (test_no_inherit_parent);
+ALTER TABLE test_no_inherit_child NO INHERIT test_no_inherit_parent;
+
+-- OF type_name
+CREATE TYPE test_type_product_type AS (
+    id int,
+    name varchar
+);
+CREATE TABLE test_type(
+    id int,
+    name varchar
+);
+ALTER TABLE test_type OF test_type_product_type;
+
+-- NOT OF
+CREATE TABLE test_type_not_of OF test_type_product_type;
+ALTER TABLE test_type_not_of NOT OF;
+
+-- TODO: This should be tested with ROLE/USER related testing
+-- OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
+
+-- REPLICA IDENTITY { DEFAULT | USING INDEX index_name | FULL | NOTHING }
+CREATE TABLE test_replica_identity1(
+    LIKE orders
+);
+ALTER TABLE test_replica_identity1 REPLICA IDENTITY DEFAULT;
+CREATE TABLE test_replica_identity2(
+    LIKE orders,
+    PRIMARY KEY (id)
+);
+ALTER TABLE test_replica_identity2 REPLICA IDENTITY USING INDEX test_replica_identity2_pkey;
+CREATE TABLE test_replica_identity3(
+    LIKE orders
+);
+ALTER TABLE test_replica_identity3 REPLICA IDENTITY FULL;
+CREATE TABLE test_replica_identity4(
+    LIKE orders
+);
+ALTER TABLE test_replica_identity4 REPLICA IDENTITY NOTHING;
+
+-- RENAME [ COLUMN ] column_name TO new_column_name
+CREATE TABLE test_alter_col_name(
+    LIKE orders
+);
+ALTER TABLE test_alter_col_name RENAME id TO new_id;
+ALTER TABLE test_alter_col_name RENAME COLUMN name TO new_name;
+
+-- RENAME CONSTRAINT constraint_name TO new_constraint_name
+CREATE TABLE test_alter_constraint_name(
+    LIKE orders,
+    CONSTRAINT test_alter_constraint_name_old CHECK (id > 10)
+);
+ALTER TABLE test_alter_constraint_name RENAME CONSTRAINT test_alter_constraint_name_old TO test_alter_constraint_name_new;
+
+-- RENAME TO new_name
+CREATE TABLE test_rename_table(
+    LIKE orders
+);
+ALTER TABLE test_rename_table RENAME to new_test_rename_table;
+
+-- SET SCHEMA new_schema
+CREATE TABLE test_set_schema(
+    LIKE orders
+);
+CREATE SCHEMA new_test_schema;
+ALTER TABLE test_set_schema SET SCHEMA new_test_schema;
+
+-- ALTER TABLE ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ]
+--     SET TABLESPACE new_tablespace [ NOWAIT ]
+-- TOFIX: can not be caught by ddl_command_end event trigger.
+-- Deparse of T_AlterTableMoveAllStmt is not supported,
+-- TABLESPACE commands (global object commands) are also not supported.
+-- ALTER TABLE ALL IN TABLESPACE pg_default SET TABLESPACE pg_default;
+-- ALTER TABLE ALL IN TABLESPACE pg_default OWNED BY ddl_testing_role SET TABLESPACE pg_default;
+
+-- ATTACH PARTITION partition_name { FOR VALUES partition_bound_spec | DEFAULT }
+CREATE TABLE test_partition_attach_range(
+    LIKE orders
+) PARTITION BY RANGE (id);
+CREATE TABLE test_partition_attach_range_p_1(
+    LIKE test_partition_attach_range
+);
+-- TOFIX
+-- ALTER TABLE test_partition_attach_range ATTACH PARTITION test_partition_attach_range_p_1 DEFAULT;
+
+CREATE TABLE test_partition_attach_range_p_2(
+    LIKE test_partition_attach_range
+);
+-- TOFIX
+-- ALTER TABLE test_partition_attach_range ATTACH PARTITION test_partition_attach_range_p_2 FOR VALUES FROM (100) TO (200);
+CREATE TABLE test_partition_attach_hash(
+    LIKE orders
+) PARTITION BY HASH (id);
+CREATE TABLE test_partition_attach_hash_p(
+    LIKE test_partition_attach_hash
+);
+-- TOFIX
+-- ALTER TABLE test_partition_attach_hash ATTACH PARTITION test_partition_attach_hash_p FOR VALUES WITH (MODULUS 10, REMAINDER 1);
+CREATE TABLE test_partition_attach_list(
+    LIKE orders
+) PARTITION BY LIST (name);
+CREATE TABLE test_partition_attach_list_p1(
+    LIKE test_partition_attach_list
+);
+CREATE TABLE test_partition_attach_list_p2(
+    LIKE test_partition_attach_list
+);
+-- TOFIX
+-- ALTER TABLE test_partition_attach_list ATTACH PARTITION test_partition_attach_list_p1 FOR VALUES IN ('key1');
+-- ALTER TABLE test_partition_attach_list ATTACH PARTITION test_partition_attach_list_p2 FOR VALUES IN ('key2', 'key3');
+
+-- DETACH PARTITION partition_name [ CONCURRENTLY | FINALIZE ]
+CREATE TABLE test_detach_partition(
+    LIKE orders
+) PARTITION BY RANGE (id);
+CREATE TABLE test_detach_partition_p1 PARTITION OF test_detach_partition FOR VALUES FROM (1) TO (100);
+CREATE TABLE test_detach_partition_p2 PARTITION OF test_detach_partition FOR VALUES FROM (101) TO (200);
+CREATE TABLE test_detach_partition_p3 PARTITION OF test_detach_partition FOR VALUES FROM (201) TO (300);
+-- TOFIX
+-- ALTER TABLE test_detach_partition DETACH PARTITION test_detach_partition_p1;
+-- ALTER TABLE test_detach_partition DETACH PARTITION test_detach_partition_p2 CONCURRENTLY;
+-- TOFIX: FINALIZE option is not testable
+-- ALTER TABLE test_detach_partition DETACH PARTITION test_detach_partition_p3 FINALIZE;
+
+
diff --git a/src/test/modules/test_ddl_deparse_regress/sql/constraints.sql b/src/test/modules/test_ddl_deparse_regress/sql/constraints.sql
new file mode 100644
index 0000000..e2d43fa
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/sql/constraints.sql
@@ -0,0 +1,385 @@
+-- column constraint, index_parameters
+
+-- [ CONSTRAINT constraint_name ]
+-- { NOT NULL |
+CREATE TABLE col_cstr_not_null(
+    id int CONSTRAINT id_constraint NOT NULL,
+    name varchar
+);
+
+--  NULL |
+CREATE TABLE col_cstr_null(
+    id int NULL,
+    name varchar CONSTRAINT name_constraint NOT NULL
+);
+
+--  CHECK ( expression ) [ NO INHERIT ] |
+CREATE TABLE col_cstr_check(
+    id int CHECK (id > 10),
+    name varchar NOT NULL
+);
+CREATE TABLE col_cstr_check_no_inherit(
+    id int CHECK (id > 10) NO INHERIT,
+    name varchar NOT NULL
+);
+
+--  DEFAULT default_expr |
+CREATE TABLE col_cstr_default(
+    id int NOT NULL,
+    name varchar DEFAULT 'foo'
+);
+
+--  GENERATED ALWAYS AS ( generation_expr ) STORED |
+CREATE TABLE col_cstr_generated_always_as(
+    id int NOT NULL,
+    id_generated int GENERATED ALWAYS AS ( id * 10 ) STORED
+);
+
+--  GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] |
+CREATE TABLE col_cstr_generated_always_as_identity(
+    id int NOT NULL,
+    id_generated int GENERATED ALWAYS AS IDENTITY
+);
+CREATE TABLE col_cstr_generated_by_default_as_identity_with_options(
+    id int NOT NULL,
+    id_generated int GENERATED BY DEFAULT AS IDENTITY ( INCREMENT BY 10 )
+);
+
+--  UNIQUE [ NULLS [ NOT ] DISTINCT ] |
+CREATE TABLE col_cstr_unique(
+    id int NOT NULL,
+    name varchar UNIQUE
+);
+CREATE TABLE col_cstr_unique_nulls_distinct(
+    id int NOT NULL,
+    name varchar UNIQUE NULLS DISTINCT
+);
+CREATE TABLE col_cstr_unique_nulls_not_distinct(
+    id int NOT NULL,
+    name varchar UNIQUE NULLS NOT DISTINCT
+);
+
+--  PRIMARY KEY |
+CREATE TABLE col_cstr_primary_key(
+    id int PRIMARY KEY,
+    name varchar UNIQUE
+);
+
+--  REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]
+--    [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
+CREATE TABLE col_cstr_reference_table_default(
+    id int REFERENCES col_cstr_primary_key,
+    name varchar
+);
+CREATE TABLE col_cstr_reference_table_column(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name)
+);
+-- [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]
+-- skip testing MATCH PARTIAL, which is treated as a syntax error with message
+-- ERROR:  MATCH PARTIAL not yet implemented
+CREATE TABLE col_cstr_reference_table_column_match_full(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) MATCH FULL
+);
+CREATE TABLE col_cstr_reference_table_column_match_simple(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) MATCH SIMPLE
+);
+
+-- [ ON DELETE referential_action ]
+CREATE TABLE col_cstr_reference_table_column_on_delete_no_action(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE NO ACTION
+);
+CREATE TABLE col_cstr_reference_table_column_on_delete_restrict(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE RESTRICT
+);
+CREATE TABLE col_cstr_reference_table_column_on_delete_cascade(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE CASCADE
+);
+CREATE TABLE col_cstr_reference_table_column_on_delete_set_null(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE SET NULL
+);
+CREATE TABLE col_cstr_reference_table_column_on_delete_set_null_with_column(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE SET NULL (name),
+    foo varchar REFERENCES col_cstr_primary_key (name) ON DELETE SET NULL (foo)
+);
+CREATE TABLE col_cstr_reference_table_column_on_delete_set_default(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE SET DEFAULT
+);
+CREATE TABLE col_cstr_reference_table_column_on_delete_set_default_with_col(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON DELETE SET DEFAULT (name)
+);
+
+-- [ ON UPDATE referential_action ]
+CREATE TABLE col_cstr_reference_table_column_on_update_no_action(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON UPDATE NO ACTION
+);
+CREATE TABLE col_cstr_reference_table_column_on_update_restrict(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON UPDATE RESTRICT
+);
+CREATE TABLE col_cstr_reference_table_column_on_update_cascade(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON UPDATE CASCADE
+);
+CREATE TABLE col_cstr_reference_table_column_on_update_set_null(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON UPDATE SET NULL
+);
+CREATE TABLE col_cstr_reference_table_column_on_update_set_default(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) ON UPDATE SET DEFAULT
+);
+-- complex combinations
+CREATE TABLE col_cstr_reference_table_column_complex_combination1(
+    id int,
+    name varchar REFERENCES col_cstr_primary_key (name) MATCH FULL ON DELETE NO ACTION ON UPDATE NO ACTION
+);
+CREATE TABLE col_cstr_reference_table_column_complex_combination2(
+    id int REFERENCES col_cstr_primary_key MATCH FULL ON DELETE SET DEFAULT ON UPDATE SET NULL,
+    name varchar
+);
+
+-- [ DEFERRABLE | NOT DEFERRABLE ]
+CREATE TABLE col_cstr_deferable(
+    id int,
+    name varchar UNIQUE DEFERRABLE
+);
+CREATE TABLE col_cstr_not_deferable(
+    id int PRIMARY KEY NOT DEFERRABLE,
+    name varchar
+);
+
+-- [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
+CREATE TABLE col_cstr_initially_deferred(
+    id int PRIMARY KEY INITIALLY DEFERRED,
+    name varchar
+);
+CREATE TABLE col_cstr_initially_immediate(
+    id int,
+    name varchar UNIQUE INITIALLY IMMEDIATE
+);
+
+-- complex combination
+CREATE TABLE col_cstr_complex_combination(
+    id int,
+    name varchar CONSTRAINT name_constraint REFERENCES col_cstr_primary_key (name) MATCH FULL ON DELETE SET DEFAULT ON UPDATE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE
+);
+
+-- part 4: table constraints
+-- [ CONSTRAINT constraint_name ]
+-- { CHECK ( expression ) [ NO INHERIT ] |
+CREATE TABLE tbl_cstr_check_1(
+    CONSTRAINT id_constraint CHECK (id > 10),
+    id int,
+    name varchar
+);
+CREATE TABLE tbl_cstr_check_2(
+    id int,
+    name varchar,
+    CONSTRAINT table_check CHECK (id > 10) NO INHERIT
+);
+CREATE TABLE tbl_cstr_check_no_inherit(
+    id int,
+    name varchar,
+    CHECK (id > 10) NO INHERIT
+);
+
+--   UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] ) [ INCLUDE ( column_name [, ...]) ] |
+CREATE TABLE tbl_cstr_unique(
+    id int,
+    name varchar,
+    UNIQUE (id)
+);
+CREATE TABLE tbl_cstr_unique_multicols(
+    id int,
+    name varchar,
+    UNIQUE (id, name)
+);
+CREATE TABLE tbl_cstr_unique_nulls_distinct(
+    id int,
+    name varchar,
+    UNIQUE NULLS DISTINCT (id)
+);
+CREATE TABLE tbl_cstr_unique_nulls_not_distinct(
+    id int,
+    name varchar,
+    UNIQUE NULLS NOT DISTINCT (id, name)
+);
+CREATE TABLE tbl_cstr_unique_nulls_distinct_include(
+    id int,
+    name varchar,
+    UNIQUE NULLS DISTINCT (id) INCLUDE (name)
+);
+CREATE TABLE tbl_cstr_unique_nulls_distinct_include_multi(
+    id int,
+    name varchar,
+    info varchar,
+    UNIQUE NULLS DISTINCT (id) INCLUDE (name, info)
+);
+
+-- PRIMARY KEY ( column_name [, ... ] ) [ INCLUDE ( column_name [, ...]) ] |
+CREATE TABLE tbl_cstr_primary_key(
+    id int,
+    name varchar,
+    PRIMARY KEY (id)
+);
+CREATE TABLE tbl_cstr_primary_key_multicols(
+    id int,
+    name varchar,
+    PRIMARY KEY (id, name)
+);
+CREATE TABLE tbl_cstr_primary_key_include(
+    id int,
+    name varchar,
+    PRIMARY KEY (id) INCLUDE (name)
+);
+CREATE TABLE tbl_cstr_primary_key_include_multicols(
+    id int,
+    name varchar,
+    info varchar,
+    PRIMARY KEY (id) INCLUDE (name, info)
+);
+
+--   EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] |
+CREATE TABLE tbl_cstr_exclude(
+    id int,
+    name varchar,
+    EXCLUDE (name WITH =)
+);
+CREATE TABLE tbl_cstr_exclude_multi(
+    id int,
+    name varchar,
+    EXCLUDE ((id*10) with =, name WITH =)
+);
+CREATE TABLE tbl_cstr_exclude_index_method(
+    id int,
+    name varchar,
+    EXCLUDE USING btree ((id*10) with =, name WITH =)
+);
+-- [ INCLUDE ( column_name [, ... ] ) ]
+CREATE TABLE tbl_cstr_exclude_with_index_params_include_1(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) INCLUDE (name)
+);
+CREATE TABLE tbl_cstr_exclude_with_index_params_include_2(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) INCLUDE (id, name)
+);
+-- [ WITH ( storage_parameter [= value] [, ... ] ) ]
+CREATE TABLE tbl_cstr_exclude_with_index_params_storage_1(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) WITH (fillfactor = 20)
+);
+CREATE TABLE tbl_cstr_exclude_with_index_params_storage_2(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) WITH (fillfactor = 20, deduplicate_items = false)
+);
+-- [ USING INDEX TABLESPACE tablespace_name ]
+CREATE TABLE tbl_cstr_exclude_with_index_params_tablespace(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) USING INDEX TABLESPACE pg_default
+);
+-- index_parameters complex combination
+CREATE TABLE tbl_cstr_exclude_with_index_params_complex(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) INCLUDE (id, name) WITH (fillfactor = 20, deduplicate_items = false) USING INDEX TABLESPACE pg_default
+);
+-- [ WHERE ( predicate ) ]
+CREATE TABLE tbl_cstr_exclude_with_predicate(
+    id int,
+    name varchar,
+    EXCLUDE (id WITH =) WHERE (name<>'foo')
+);
+-- complex combination for table constraint clauses
+CREATE TABLE tbl_cstr_exclude_complex_combination(
+    id int,
+    name varchar,
+    EXCLUDE USING btree (id WITH =, name WITH =) INCLUDE (id, name) WITH (fillfactor = 20, deduplicate_items = false) USING INDEX TABLESPACE pg_default WHERE (name<>'foo')
+);
+
+-- FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ]
+--     [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
+CREATE TABLE tbl_cstr_foreign_table(
+    id int PRIMARY KEY,
+    name varchar UNIQUE,
+    UNIQUE (id, name)
+);
+CREATE TABLE tbl_cstr_foreign_key_simple_1(
+    id int,
+    name varchar,
+    FOREIGN KEY (id) REFERENCES tbl_cstr_foreign_table
+);
+CREATE TABLE tbl_cstr_foreign_key_simple_2(
+    id int,
+    name varchar,
+    FOREIGN KEY (id) REFERENCES tbl_cstr_foreign_table(id)
+);
+CREATE TABLE tbl_cstr_foreign_key_multiple_keys(
+    id int,
+    name varchar,
+    FOREIGN KEY (id, name) REFERENCES tbl_cstr_foreign_table (id, name)
+);
+
+-- some combinations from REFERENCES clause, which is already tested in part 3
+CREATE TABLE tbl_cstr_reference_table_complex_combination1(
+    id int,
+    name varchar,
+    FOREIGN KEY (name) REFERENCES tbl_cstr_foreign_table (name) MATCH SIMPLE ON DELETE CASCADE ON UPDATE SET NULL
+);
+CREATE TABLE tbl_cstr_reference_table_complex_combination2(
+    id int,
+    name varchar,
+    CONSTRAINT tbl_cstr FOREIGN KEY (id, name) REFERENCES tbl_cstr_foreign_table (id, name) ON DELETE SET NULL (id, name) ON UPDATE SET DEFAULT
+);
+
+-- [ DEFERRABLE | NOT DEFERRABLE ]
+CREATE TABLE tbl_cstr_reference_table_column_deferable(
+    id int,
+    name varchar,
+    UNIQUE (id, name) DEFERRABLE
+);
+CREATE TABLE tbl_cstr_reference_table_column_not_deferable(
+    id int,
+    name varchar,
+    PRIMARY KEY (id) NOT DEFERRABLE
+);
+
+-- [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
+CREATE TABLE tbl_cstr_reference_table_column_initially_deferred(
+    id int,
+    name varchar,
+    UNIQUE (id, name) INITIALLY DEFERRED
+);
+CREATE TABLE tbl_cstr_reference_table_column_initially_immediate(
+    id int,
+    name varchar,
+    PRIMARY KEY (id) INITIALLY IMMEDIATE
+);
+
+-- complex combinations
+CREATE TABLE tbl_cstr_reference_table_column_complex_combination1(
+    id int,
+    name varchar,
+    CONSTRAINT tbl_cstr FOREIGN KEY (name) REFERENCES tbl_cstr_foreign_table (name) MATCH FULL ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED
+);
+CREATE TABLE tbl_cstr_reference_table_column_complex_combination2(
+    id int,
+    name varchar,
+    CONSTRAINT tbl_cstr PRIMARY KEY (id, name) NOT DEFERRABLE INITIALLY IMMEDIATE
+);
diff --git a/src/test/modules/test_ddl_deparse_regress/sql/create_extension.sql b/src/test/modules/test_ddl_deparse_regress/sql/create_extension.sql
new file mode 100644
index 0000000..d23e7fd
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/sql/create_extension.sql
@@ -0,0 +1,5 @@
+---
+--- CREATE_EXTENSION
+---
+
+CREATE EXTENSION pg_stat_statements;
diff --git a/src/test/modules/test_ddl_deparse_regress/sql/create_schema.sql b/src/test/modules/test_ddl_deparse_regress/sql/create_schema.sql
new file mode 100644
index 0000000..10b13f0
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/sql/create_schema.sql
@@ -0,0 +1,16 @@
+--
+-- CREATE_SCHEMA
+--
+
+CREATE SCHEMA foo;
+
+CREATE SCHEMA IF NOT EXISTS bar;
+
+CREATE SCHEMA baz;
+
+-- Will not be created, and will not be handled by the
+-- event trigger
+CREATE SCHEMA IF NOT EXISTS baz;
+
+CREATE SCHEMA element_test
+  CREATE TABLE foo (id int)
diff --git a/src/test/modules/test_ddl_deparse_regress/sql/create_table.sql b/src/test/modules/test_ddl_deparse_regress/sql/create_table.sql
new file mode 100644
index 0000000..a51776d
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/sql/create_table.sql
@@ -0,0 +1,417 @@
+-- part 1: shared prefixes
+-- [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ]
+CREATE TABLE part1_simple_table(
+    id int,
+    name varchar
+);
+CREATE TEMPORARY TABLE part1_temp_table0(
+    id int,
+    name varchar
+);
+CREATE TEMP TABLE part1_temp_table(
+    id int,
+    name varchar
+);
+-- GLOBAL TEMP TATBLE is deprecated, expect warning message and create local temp table
+CREATE GLOBAL TEMP TABLE part1_global_temp_table(
+    id int,
+    name varchar
+);
+CREATE LOCAL TEMP TABLE part1_local_temp_table(
+    id int,
+    name varchar
+);
+CREATE UNLOGGED TABLE part1_unlogged_table(
+    id int,
+    name varchar
+);
+-- [ IF NOT EXISTS ]
+CREATE TABLE IF NOT EXISTS part1_simple_table(
+    id int,
+    name varchar
+);
+CREATE TABLE IF NOT EXISTS part1_local_temp_table_not_exists(
+    id int,
+    name varchar
+);
+
+-- part 2: shared suffixes
+-- [ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ]
+CREATE TABLE part2_partition_by_range_simple(
+    id int,
+    name varchar
+) PARTITION BY RANGE (id);
+CREATE TABLE part2_partition_by_list_simple(
+    id int,
+    name varchar
+) PARTITION BY LIST (id);
+CREATE TABLE part2_partition_by_hash_simple(
+    id int,
+    name varchar
+) PARTITION BY HASH (id);
+CREATE TABLE part2_partition_with_expression(
+    id int,
+    name varchar
+) PARTITION BY RANGE ((id * 190), name);
+CREATE TABLE part2_partition_with_collation(
+    id int,
+    name varchar
+) PARTITION BY LIST (name COLLATE "fr_FR");
+CREATE TABLE part2_partition_with_opclass(
+    id int,
+    name varchar
+) PARTITION BY HASH (id int4_ops, name varchar_ops);
+CREATE TABLE part2_partition_with_collation_opclass(
+    id int,
+    name varchar
+) PARTITION BY RANGE ((id * 10) int4_ops, name COLLATE "fr_FR" varchar_ops);
+
+-- [ USING method ]
+-- default method
+CREATE TABLE part2_using_default_access_method(
+    id int,
+    name varchar
+) USING heap;
+
+-- [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ]
+CREATE TABLE part2_without_oids(
+    id int,
+    name varchar
+) WITHOUT OIDS;
+CREATE TABLE part2_with_one_storage_param(
+    id int,
+    name varchar
+) WITH (fillfactor = 20);
+CREATE TABLE part2_with_multiple_storage_params(
+    id int,
+    name varchar
+) WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true);
+
+-- [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
+CREATE TEMP TABLE part2_on_commit_preserve_rows(
+    id int,
+    name varchar
+) ON COMMIT PRESERVE ROWS;
+CREATE TEMP TABLE part2_on_commit_delete_rows(
+    id int,
+    name varchar
+) ON COMMIT DELETE ROWS;
+CREATE TEMPORARY TABLE part2_on_commit_drop(
+    id int,
+    name varchar
+) ON COMMIT DROP;
+
+-- [ TABLESPACE tablespace_name ]
+CREATE TABLE part2_tablespace_pg_default(
+    id int,
+    name varchar
+) TABLESPACE pg_default;
+
+-- some complex combinations from the components above
+CREATE TEMPORARY TABLE part2_combination_1(
+    id int,
+    name varchar
+) PARTITION BY RANGE (id) ON COMMIT PRESERVE ROWS;
+
+CREATE LOCAL TEMP TABLE part2_combination_2(
+    id int,
+    name varchar
+) USING heap WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true) ON COMMIT PRESERVE ROWS TABLESPACE pg_default;
+
+CREATE TABLE part2_combination_3(
+    id int,
+    name varchar
+) USING heap WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true) TABLESPACE pg_default;
+
+
+-- part 5: LIKE source_table [ like_option ... ]
+CREATE TABLE part5_source_table(
+    id int,
+    name varchar
+);
+CREATE TABLE part5_source_table2(
+    id2 int,
+    name2 varchar
+);
+CREATE TABLE part5_like_simple(
+    LIKE part5_source_table
+);
+-- { INCLUDING | EXCLUDING } { COMMENTS | COMPRESSION | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }
+CREATE TABLE part5_including_all(
+    LIKE part5_source_table INCLUDING ALL
+);
+CREATE TABLE part5_including_comments(
+    LIKE part5_source_table INCLUDING COMMENTS
+);
+CREATE TABLE part5_including_compression(
+    LIKE part5_source_table INCLUDING COMPRESSION
+);
+CREATE TABLE part5_including_defaults(
+    LIKE part5_source_table INCLUDING DEFAULTS
+);
+CREATE TABLE part5_including_generated(
+    LIKE part5_source_table INCLUDING GENERATED
+);
+CREATE TABLE part5_including_identity(
+    LIKE part5_source_table INCLUDING IDENTITY
+);
+CREATE TABLE part5_including_indexes(
+    LIKE part5_source_table INCLUDING INDEXES
+);
+CREATE TABLE part5_including_statistics(
+    LIKE part5_source_table INCLUDING STATISTICS
+);
+CREATE TABLE part5_including_storage(
+    LIKE part5_source_table INCLUDING STORAGE
+);
+CREATE TABLE part5_excluding_all(
+    LIKE part5_source_table EXCLUDING ALL
+);
+CREATE TABLE part5_excluding_comments(
+    LIKE part5_source_table EXCLUDING COMMENTS
+);
+CREATE TABLE part5_excluding_compression(
+    LIKE part5_source_table EXCLUDING COMPRESSION
+);
+CREATE TABLE part5_excluding_defaults(
+    LIKE part5_source_table EXCLUDING DEFAULTS
+);
+CREATE TABLE part5_excluding_generated(
+    LIKE part5_source_table EXCLUDING GENERATED
+);
+CREATE TABLE part5_excluding_identity(
+    LIKE part5_source_table EXCLUDING IDENTITY
+);
+CREATE TABLE part5_excluding_indexes(
+    LIKE part5_source_table EXCLUDING INDEXES
+);
+CREATE TABLE part5_excluding_statistics(
+    LIKE part5_source_table EXCLUDING STATISTICS
+);
+CREATE TABLE part5_excluding_storage(
+    LIKE part5_source_table EXCLUDING STORAGE
+);
+CREATE TABLE part5_like_list(
+    LIKE part5_source_table,
+    info text,
+    LIKE part5_source_table2 INCLUDING ALL,
+    CONSTRAINT primary_key_constraint PRIMARY KEY (id)
+);
+
+-- part 6: partition specification
+-- PARTITION OF parent_table { FOR VALUES partition_bound_spec | DEFAULT }
+CREATE TABLE part6_parent_table_range(
+    id int,
+    name varchar
+) PARTITION BY RANGE (id);
+CREATE TABLE part6_parent_table_list(
+    id int,
+    name varchar
+) PARTITION BY LIST (id);
+CREATE TABLE part6_parent_table_hash(
+    id int,
+    name varchar
+) PARTITION BY HASH (id);
+CREATE TABLE part6_partition_default PARTITION OF part6_parent_table_range DEFAULT;
+-- FROM ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] )
+--  TO ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) |
+CREATE TABLE part6_partition_spec_range1 PARTITION OF part6_parent_table_range
+FOR VALUES FROM (MINVALUE) TO (2);
+CREATE TABLE part6_partition_spec_range2 PARTITION OF part6_parent_table_range
+FOR VALUES FROM (3) TO (MAXVALUE);
+-- IN ( partition_bound_expr [, ...] ) |
+CREATE TABLE part6_partition_spec_list PARTITION OF part6_parent_table_list
+FOR VALUES IN (1, (1+2), (4+5));
+-- WITH ( MODULUS numeric_literal, REMAINDER numeric_literal )
+CREATE TABLE part6_partition_spec_hash PARTITION OF part6_parent_table_hash
+FOR VALUES WITH (MODULUS 10, REMAINDER 2);
+
+
+-- part7: create table
+-- all data types
+CREATE TABLE part7_source_table(
+    src_id int
+);
+CREATE TABLE part7_data_types(
+    var1 int8,
+    var2 serial8,
+    var3 bit,
+    var4 bit[5],
+    var5 varbit,
+    var6 varbit[5],
+    var7 bool,
+    var8 box,
+    var9 bytea,
+    var10 char,
+    var11 char[8],
+    var12 varchar,
+    var13 varchar[5],
+    var14 cidr,
+    var15 circle,
+    var16 date,
+    var17 double precision,
+    var18 inet,
+    var19 int,
+    var20 int4,
+    var21 interval,
+    var22 json,
+    var23 jsonb,
+    var24 line,
+    var25 lseg,
+    var26 macaddr,
+    var27 money,
+    var28 decimal,
+    var29 decimal(3,1),
+    var30 path,
+    var31 pg_lsn,
+    var32 pg_snapshot,
+    var33 point,
+    var34 polygon,
+    var35 float4,
+    var36 int2,
+    var37 serial2,
+    var38 serial4,
+    var39 text,
+    var40 time,
+    var41 time(3),
+    var42 timetz,
+    var43 timetz(3),
+    var44 timestamp,
+    var45 timestamp(3),
+    var46 timestamptz,
+    var47 timestamptz(3),
+    var48 tsquery,
+    var49 tsvector,
+    var50 txid_snapshot,
+    var51 uuid,
+    var52 xml
+);
+CREATE TABLE part7_compression_collate(
+    str1 varchar COMPRESSION "pglz",
+    str2 varchar COLLATE "fr_FR"
+);
+CREATE TABLE part7_inherits_parent(
+    id int,
+    name varchar
+)
+INHERITS (part7_data_types, part7_compression_collate);
+
+CREATE TABLE part7_combine_all_clauses(
+    id varchar(5) COMPRESSION "pglz" COLLATE "fr_FR" CONSTRAINT id_constraint DEFAULT 'foo',
+    PRIMARY KEY (id),
+    LIKE part7_source_table,
+    name varchar
+)
+INHERITS (part7_data_types, part7_compression_collate)
+USING heap
+WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true)
+TABLESPACE pg_default;
+
+CREATE TEMP TABLE part7_combine_all_clauses_temp(
+    id varchar(5) COMPRESSION "pglz" COLLATE "fr_FR" CONSTRAINT id_constraint DEFAULT 'foo',
+    PRIMARY KEY (id),
+    LIKE part7_source_table,
+    name varchar
+)
+INHERITS (part7_data_types, part7_compression_collate)
+USING heap
+WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true)
+ON COMMIT DELETE ROWS
+TABLESPACE pg_default;
+
+-- part8: create typed table
+CREATE TYPE part8_people_type AS (
+    id int,
+    name varchar,
+    height float4,
+    weight float4
+);
+CREATE TABLE part8_create_typed_table OF part8_people_type;
+CREATE TABLE part8_create_typed_table_simple OF part8_people_type(
+    weight,
+    PRIMARY KEY (id)
+);
+CREATE TABLE part8_create_typed_table_with_options_constaints OF part8_people_type(
+    weight WITH OPTIONS NOT NULL,
+    name UNIQUE,
+    PRIMARY KEY (id)
+);
+
+CREATE TABLE part8_create_typed_table_complex_combinations OF part8_people_type(
+    weight WITH OPTIONS NOT NULL,
+    name UNIQUE,
+    PRIMARY KEY (id)
+)
+USING heap
+WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true)
+TABLESPACE pg_default;
+
+-- part9: create table as a partition of parent table, FOR VALUES clause is tested in part 6
+CREATE TABLE part9_parent_table_range(
+    id int,
+    name varchar,
+    height float4,
+    weight float4
+) PARTITION BY RANGE (height);
+CREATE TABLE part9_parent_table_list(
+    id int,
+    name varchar,
+    height float4,
+    weight float4
+) PARTITION BY LIST (name);
+CREATE TABLE part9_parent_table_hash(
+    id int,
+    name varchar,
+    height float4,
+    weight float4
+) PARTITION BY HASH (id);
+
+-- TOFIX
+-- CREATE TABLE part9_partition_with_options_constraintscd
+-- PARTITION OF part9_parent_table_range (
+--     id PRIMARY KEY,
+--     name WITH OPTIONS NOT NULL,
+--     weight,
+--     CHECK (height > 0)
+-- )
+-- FOR VALUES FROM (MINVALUE) TO (2);
+
+-- TOFIX
+-- CREATE TABLE part9_partition_with_options_constraints_default
+-- PARTITION OF part9_parent_table_range (
+--     id PRIMARY KEY,
+--     name WITH OPTIONS NOT NULL,
+--     CHECK (height > 0)
+-- ) DEFAULT;
+
+-- TOFIX
+-- CREATE TABLE part9_partition_complex_combinations
+-- PARTITION OF part9_parent_table_range (
+--     id PRIMARY KEY,
+--     name WITH OPTIONS NOT NULL,
+--     CHECK (height > 0)
+-- )
+-- FOR VALUES FROM (3) TO (10)
+-- USING heap
+-- WITH (vacuum_index_cleanup = ON, autovacuum_vacuum_scale_factor = 0.2, vacuum_truncate = true)
+-- TABLESPACE pg_default;
+
+-- copied from old create_table.sql
+-- Test TableLikeClause is handled properly
+CREATE TABLE ctlt1 (a text CHECK (length(a) > 2) PRIMARY KEY, b text);
+ALTER TABLE ctlt1 ALTER COLUMN a SET STORAGE MAIN;
+ALTER TABLE ctlt1 ALTER COLUMN b SET STORAGE EXTERNAL;
+CREATE TABLE ctlt1_like (LIKE ctlt1 INCLUDING ALL);
+
+-- Test foreign key constraint is handled in a following ALTER TABLE ADD CONSTRAINT FOREIGN KEY REFERENCES subcommand
+CREATE TABLE product (id int PRIMARY KEY, name text);
+CREATE TABLE orders2 (order_id int PRIMARY KEY, product_id int
+REFERENCES product (id));
+
+-- Test CREATE and ALTER inherited table
+CREATE TABLE gtest30 (
+a int,
+b int GENERATED ALWAYS AS (a * 2) STORED
+);
+CREATE TABLE gtest30_1 () INHERITS (gtest30);
+ALTER TABLE gtest30 ALTER COLUMN b DROP EXPRESSION;
diff --git a/src/test/modules/test_ddl_deparse_regress/sql/test_ddl_deparse.sql b/src/test/modules/test_ddl_deparse_regress/sql/test_ddl_deparse.sql
new file mode 100644
index 0000000..070cee8
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/sql/test_ddl_deparse.sql
@@ -0,0 +1,23 @@
+CREATE ROLE ddl_testing_role SUPERUSER;
+SET ROLE ddl_testing_role;
+
+CREATE EXTENSION test_ddl_deparse_regress;
+
+CREATE OR REPLACE FUNCTION test_ddl_deparse()
+  RETURNS event_trigger LANGUAGE plpgsql AS
+$$
+DECLARE
+	r record;
+	deparsed_json text;
+BEGIN
+	FOR r IN SELECT * FROM pg_event_trigger_ddl_commands()
+	LOOP
+		deparsed_json = pg_catalog.ddl_deparse_to_json(r.command);
+		RAISE NOTICE 'deparsed json: %', deparsed_json;
+		RAISE NOTICE 're-formed command: %', pg_catalog.ddl_deparse_expand_command(deparsed_json);
+	END LOOP;
+END;
+$$;
+
+CREATE EVENT TRIGGER test_ddl_deparse
+ON ddl_command_end EXECUTE PROCEDURE test_ddl_deparse();
diff --git a/src/test/modules/test_ddl_deparse_regress/t/001_compare_dumped_results.pl b/src/test/modules/test_ddl_deparse_regress/t/001_compare_dumped_results.pl
new file mode 100644
index 0000000..c511b5b
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/t/001_compare_dumped_results.pl
@@ -0,0 +1,211 @@
+use strict;
+use warnings;
+use Env;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+use File::Basename;
+
+sub execute_test_case {
+    my $test_name = $_[0];
+    my $pub_node = $_[1];
+    my $sub_node = $_[2];
+    my $dbname = $_[3];
+    my $user = $_[4];
+    my $outputdir = $PostgreSQL::Test::Utils::tmp_check;
+
+    # set up deparse testing resources
+    create_deparse_testing_resources_on_pub_node($pub_node, $dbname, $user);
+
+    my $test_file = "./sql/${test_name}.sql";
+    my $content = do{local(@ARGV,$/)=$test_file;<>};
+    my $pub_node_error = '';
+    $pub_node -> psql($dbname, $content,
+        stderr => \$pub_node_error,
+        extra_params => ["-U", "${user}"]);
+    # check execution of test SQL commands
+    ok($pub_node_error eq '', "execute test SQL commands from ".$test_name) or diag("Failure from "
+        .$test_file.": ".$pub_node_error);
+
+    # retrieve reformed SQL commands on pub node, write to file
+    my $ddl_sql = '';
+    $pub_node -> psql($dbname,q(
+        select ddl_deparse_expand_command(ddl) || ';' from deparsed_ddls ORDER BY id ASC),
+        stdout => \$ddl_sql,
+        extra_params => ["-U", "${user}"]);
+    mkdir ${outputdir}."/ddl", 0755;
+    my $ddl_output_file = ${outputdir}."/ddl/${test_name}.sql";
+    open(FH, '>', $ddl_output_file) or die $!;
+    print FH $ddl_sql;
+    close(FH);
+
+    # execute reformed SQL commands on sub node
+    my $sub_node_error = '';
+    $sub_node -> psql($dbname, $ddl_sql,
+        stderr => \$sub_node_error,
+        extra_params => ["-U", "${user}"]);
+    # check execution of reformed DDL commands
+    ok($sub_node_error eq '', "replay reformed DDL commands from ".$test_name) or diag("Failure from "
+        .$ddl_output_file.": ".$sub_node_error);
+
+    # clean up deparse testing resources
+    clean_deparse_testing_resources_on_pub_node($pub_node, $dbname);
+    # dump from pub node and sub node
+    mkdir ${outputdir}."/dumps", 0755;
+    my $pub_dump = ${outputdir}."/dumps/${test_name}_pub.dump";
+    my $sub_dump = ${outputdir}."/dumps/${test_name}_sub.dump";
+    my $dump_diff = ${outputdir}."/dumps/${test_name}_dump.diff";
+    system("pg_dumpall "
+        . "-s "
+        . "-f "
+        . $pub_dump . " "
+        . "--no-sync "
+        .  '-p '
+        . $pub_node->port)  == 0 or die "Dump pub node failed in ${test_name}";
+    system("pg_dumpall "
+        . "-s "
+        . "-f "
+        . $sub_dump . " "
+        . "--no-sync "
+        .  '-p '
+        . $sub_node->port)  == 0 or die "Dump sub node failed in ${test_name}";
+
+    # compare dumped results
+    system("diff ".$pub_dump." ".$sub_dump." > ".$dump_diff);
+    ok(system("diff ".$pub_dump." ".$sub_dump) == 0, "compare dumped results in ${test_name}")
+        or diag("Dumped results are different in ".$test_name
+        .", check ".$dump_diff);
+}
+
+sub init_node {
+    my $node_name = $_[0];
+    my $node = PostgreSQL::Test::Cluster->new($node_name);
+    # increase some settings that Cluster->new makes too low by default.
+    $node -> init();
+    $node -> start();
+    $node -> append_conf('postgresql.conf', 'max_connections = 25');
+    $node -> append_conf('postgresql.conf', 'client_min_messages = error');
+    $node -> append_conf('postgresql.conf', 'max_prepared_transactions = 10');
+    $node -> restart();
+    return $node;
+}
+
+sub init_pub_node {
+    my $node_name = $_[0]."_pub";
+    return init_node($node_name)
+}
+
+sub init_sub_node {
+    my $node_name = $_[0]."_sub";
+    return init_node($node_name)
+}
+
+sub create_deparse_testing_resources_on_pub_node {
+    my $node = $_[0];
+    my $dbname = $_[1];
+    my $user = $_[2];
+    $node -> psql($dbname, "
+        begin;
+        CREATE EXTENSION test_ddl_deparse_regress;
+        create table deparsed_ddls(id SERIAL PRIMARY KEY, tag text, object_identity text, ddl text);
+
+        create or replace function deparse_to_json()
+            returns event_trigger language plpgsql as
+        \$\$
+        declare
+            r record;
+        begin
+            for r in select * from pg_event_trigger_ddl_commands()
+            loop
+                insert into deparsed_ddls(tag, object_identity, ddl) values (r.command_tag, r.object_identity, pg_catalog.ddl_deparse_to_json(r.command));
+            end loop;
+        END;
+        \$\$;
+
+        create or replace function deparse_drops_to_json()
+            returns event_trigger language plpgsql as
+        \$\$
+        declare
+            r record;
+        begin
+            for r in select * from pg_event_trigger_dropped_objects()
+            loop
+                insert into deparsed_ddls(tag, object_identity, ddl) values (r.object_type, r.object_identity, public.deparse_drop_ddl(r.object_identity, r.object_type));
+            end loop;
+        END;
+        \$\$;
+
+        create event trigger ddl_deparse_trig
+        on ddl_command_end execute procedure deparse_to_json();
+
+        create event trigger ddl_drops_deparse_trig
+        on sql_drop execute procedure deparse_drops_to_json();
+
+        commit;
+    "
+    );
+}
+
+sub clean_deparse_testing_resources_on_pub_node {
+    my $node = $_[0];
+    my $dbname = $_[1];
+    # Drop the event trigger and the function before taking a logical dump.
+    $node -> safe_psql($dbname,q(
+        drop event trigger ddl_deparse_trig;
+        drop event trigger ddl_drops_deparse_trig;
+        drop function deparse_to_json();
+        drop function deparse_drops_to_json();
+        drop table deparsed_ddls;
+        DROP EXTENSION test_ddl_deparse_regress;
+    ));
+}
+
+sub create_prerequisite_resources {
+    my $node = $_[0];
+    my $dbname = $_[1];
+    my $user = $_[2];
+    $node -> safe_psql($dbname, "CREATE ROLE ${user} SUPERUSER LOGIN CREATEDB;");
+}
+
+sub trim {
+    my @out = @_;
+    for (@out) {
+        s/^\s+//;
+        s/\s+$//;
+    }
+    return wantarray ? @out : $out[0];
+}
+
+# Create and start pub sub nodes
+my $initial_dbname = "postgres";
+my $user = "ddl_testing_role";
+my $pub_node = init_pub_node("test", $user);
+my $sub_node = init_sub_node("test", $user);
+create_prerequisite_resources($pub_node, $initial_dbname, $user);
+create_prerequisite_resources($sub_node, $initial_dbname, $user);
+
+# load test cases from the regression tests
+my @regress_tests = split /\s+/, $ENV{REGRESS};
+my $test_case_count = scalar @regress_tests - 1;
+my $test_count_per_case = 3;
+my $test_count = $test_case_count * $test_count_per_case;
+
+plan tests => $test_count;
+foreach(@regress_tests) {
+    my $test_name = trim($_);
+    # skip if it's regression test preparation or empty string
+    if ($test_name eq "" or $test_name eq "test_ddl_deparse")
+    {
+        next;
+    }
+    my $test_dbname = $test_name;
+    $pub_node -> safe_psql($initial_dbname, "CREATE DATABASE ${test_dbname};", extra_params => ["-U", "${user}"]);
+    $sub_node -> safe_psql($initial_dbname, "CREATE DATABASE ${test_dbname};", extra_params => ["-U", "${user}"]);
+    execute_test_case($test_name, $pub_node, $sub_node, $test_dbname, $user);
+}
+done_testing();
+
+# Close nodes
+$pub_node->stop;
+$sub_node->stop;
+
diff --git a/src/test/modules/test_ddl_deparse_regress/t/002_regress_tests.pl b/src/test/modules/test_ddl_deparse_regress/t/002_regress_tests.pl
new file mode 100644
index 0000000..3a875c3
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/t/002_regress_tests.pl
@@ -0,0 +1,207 @@
+use strict;
+use warnings;
+use Env;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+use File::Basename;
+
+sub execute_regress_test {
+    my $pub_node = $_[0];
+    my $sub_node = $_[1];
+    my $dbname = "postgres";
+    my $dlpath    = dirname($ENV{REGRESS_SHLIB});
+    my $inputdir = "../../regress";
+    my $outputdir = $PostgreSQL::Test::Utils::tmp_check;
+
+    # set up deparse testing resources
+    create_deparse_testing_resources_on_pub_node($pub_node, $dbname);
+
+    # execute core regression tests on pub node
+    my $regress_cmd = $ENV{PG_REGRESS}
+        . " "
+        . "--dlpath=\"$dlpath\" "
+        . "--max-concurrent-tests=20 "
+        . "--dbname="
+        . $dbname . " "
+        . "--use-existing "
+        . "--host="
+        . $pub_node->host . " "
+        . "--port="
+        . $pub_node->port . " "
+        . "--inputdir=$inputdir "
+        . "--outputdir=\"$outputdir\" "
+        . "--schedule=$inputdir/parallel_schedule";
+    print "Regression test command is $regress_cmd";
+    my $rc = system($regress_cmd);
+    if ($rc != 0)
+    {
+        # If regression test fails, dump out the regression diffs file
+        my $diffs = "${outputdir}/regression/regression.diffs";
+        if (-e $diffs)
+        {
+            print "=== dumping $diffs ===\n";
+            print slurp_file($diffs);
+            print "=== EOF ===\n";
+        }
+        die "Regression test failed";
+    }
+
+    # Retrieve SQL commands generated from deparsed DDLs on pub node
+    my $ddl_sql = '';
+    $pub_node -> psql($dbname,q(
+        select ddl_deparse_expand_command(ddl) || ';' from deparsed_ddls ORDER BY id ASC),
+        stdout => \$ddl_sql);
+
+    # Execute SQL commands on sub node
+    $sub_node -> psql($dbname, $ddl_sql);
+
+    # Clean up deparse testing resources
+    clean_deparse_testing_resources_on_pub_node($pub_node, $dbname);
+
+    # Dump from pub node and sub node
+    mkdir ${outputdir}."/dumps", 0755;
+    my $pub_dump = ${outputdir}."/dumps/regress_pub.dump";
+    my $sub_dump = ${outputdir}."/dumps/regress_sub.dump";
+    system("pg_dumpall "
+        . "-s "
+        . "-f "
+        . $pub_dump . " "
+        . "--no-sync "
+        .  '-p '
+        . $pub_node->port)  == 0 or die "Dump pub node failed";
+    system("pg_dumpall "
+        . "-s "
+        . "-f "
+        . $sub_dump . " "
+        . "--no-sync "
+        .  '-p '
+        . $sub_node->port)  == 0 or die "Dump sub node failed";
+
+    # Compare dumped results
+    is(system("diff "
+    . $pub_dump . " "
+    . $sub_dump), 0, "Comparing dumped output");
+
+    # Close nodes
+    $pub_node->stop;
+    $sub_node->stop;
+}
+
+sub init_node {
+    my $node_name = $_[0];
+    my $node = PostgreSQL::Test::Cluster->new($node_name);
+    $node->init;
+    # increase some settings that Cluster->new makes too low by default.
+    $node->adjust_conf('postgresql.conf', 'max_connections', '25');
+    $node->append_conf('postgresql.conf',
+		   'max_prepared_transactions = 10');
+    return $node;
+}
+
+sub init_pub_node {
+    my $node_name = $_[0]."_pub";
+    return init_node($node_name)
+}
+
+sub init_sub_node {
+    my $node_name = $_[0]."_sub";
+    return init_node($node_name)
+}
+
+sub create_deparse_testing_resources_on_pub_node {
+    my $node = $_[0];
+    my $dbname = $_[1];
+    $node -> psql($dbname, q(
+        begin;
+        CREATE EXTENSION test_ddl_deparse_regress;
+        create table deparsed_ddls(id SERIAL PRIMARY KEY, tag text, object_identity text, ddl text);
+        create or replace function deparse_to_json()
+            returns event_trigger language plpgsql as
+        $$
+        declare
+            r record;
+        begin
+            for r in select * from pg_event_trigger_ddl_commands()
+            loop
+                insert into deparsed_ddls(tag, object_identity, ddl) values (r.command_tag, r.object_identity, pg_catalog.ddl_deparse_to_json(r.command));
+            end loop;
+        END;
+        $$;
+        create or replace function deparse_drops_to_json()
+            returns event_trigger language plpgsql as
+        $$
+        declare
+            r record;
+        begin
+            for r in select * from pg_event_trigger_dropped_objects()
+            loop
+                insert into deparsed_ddls(tag, object_identity, ddl) values (r.object_type, r.object_identity, public.deparse_drop_ddl(r.object_identity, r.object_type));
+            end loop;
+        END;
+        $$;
+        create event trigger ddl_deparse_trig
+        on ddl_command_end execute procedure deparse_to_json();
+        create event trigger ddl_drops_deparse_trig
+        on sql_drop execute procedure deparse_drops_to_json();
+        commit;
+    ));
+}
+
+sub clean_deparse_testing_resources_on_pub_node {
+    my $node = $_[0];
+    my $dbname = $_[1];
+    # Drop the event trigger and the function before taking a logical dump.
+    $node -> safe_psql($dbname,q(
+        drop event trigger ddl_deparse_trig;
+        drop event trigger ddl_drops_deparse_trig;
+        drop function deparse_to_json();
+        drop function deparse_drops_to_json();
+        drop table deparsed_ddls;
+        DROP EXTENSION test_ddl_deparse_regress;
+    ));
+}
+
+sub trim {
+    my @out = @_;
+    for (@out) {
+        s/^\s+//;
+        s/\s+$//;
+    }
+    return wantarray ? @out : $out[0];
+}
+
+# Create and start pub sub nodes
+my $pub_node = init_pub_node("regress");
+my $sub_node = init_sub_node("regress");
+$pub_node -> start;
+$sub_node -> start;
+
+# Comment the execution temporarily, an error in ddl_deparse.c will cause the database exits abnormally, error signature:
+#
+# 2022-12-03 23:02:44.778 UTC [129102] pg_regress/tablespace LOG:  statement: ALTER TABLE ALL IN TABLESPACE regress_tblspace_renamed SET TABLESPACE pg_default;
+# TRAP: failed Assert("IsA(stmt, AlterTableStmt)"), File: "ddl_deparse.c", Line: 3371, PID: 129102
+# postgres: regress_pub: runqi postgres [local] ALTER TABLE(ExceptionalCondition+0xbb)[0x563bd6ea5b0d]
+# ...
+# /lib/x86_64-linux-gnu/libc.so.6(+0x29d90)[0x7fd6a74a6d90]
+# /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80)[0x7fd6a74a6e40]
+# postgres: regress_pub: runqi postgres [local] ALTER TABLE(_start+0x25)[0x563bd672f1e5]
+# 2022-12-03 23:02:44.850 UTC [129058] LOG:  server process (PID 129102) was terminated by signal 6: Aborted
+# 2022-12-03 23:02:44.850 UTC [129058] DETAIL:  Failed process was running: ALTER TABLE ALL IN TABLESPACE regress_tblspace_renamed SET TABLESPACE pg_default;
+# 2022-12-03 23:02:44.850 UTC [129058] LOG:  terminating any other active server processes
+# 2022-12-03 23:02:44.851 UTC [129058] LOG:  shutting down because restart_after_crash is off
+# 2022-12-03 23:02:44.852 UTC [129058] LOG:  database system is shut down
+
+# eval {execute_regress_test($pub_node, $sub_node);};
+# if ($@ ne "")
+# {
+#     fail($@);
+# }
+
+# Close nodes
+$pub_node->stop;
+$sub_node->stop;
+
+pass("regresssion test passed");
+
+done_testing();
\ No newline at end of file
diff --git a/src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress--1.0.sql b/src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress--1.0.sql
new file mode 100644
index 0000000..14070cd
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress--1.0.sql
@@ -0,0 +1,9 @@
+/* src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION test_ddl_deparse_regress" to load this file. \quit
+
+CREATE FUNCTION deparse_drop_ddl(IN objidentity text,
+    IN objecttype text)
+  RETURNS text IMMUTABLE STRICT
+  AS 'MODULE_PATHNAME' LANGUAGE C;
\ No newline at end of file
diff --git a/src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress.c b/src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress.c
new file mode 100644
index 0000000..bd6992b
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress.c
@@ -0,0 +1,59 @@
+/*----------------------------------------------------------------------
+ * test_ddl_deparse_regress.c
+ *		Support functions for the test_ddl_deparse_regress module
+ *
+ * Copyright (c) 2014-2022, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress.c
+ *----------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "catalog/pg_type.h"
+#include "funcapi.h"
+#include "nodes/execnodes.h"
+#include "tcop/deparse_utility.h"
+#include "tcop/utility.h"
+#include "utils/builtins.h"
+#include "tcop/ddl_deparse.h"
+
+PG_MODULE_MAGIC;
+
+PG_FUNCTION_INFO_V1(deparse_drop_ddl);
+
+/*
+ * Given object_identity and object_type of dropped object, return a JSON representation of DROP command.
+ */
+Datum
+deparse_drop_ddl(PG_FUNCTION_ARGS)
+{
+	text	   *objidentity = PG_GETARG_TEXT_P(0);
+	const char	   *objidentity_str = text_to_cstring(objidentity);
+	text	   *objecttype = PG_GETARG_TEXT_P(1);
+	const char	   *objecttype_str = text_to_cstring(objecttype);
+
+	char		   *command;
+
+	// constraint is part of alter table command, no need to drop in DROP command
+	if (strcmp(objecttype_str, "table constraint") == 0) {
+		PG_RETURN_NULL();
+	} else if (strcmp(objecttype_str, "toast table") == 0) {
+		objecttype_str = "table";
+	}  else if (strcmp(objecttype_str, "default value") == 0) {
+		PG_RETURN_NULL();
+	} else if (strcmp(objecttype_str, "operator of access method") == 0) {
+		PG_RETURN_NULL();
+	} else if (strcmp(objecttype_str, "function of access method") == 0) {
+		PG_RETURN_NULL();
+	} else if (strcmp(objecttype_str, "table column") == 0) {
+		PG_RETURN_NULL();
+	}
+
+	command = deparse_drop_command(objidentity_str, objecttype_str, DROP_CASCADE);
+
+	if (command)
+		PG_RETURN_TEXT_P(cstring_to_text(command));
+
+	PG_RETURN_NULL();
+}
\ No newline at end of file
diff --git a/src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress.control b/src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress.control
new file mode 100644
index 0000000..a1f934e
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse_regress/test_ddl_deparse_regress.control
@@ -0,0 +1,4 @@
+comment = 'Test code for DDL deparse regress feature'
+default_version = '1.0'
+module_pathname = '$libdir/test_ddl_deparse_regress'
+relocatable = true
-- 
1.8.3.1



  [application/octet-stream] v80-0002-Functions-to-deparse-Table-DDL-commands.patch (131.2K, 5-v80-0002-Functions-to-deparse-Table-DDL-commands.patch)
  download | inline diff:
From 79bf0ea3b481419dae46f14a6419238943fafdf3 Mon Sep 17 00:00:00 2001
From: Ajin Cherian <ajinc@fast.au.fujitsu.com>
Date: Mon, 13 Mar 2023 23:39:45 -0400
Subject: [PATCH v80 2/8] Functions to deparse Table DDL commands.

This patch constructs JSON blobs representing DDL commands, which can
later be re-processed into plain strings by well-defined sprintf-like
expansion. These JSON objects are intended to allow for machine-editing of
the commands, by replacing certain nodes within the objects.

Much of the information in the output blob actually comes from system
catalogs, not from the command parse node, as it is impossible to reliably
construct a fully-specified command (i.e. one not dependent on search_path
etc) looking only at the parse node.

This provides a base for logical replication of DDL statements. Currently,
the patch has support for:

CREATE/ALTER/DROP TABLE -- Note #1, Note #2

(Note #1) Some recently introduced DDLs(e.g. DDLs related to
PARTITIONED TABLE) are unsupported. We can extend it as we need more
functionality for DDL replication.

(Note #2) For ATTACH/DETACH PARTITION, we haven't added extra logic on
the subscriber to handle the case where the table on the publisher is a PARTITIONED
TABLE while the target table on the subcriber side is a NORMAL table. We will
research this more and improve it later.
---
 src/backend/commands/Makefile        |    2 +
 src/backend/commands/collationcmds.c |    4 +-
 src/backend/commands/ddl_deparse.c   | 3598 ++++++++++++++++++++++++++++++++++
 src/backend/commands/ddl_json.c      |  781 ++++++++
 src/backend/commands/event_trigger.c |    3 +
 src/backend/commands/meson.build     |    2 +
 src/include/catalog/pg_proc.dat      |    7 +
 src/include/nodes/parsenodes.h       |    1 +
 src/include/tcop/ddl_deparse.h       |   22 +
 src/include/tcop/deparse_utility.h   |   11 +-
 src/tools/pgindent/typedefs.list     |    4 +
 11 files changed, 4432 insertions(+), 3 deletions(-)
 create mode 100644 src/backend/commands/ddl_deparse.c
 create mode 100644 src/backend/commands/ddl_json.c
 create mode 100644 src/include/tcop/ddl_deparse.h

diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile
index 48f7348..171dfb2 100644
--- a/src/backend/commands/Makefile
+++ b/src/backend/commands/Makefile
@@ -29,6 +29,8 @@ OBJS = \
 	copyto.o \
 	createas.o \
 	dbcommands.o \
+	ddl_deparse.o \
+	ddl_json.o \
 	define.o \
 	discard.o \
 	dropcmds.o \
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index e5b2d99..a911fda 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -156,8 +156,8 @@ DefineCollation(ParseState *pstate, List *names, List *parameters,
 			elog(ERROR, "cache lookup failed for collation %u", collid);
 
 		/*
-		 * Make from existing collationid available to callers for statements such as
-		 * CREATE COLLATION any_name FROM any_name
+		 * Make from existing collationid available to callers for statements
+		 * such as CREATE COLLATION any_name FROM existing_collation.
 		 */
 		if (from_existing_collid && OidIsValid(collid))
 			ObjectAddressSet(*from_existing_collid, CollationRelationId, collid);
diff --git a/src/backend/commands/ddl_deparse.c b/src/backend/commands/ddl_deparse.c
new file mode 100644
index 0000000..4e248de
--- /dev/null
+++ b/src/backend/commands/ddl_deparse.c
@@ -0,0 +1,3598 @@
+/*-------------------------------------------------------------------------
+ *
+ * ddl_deparse.c
+ *	  Functions to convert utility commands to machine-parseable
+ *	  representation
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ *
+ * This is intended to provide JSON blobs representing DDL commands, which can
+ * later be re-processed into plain strings by well-defined sprintf-like
+ * expansion.  These JSON objects are intended to allow for machine-editing of
+ * the commands, by replacing certain nodes within the objects.
+ *
+ * Much of the information in the output blob actually comes from system
+ * catalogs, not from the command parse node, as it is impossible to reliably
+ * construct a fully-specified command (i.e. one not dependent on search_path
+ * etc) looking only at the parse node.
+ *
+ * Deparse object tree is created by using:
+ * 	a) new_objtree("know contents") where the complete tree content is known or
+ *     the initial tree content is known.
+ * 	b) new_objtree("") for the syntax where the object tree will be derived
+ *     based on some conditional checks.
+ * 	c) new_objtree_VA where the complete tree can be derived using some fixed
+ *     content and/or some variable arguments.
+ *
+ * IDENTIFICATION
+ *	  src/backend/commands/ddl_deparse.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/amapi.h"
+#include "access/relation.h"
+#include "access/table.h"
+#include "catalog/namespace.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_aggregate.h"
+#include "catalog/pg_authid.h"
+#include "catalog/pg_cast.h"
+#include "catalog/pg_collation.h"
+#include "catalog/pg_constraint.h"
+#include "catalog/pg_conversion.h"
+#include "catalog/pg_depend.h"
+#include "catalog/pg_extension.h"
+#include "catalog/pg_foreign_data_wrapper.h"
+#include "catalog/pg_foreign_server.h"
+#include "catalog/pg_inherits.h"
+#include "catalog/pg_language.h"
+#include "catalog/pg_largeobject.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_opclass.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_opfamily.h"
+#include "catalog/pg_policy.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_range.h"
+#include "catalog/pg_rewrite.h"
+#include "catalog/pg_sequence.h"
+#include "catalog/pg_statistic_ext.h"
+#include "catalog/pg_transform.h"
+#include "catalog/pg_ts_config.h"
+#include "catalog/pg_ts_dict.h"
+#include "catalog/pg_ts_parser.h"
+#include "catalog/pg_ts_template.h"
+#include "catalog/pg_type.h"
+#include "catalog/pg_user_mapping.h"
+#include "commands/defrem.h"
+#include "commands/sequence.h"
+#include "commands/tablespace.h"
+#include "foreign/foreign.h"
+#include "funcapi.h"
+#include "mb/pg_wchar.h"
+#include "nodes/nodeFuncs.h"
+#include "nodes/parsenodes.h"
+#include "optimizer/optimizer.h"
+#include "parser/parse_type.h"
+#include "rewrite/rewriteHandler.h"
+#include "tcop/ddl_deparse.h"
+#include "tcop/utility.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/guc.h"
+#include "utils/jsonb.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/ruleutils.h"
+#include "utils/syscache.h"
+
+/* Estimated length of the generated jsonb string */
+#define JSONB_ESTIMATED_LEN 128
+
+/*
+ * Before they are turned into JSONB representation, each command is
+ * represented as an object tree, using the structs below.
+ */
+typedef enum
+{
+	ObjTypeNull,
+	ObjTypeBool,
+	ObjTypeString,
+	ObjTypeArray,
+	ObjTypeInteger,
+	ObjTypeFloat,
+	ObjTypeObject
+} ObjType;
+
+/*
+ * Represent the command as an object tree.
+ */
+typedef struct ObjTree
+{
+	slist_head	params;			/* Object tree parameters */
+	int			numParams;		/* Number of parameters in the object tree */
+	StringInfo	fmtinfo;		/* Format string of the ObjTree */
+	bool		present;		/* Indicates if boolean value should be stored */
+} ObjTree;
+
+/*
+ * An element of an object tree (ObjTree).
+ */
+typedef struct ObjElem
+{
+	char	   *name;			/* Name of object element */
+	ObjType		objtype;		/* Object type */
+
+	union
+	{
+		bool		boolean;
+		char	   *string;
+		int64		integer;
+		float8		flt;
+		ObjTree    *object;
+		List	   *array;
+	}			value;			/* Store the object value based on the object
+								 * type */
+	slist_node	node;			/* Used in converting back to ObjElem
+								 * structure */
+} ObjElem;
+
+/*
+ * Reduce some unnecessary strings from the output json when verbose
+ * and "present" member is false. This means these strings won't be merged into
+ * the last DDL command.
+ */
+bool		verbose = true;
+
+static void append_array_object(ObjTree *tree, char *sub_fmt, List *array);
+static void append_bool_object(ObjTree *tree, char *sub_fmt, bool value);
+static void append_null_object(ObjTree *tree, char *sub_fmt);
+static void append_object_object(ObjTree *tree, char *sub_fmt, ObjTree *value);
+static char *append_object_to_format_string(ObjTree *tree, char *sub_fmt);
+static void append_premade_object(ObjTree *tree, ObjElem *elem);
+static void append_string_object(ObjTree *tree, char *sub_fmt, char *name,
+								 char *value);
+static void format_type_detailed(Oid type_oid, int32 typemod,
+								 Oid *nspid, char **typname, char **typemodstr,
+								 bool *typarray);
+static ObjElem *new_object(ObjType type, char *name);
+static ObjTree *new_objtree_for_qualname_id(Oid classId, Oid objectId);
+static ObjElem *new_object_object(ObjTree *value);
+static ObjTree *new_objtree_VA(char *fmt, int numobjs,...);
+static JsonbValue *objtree_to_jsonb_rec(ObjTree *tree, JsonbParseState *state);
+static void pg_get_indexdef_detailed(Oid indexrelid,
+									 char **index_am,
+									 char **definition,
+									 char **reloptions,
+									 char **tablespace,
+									 char **whereClause);
+static char *RelationGetColumnDefault(Relation rel, AttrNumber attno,
+									  List *dpcontext, List **exprs);
+
+static ObjTree *deparse_ColumnDef(Relation relation, List *dpcontext, bool composite,
+								  ColumnDef *coldef, bool is_alter, List **exprs);
+static ObjTree *deparse_ColumnIdentity(Oid seqrelid, char identity, bool alter_table);
+static ObjTree *deparse_ColumnSetOptions(AlterTableCmd *subcmd);
+
+static ObjTree *deparse_DefElem(DefElem *elem, bool is_reset);
+static ObjTree *deparse_OnCommitClause(OnCommitAction option);
+static ObjTree *deparse_RelSetOptions(AlterTableCmd *subcmd);
+
+static inline ObjElem *deparse_Seq_Cache(Form_pg_sequence seqdata, bool alter_table);
+static inline ObjElem *deparse_Seq_Cycle(Form_pg_sequence seqdata, bool alter_table);
+static inline ObjElem *deparse_Seq_IncrementBy(Form_pg_sequence seqdata, bool alter_table);
+static inline ObjElem *deparse_Seq_Minvalue(Form_pg_sequence seqdata, bool alter_table);
+static inline ObjElem *deparse_Seq_Maxvalue(Form_pg_sequence seqdata, bool alter_table);
+static inline ObjElem *deparse_Seq_Restart(int64 last_value);
+static inline ObjElem *deparse_Seq_Startwith(Form_pg_sequence seqdata, bool alter_table);
+static inline ObjElem *deparse_Seq_As(Form_pg_sequence seqdata);
+static inline ObjElem *deparse_Type_Storage(Form_pg_type typForm);
+static inline ObjElem *deparse_Type_Receive(Form_pg_type typForm);
+static inline ObjElem *deparse_Type_Send(Form_pg_type typForm);
+static inline ObjElem *deparse_Type_Typmod_In(Form_pg_type typForm);
+static inline ObjElem *deparse_Type_Typmod_Out(Form_pg_type typForm);
+static inline ObjElem *deparse_Type_Analyze(Form_pg_type typForm);
+static inline ObjElem *deparse_Type_Subscript(Form_pg_type typForm);
+
+static List *deparse_InhRelations(Oid objectId);
+static List *deparse_TableElements(Relation relation, List *tableElements, List *dpcontext,
+								   bool typed, bool composite);
+
+/*
+ * Append present as false to a tree.
+ */
+static void
+append_not_present(ObjTree *tree)
+{
+	append_bool_object(tree, "present", false);
+}
+
+/*
+ * Append an array parameter to a tree.
+ */
+static void
+append_array_object(ObjTree *tree, char *sub_fmt, List *array)
+{
+	ObjElem    *param;
+	char	   *object_name;
+
+	Assert(sub_fmt);
+
+	if (list_length(array) == 0)
+		return;
+
+	if (!verbose)
+	{
+		ListCell   *lc;
+
+		/* Remove elements where present flag is false */
+		foreach(lc, array)
+		{
+			ObjElem    *elem = (ObjElem *) lfirst(lc);
+
+			Assert(elem->objtype == ObjTypeObject ||
+				   elem->objtype == ObjTypeString);
+
+			if (!elem->value.object->present &&
+				elem->objtype == ObjTypeObject)
+				array = foreach_delete_current(array, lc);
+		}
+
+	}
+
+	/* Check for empty list after removing elements */
+	if (list_length(array) == 0)
+		return;
+
+	object_name = append_object_to_format_string(tree, sub_fmt);
+
+	param = new_object(ObjTypeArray, object_name);
+	param->value.array = array;
+	append_premade_object(tree, param);
+}
+
+/*
+ * Append a boolean parameter to a tree.
+ */
+static void
+append_bool_object(ObjTree *tree, char *sub_fmt, bool value)
+{
+	ObjElem    *param;
+	char	   *object_name = sub_fmt;
+	bool		is_present_flag = false;
+
+	Assert(sub_fmt);
+
+	/*
+	 * Check if the format string is 'present' and if yes, store the boolean
+	 * value
+	 */
+	if (strcmp(sub_fmt, "present") == 0)
+	{
+		is_present_flag = true;
+		tree->present = value;
+	}
+
+	if (!is_present_flag)
+		object_name = append_object_to_format_string(tree, sub_fmt);
+
+	param = new_object(ObjTypeBool, object_name);
+	param->value.boolean = value;
+	append_premade_object(tree, param);
+}
+
+/*
+ * Append the input format string to the ObjTree.
+ */
+static void
+append_format_string(ObjTree *tree, char *sub_fmt)
+{
+	int			len;
+	char	   *fmt;
+
+	if (tree->fmtinfo == NULL)
+		return;
+
+	fmt = tree->fmtinfo->data;
+	len = tree->fmtinfo->len;
+
+	/* Add a separator if necessary */
+	if (len > 0 && fmt[len - 1] != ' ')
+		appendStringInfoSpaces(tree->fmtinfo, 1);
+
+	appendStringInfoString(tree->fmtinfo, sub_fmt);
+}
+
+/*
+ * Append a NULL object to a tree.
+ */
+static void
+append_null_object(ObjTree *tree, char *sub_fmt)
+{
+	char	   *object_name;
+
+	Assert(sub_fmt);
+
+	if (!verbose)
+		return;
+
+	object_name = append_object_to_format_string(tree, sub_fmt);
+
+	append_premade_object(tree, new_object(ObjTypeNull, object_name));
+}
+
+/*
+ * Append an object parameter to a tree.
+ */
+static void
+append_object_object(ObjTree *tree, char *sub_fmt, ObjTree *value)
+{
+	ObjElem    *param;
+	char	   *object_name;
+
+	Assert(sub_fmt);
+
+	if (!verbose && !value->present)
+		return;
+
+	object_name = append_object_to_format_string(tree, sub_fmt);
+
+	param = new_object(ObjTypeObject, object_name);
+	param->value.object = value;
+	append_premade_object(tree, param);
+}
+
+/*
+ * Return the object name which is extracted from the input "*%{name[:.]}*"
+ * style string. And append the input format string to the ObjTree.
+ */
+static char *
+append_object_to_format_string(ObjTree *tree, char *sub_fmt)
+{
+	StringInfoData object_name;
+	const char *end_ptr, *start_ptr;
+	int         length;
+	char        *tmp_str;
+
+	if (sub_fmt == NULL || tree->fmtinfo == NULL)
+		return sub_fmt;
+
+	initStringInfo(&object_name);
+
+	start_ptr = strchr(sub_fmt, '{');
+	end_ptr = strchr(sub_fmt, ':');
+	if (end_ptr == NULL)
+		end_ptr = strchr(sub_fmt, '}');
+
+	if (start_ptr != NULL && end_ptr != NULL)
+	{
+		length = end_ptr - start_ptr - 1;
+		tmp_str = (char *) palloc(length + 1);
+		strncpy(tmp_str, start_ptr + 1, length);
+		tmp_str[length] = '\0';
+		appendStringInfoString(&object_name, tmp_str);
+		pfree(tmp_str);
+	}
+
+	if (object_name.len == 0)
+		elog(ERROR, "object name not found");
+
+	append_format_string(tree, sub_fmt);
+
+	return object_name.data;
+
+}
+
+/*
+ * Append a preallocated parameter to a tree.
+ */
+static inline void
+append_premade_object(ObjTree *tree, ObjElem *elem)
+{
+	slist_push_head(&tree->params, &elem->node);
+	tree->numParams++;
+}
+
+/*
+ * Append a string parameter to a tree.
+ */
+static void
+append_string_object(ObjTree *tree, char *sub_fmt, char * object_name,
+					 char *value)
+{
+	ObjElem    *param;
+
+	Assert(sub_fmt);
+
+	if (!verbose && (value == NULL || value[0] == '\0'))
+		return;
+
+	append_format_string(tree, sub_fmt);
+	param = new_object(ObjTypeString, object_name);
+	param->value.string = value;
+	append_premade_object(tree, param);
+}
+
+/*
+ * Similar to format_type_extended, except we return each bit of information
+ * separately:
+ *
+ * - nspid is the schema OID.  For certain SQL-standard types which have weird
+ *   typmod rules, we return InvalidOid; the caller is expected to not schema-
+ *   qualify the name nor add quotes to the type name in this case.
+ *
+ * - typname is set to the type name, without quotes
+ *
+ * - typemodstr is set to the typemod, if any, as a string with parentheses
+ *
+ * - typarray indicates whether []s must be added
+ *
+ * We don't try to decode type names to their standard-mandated names, except
+ * in the cases of types with unusual typmod rules.
+ */
+static void
+format_type_detailed(Oid type_oid, int32 typemod,
+					 Oid *nspid, char **typename, char **typemodstr,
+					 bool *typearray)
+{
+	HeapTuple	tuple;
+	Form_pg_type typeform;
+	Oid			array_base_type;
+
+	tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_oid));
+	if (!HeapTupleIsValid(tuple))
+		elog(ERROR, "cache lookup failed for type with OID %u", type_oid);
+
+	typeform = (Form_pg_type) GETSTRUCT(tuple);
+
+	/*
+	 * Check if it's a regular (variable length) array type.  As above,
+	 * fixed-length array types such as "name" shouldn't get deconstructed.
+	 */
+	array_base_type = typeform->typelem;
+
+	*typearray = (IsTrueArrayType(typeform) && typeform->typstorage != TYPSTORAGE_PLAIN);
+
+	if (*typearray)
+	{
+		/* Switch our attention to the array element type */
+		ReleaseSysCache(tuple);
+		tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(array_base_type));
+		if (!HeapTupleIsValid(tuple))
+			elog(ERROR, "cache lookup failed for type with OID %u", type_oid);
+
+		typeform = (Form_pg_type) GETSTRUCT(tuple);
+		type_oid = array_base_type;
+	}
+
+	/*
+	 * Special-case crock for types with strange typmod rules where we put
+	 * typemod at the middle of name (e.g. TIME(6) with time zone). We cannot
+	 * schema-qualify nor add quotes to the type name in these cases.
+	 */
+	*nspid = InvalidOid;
+
+	switch (type_oid)
+	{
+		case INTERVALOID:
+			*typename = pstrdup("INTERVAL");
+			break;
+		case TIMESTAMPTZOID:
+			if (typemod < 0)
+				*typename = pstrdup("TIMESTAMP WITH TIME ZONE");
+			else
+				/* otherwise, WITH TZ is added by typmod. */
+				*typename = pstrdup("TIMESTAMP");
+			break;
+		case TIMESTAMPOID:
+			*typename = pstrdup("TIMESTAMP");
+			break;
+		case TIMETZOID:
+			if (typemod < 0)
+				*typename = pstrdup("TIME WITH TIME ZONE");
+			else
+				/* otherwise, WITH TZ is added by typmod. */
+				*typename = pstrdup("TIME");
+			break;
+		case TIMEOID:
+			*typename = pstrdup("TIME");
+			break;
+		default:
+
+			/*
+			 * No additional processing is required for other types, so get
+			 * the type name and schema directly from the catalog.
+			 */
+			*nspid = typeform->typnamespace;
+			*typename = pstrdup(NameStr(typeform->typname));
+	}
+
+	if (typemod >= 0)
+		*typemodstr = printTypmod("", typemod, typeform->typmodout);
+	else
+		*typemodstr = pstrdup("");
+
+	ReleaseSysCache(tuple);
+}
+
+/*
+ * Return the string representation of the given RELPERSISTENCE value.
+ */
+static char *
+get_persistence_str(char persistence)
+{
+	switch (persistence)
+	{
+		case RELPERSISTENCE_TEMP:
+			return "TEMPORARY";
+		case RELPERSISTENCE_UNLOGGED:
+			return "UNLOGGED";
+		case RELPERSISTENCE_PERMANENT:
+			return "";
+		default:
+			elog(ERROR, "unexpected persistence marking %c", persistence);
+			return "";			/* make compiler happy */
+	}
+}
+
+/*
+ * Return the string representation of the given storagetype value.
+ */
+static inline char *
+get_type_storage(char storagetype)
+{
+	switch (storagetype)
+	{
+		case 'p':
+			return "plain";
+		case 'e':
+			return "external";
+		case 'x':
+			return "extended";
+		case 'm':
+			return "main";
+		default:
+			elog(ERROR, "invalid storage specifier %c", storagetype);
+	}
+}
+
+/*
+ * Allocate a new parameter.
+ */
+static ObjElem *
+new_object(ObjType type, char *name)
+{
+	ObjElem    *param;
+
+	param = palloc0(sizeof(ObjElem));
+	param->name = name;
+	param->objtype = type;
+
+	return param;
+}
+
+/*
+ * Allocate a new object parameter.
+ */
+static ObjElem *
+new_object_object(ObjTree *value)
+{
+	ObjElem    *param;
+
+	param = new_object(ObjTypeObject, NULL);
+	param->value.object = value;
+
+	return param;
+}
+
+/*
+ * Allocate a new object tree to store parameter values.
+ */
+static ObjTree *
+new_objtree(char *fmt)
+{
+	ObjTree    *params;
+
+	params = palloc0(sizeof(ObjTree));
+	params->present = true;
+	slist_init(&params->params);
+
+	if (fmt)
+	{
+		params->fmtinfo = makeStringInfo();
+		appendStringInfoString(params->fmtinfo, fmt);
+	}
+
+	return params;
+}
+
+/*
+ * A helper routine to set up %{}D and %{}O elements.
+ *
+ * Elements "schema_name" and "obj_name" are set.  If the namespace OID
+ * corresponds to a temp schema, that's set to "pg_temp".
+ *
+ * The difference between those two element types is whether the obj_name will
+ * be quoted as an identifier or not, which is not something that this routine
+ * concerns itself with; that will be up to the expand function.
+ */
+static ObjTree *
+new_objtree_for_qualname(Oid nspid, char *name)
+{
+	ObjTree    *qualified;
+	char	   *namespace;
+
+	if (isAnyTempNamespace(nspid))
+		namespace = pstrdup("pg_temp");
+	else
+		namespace = get_namespace_name(nspid);
+
+	qualified = new_objtree_VA(NULL, 2,
+							   "schemaname", ObjTypeString, namespace,
+							   "objname", ObjTypeString, pstrdup(name));
+
+	return qualified;
+}
+
+/*
+ * A helper routine to set up %{}D and %{}O elements, with the object specified
+ * by classId/objId.
+ */
+static ObjTree *
+new_objtree_for_qualname_id(Oid classId, Oid objectId)
+{
+	ObjTree    *qualified;
+	Relation	catalog;
+	HeapTuple	catobj;
+	Datum		obj_nsp;
+	Datum		obj_name;
+	AttrNumber	Anum_name;
+	AttrNumber	Anum_namespace;
+	AttrNumber	Anum_oid = get_object_attnum_oid(classId);
+	bool		isnull;
+
+	catalog = table_open(classId, AccessShareLock);
+
+	catobj = get_catalog_object_by_oid(catalog, Anum_oid, objectId);
+	if (!catobj)
+		elog(ERROR, "cache lookup failed for object with OID %u of catalog \"%s\"",
+			 objectId, RelationGetRelationName(catalog));
+	Anum_name = get_object_attnum_name(classId);
+	Anum_namespace = get_object_attnum_namespace(classId);
+
+	obj_nsp = heap_getattr(catobj, Anum_namespace, RelationGetDescr(catalog),
+						  &isnull);
+	if (isnull)
+		elog(ERROR, "null namespace for object %u", objectId);
+
+	obj_name = heap_getattr(catobj, Anum_name, RelationGetDescr(catalog),
+						   &isnull);
+	if (isnull)
+		elog(ERROR, "null attribute name for object %u", objectId);
+
+	qualified = new_objtree_for_qualname(DatumGetObjectId(obj_nsp),
+										 NameStr(*DatumGetName(obj_name)));
+	table_close(catalog, AccessShareLock);
+
+	return qualified;
+}
+
+/*
+ * A helper routine to setup %{}T elements.
+ */
+static ObjTree *
+new_objtree_for_type(Oid typeId, int32 typmod)
+{
+	Oid			typnspid;
+	char	   *type_nsp;
+	char	   *type_name = NULL;
+	char	   *typmodstr;
+	bool		type_array;
+
+	format_type_detailed(typeId, typmod,
+						 &typnspid, &type_name, &typmodstr, &type_array);
+
+	if (OidIsValid(typnspid))
+		type_nsp = get_namespace_name_or_temp(typnspid);
+	else
+		type_nsp = pstrdup("");
+
+	return new_objtree_VA(NULL, 4,
+						  "schemaname", ObjTypeString, type_nsp,
+						  "typename", ObjTypeString, type_name,
+						  "typmod", ObjTypeString, typmodstr,
+						  "typarray", ObjTypeBool, type_array);
+}
+
+/*
+ * Allocate a new object tree to store parameter values -- varargs version.
+ *
+ * The "fmt" argument is used to append as a "fmt" element in the output blob.
+ * numobjs indicates the number of extra elements to append; for each one, a
+ * name (string), type (from the ObjType enum) and value must be supplied.  The
+ * value must match the type given; for instance, ObjTypeInteger requires an
+ * int64, ObjTypeString requires a char *, ObjTypeArray requires a list (of
+ * ObjElem), ObjTypeObject requires an ObjTree, and so on.  Each element type *
+ * must match the conversion specifier given in the format string, as described
+ * in ddl_deparse_expand_command, q.v.
+ *
+ * Note we don't have the luxury of sprintf-like compiler warnings for
+ * malformed argument lists.
+ */
+static ObjTree *
+new_objtree_VA(char *fmt, int numobjs,...)
+{
+	ObjTree    *tree;
+	va_list		args;
+	int			i;
+
+	/* Set up the toplevel object and its "fmt" */
+	tree = new_objtree(fmt);
+
+	/* And process the given varargs */
+	va_start(args, numobjs);
+	for (i = 0; i < numobjs; i++)
+	{
+		char	   *name;
+		ObjType		type;
+		ObjElem    *elem;
+
+		name = va_arg(args, char *);
+		type = va_arg(args, ObjType);
+		elem = new_object(type, NULL);
+
+		/*
+		 * For all param types other than ObjTypeNull, there must be a value in
+		 * the varargs. Fetch it and add the fully formed subobject into the
+		 * main object.
+		 */
+		switch (type)
+		{
+			case ObjTypeNull:
+				/* Null params don't have a value (obviously) */
+				break;
+			case ObjTypeBool:
+				elem->value.boolean = va_arg(args, int);
+				break;
+			case ObjTypeString:
+				elem->value.string = va_arg(args, char *);
+				break;
+			case ObjTypeArray:
+				elem->value.array = va_arg(args, List *);
+				break;
+			case ObjTypeInteger:
+				elem->value.integer = va_arg(args, int);
+				break;
+			case ObjTypeFloat:
+				elem->value.flt = va_arg(args, double);
+				break;
+			case ObjTypeObject:
+				elem->value.object = va_arg(args, ObjTree *);
+				break;
+			default:
+				elog(ERROR, "invalid ObjTree element type %d", type);
+		}
+
+		elem->name = name;
+		append_premade_object(tree, elem);
+	}
+
+	va_end(args);
+	return tree;
+}
+
+/*
+ * Process the pre-built format string from the ObjTree into the output parse
+ * state.
+ */
+static void
+objtree_fmt_to_jsonb_element(JsonbParseState *state, ObjTree *tree)
+{
+	JsonbValue	key;
+	JsonbValue	val;
+
+	if (tree->fmtinfo == NULL)
+		return;
+
+	/* Push the key first */
+	key.type = jbvString;
+	key.val.string.val = "fmt";
+	key.val.string.len = strlen(key.val.string.val);
+	pushJsonbValue(&state, WJB_KEY, &key);
+
+	/* Then process the pre-built format string */
+	val.type = jbvString;
+	val.val.string.len = tree->fmtinfo->len;
+	val.val.string.val = tree->fmtinfo->data;
+	pushJsonbValue(&state, WJB_VALUE, &val);
+}
+
+/*
+ * Create a JSONB representation from an ObjTree.
+ */
+static Jsonb *
+objtree_to_jsonb(ObjTree *tree)
+{
+	JsonbValue *value;
+
+	value = objtree_to_jsonb_rec(tree, NULL);
+	return JsonbValueToJsonb(value);
+}
+
+/*
+ * Helper for objtree_to_jsonb: process an individual element from an object or
+ * an array into the output parse state.
+ */
+static void
+objtree_to_jsonb_element(JsonbParseState *state, ObjElem *object,
+						 JsonbIteratorToken elem_token)
+{
+	JsonbValue	val;
+
+	switch (object->objtype)
+	{
+		case ObjTypeNull:
+			val.type = jbvNull;
+			pushJsonbValue(&state, elem_token, &val);
+			break;
+
+		case ObjTypeString:
+			val.type = jbvString;
+			val.val.string.len = strlen(object->value.string);
+			val.val.string.val = object->value.string;
+			pushJsonbValue(&state, elem_token, &val);
+			break;
+
+		case ObjTypeInteger:
+			val.type = jbvNumeric;
+			val.val.numeric = (Numeric)
+				DatumGetNumeric(DirectFunctionCall1(int8_numeric,
+													object->value.integer));
+			pushJsonbValue(&state, elem_token, &val);
+			break;
+
+		case ObjTypeFloat:
+			val.type = jbvNumeric;
+			val.val.numeric = (Numeric)
+				DatumGetNumeric(DirectFunctionCall1(float8_numeric,
+													object->value.integer));
+			pushJsonbValue(&state, elem_token, &val);
+			break;
+
+		case ObjTypeBool:
+			val.type = jbvBool;
+			val.val.boolean = object->value.boolean;
+			pushJsonbValue(&state, elem_token, &val);
+			break;
+
+		case ObjTypeObject:
+			/* Recursively add the object into the existing parse state */
+			objtree_to_jsonb_rec(object->value.object, state);
+			break;
+
+		case ObjTypeArray:
+			{
+				ListCell   *cell;
+
+				pushJsonbValue(&state, WJB_BEGIN_ARRAY, NULL);
+				foreach(cell, object->value.array)
+				{
+					ObjElem    *elem = lfirst(cell);
+
+					objtree_to_jsonb_element(state, elem, WJB_ELEM);
+				}
+				pushJsonbValue(&state, WJB_END_ARRAY, NULL);
+			}
+			break;
+
+		default:
+			elog(ERROR, "unrecognized object type %d", object->objtype);
+			break;
+	}
+}
+
+/*
+ * Recursive helper for objtree_to_jsonb.
+ */
+static JsonbValue *
+objtree_to_jsonb_rec(ObjTree *tree, JsonbParseState *state)
+{
+	slist_iter	iter;
+
+	pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
+
+	objtree_fmt_to_jsonb_element(state, tree);
+
+	slist_foreach(iter, &tree->params)
+	{
+		ObjElem    *object = slist_container(ObjElem, node, iter.cur);
+		JsonbValue	key;
+
+		/* Push the key first */
+		key.type = jbvString;
+		key.val.string.len = strlen(object->name);
+		key.val.string.val = object->name;
+		pushJsonbValue(&state, WJB_KEY, &key);
+
+		/* Then process the value according to its type */
+		objtree_to_jsonb_element(state, object, WJB_VALUE);
+	}
+
+	return pushJsonbValue(&state, WJB_END_OBJECT, NULL);
+}
+
+/*
+ * Subroutine for CREATE TABLE/CREATE DOMAIN deparsing.
+ *
+ * Given a table OID or domain OID, obtain its constraints and append them to
+ * the given elements list.  The updated list is returned.
+ *
+ * This works for typed tables, regular tables, and domains.
+ *
+ * Note that CONSTRAINT_FOREIGN constraints are always ignored.
+ */
+static List *
+obtainConstraints(List *elements, Oid relationId, Oid domainId)
+{
+	Relation	conRel;
+	ScanKeyData key;
+	SysScanDesc scan;
+	HeapTuple	tuple;
+	ObjTree    *constr;
+
+	/* Only one may be valid */
+	Assert(OidIsValid(relationId) ^ OidIsValid(domainId));
+
+	/*
+	 * Scan pg_constraint to fetch all constraints linked to the given
+	 * relation.
+	 */
+	conRel = table_open(ConstraintRelationId, AccessShareLock);
+	if (OidIsValid(relationId))
+	{
+		ScanKeyInit(&key,
+					Anum_pg_constraint_conrelid,
+					BTEqualStrategyNumber, F_OIDEQ,
+					ObjectIdGetDatum(relationId));
+		scan = systable_beginscan(conRel, ConstraintRelidTypidNameIndexId,
+								  true, NULL, 1, &key);
+	}
+	else
+	{
+		ScanKeyInit(&key,
+					Anum_pg_constraint_contypid,
+					BTEqualStrategyNumber, F_OIDEQ,
+					ObjectIdGetDatum(domainId));
+		scan = systable_beginscan(conRel, ConstraintTypidIndexId,
+								  true, NULL, 1, &key);
+	}
+
+	/*
+	 * For each constraint, add a node to the list of table elements.  In
+	 * these nodes we include not only the printable information ("fmt"), but
+	 * also separate attributes to indicate the type of constraint, for
+	 * automatic processing.
+	 */
+	while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+	{
+		Form_pg_constraint constrForm;
+		char	   *contype;
+
+		constrForm = (Form_pg_constraint) GETSTRUCT(tuple);
+
+		switch (constrForm->contype)
+		{
+			case CONSTRAINT_CHECK:
+				contype = "check";
+				break;
+			case CONSTRAINT_FOREIGN:
+				continue;		/* not here */
+			case CONSTRAINT_PRIMARY:
+				contype = "primary key";
+				break;
+			case CONSTRAINT_UNIQUE:
+				contype = "unique";
+				break;
+			case CONSTRAINT_TRIGGER:
+				contype = "trigger";
+				break;
+			case CONSTRAINT_EXCLUSION:
+				contype = "exclusion";
+				break;
+			default:
+				elog(ERROR, "unrecognized constraint type");
+		}
+
+		/*
+		 * "type" and "contype" are not part of the printable output, but are
+		 * useful to programmatically distinguish these from columns and among
+		 * different constraint types.
+		 *
+		 * XXX it might be useful to also list the column names in a PK, etc.
+		 */
+		constr = new_objtree_VA("CONSTRAINT %{name}I %{definition}s", 4,
+								"type", ObjTypeString, "constraint",
+								"contype", ObjTypeString, contype,
+								"name", ObjTypeString, NameStr(constrForm->conname),
+								"definition", ObjTypeString,
+								pg_get_constraintdef_string(constrForm->oid));
+		elements = lappend(elements, new_object_object(constr));
+	}
+
+	systable_endscan(scan);
+	table_close(conRel, AccessShareLock);
+
+	return elements;
+}
+
+/*
+ * Return an index definition, split into several pieces.
+ *
+ * A large amount of code is duplicated from  pg_get_indexdef_worker, but
+ * control flow is different enough that it doesn't seem worth keeping them
+ * together.
+ */
+static void
+pg_get_indexdef_detailed(Oid indexrelid,
+						 char **index_am,
+						 char **definition,
+						 char **reloptions,
+						 char **tablespace,
+						 char **whereClause)
+{
+	HeapTuple	ht_idx;
+	HeapTuple	ht_idxrel;
+	HeapTuple	ht_am;
+	Form_pg_index idxrec;
+	Form_pg_class idxrelrec;
+	Form_pg_am	amrec;
+	IndexAmRoutine *amroutine;
+	List	   *indexprs;
+	ListCell   *indexpr_item;
+	List	   *context;
+	Oid			indrelid;
+	int			keyno;
+	Datum		indcollDatum;
+	Datum		indclassDatum;
+	Datum		indoptionDatum;
+	bool		isnull;
+	oidvector  *indcollation;
+	oidvector  *indclass;
+	int2vector *indoption;
+	StringInfoData definitionBuf;
+
+	*tablespace = NULL;
+	*whereClause = NULL;
+
+	/* Fetch the pg_index tuple by the Oid of the index */
+	ht_idx = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexrelid));
+	if (!HeapTupleIsValid(ht_idx))
+		elog(ERROR, "cache lookup failed for index with OID %u", indexrelid);
+	idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
+
+	indrelid = idxrec->indrelid;
+	Assert(indexrelid == idxrec->indexrelid);
+
+	/* Must get indcollation, indclass, and indoption the hard way */
+	indcollDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
+								   Anum_pg_index_indcollation, &isnull);
+	Assert(!isnull);
+	indcollation = (oidvector *) DatumGetPointer(indcollDatum);
+
+	indclassDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
+									Anum_pg_index_indclass, &isnull);
+	Assert(!isnull);
+	indclass = (oidvector *) DatumGetPointer(indclassDatum);
+
+	indoptionDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
+									 Anum_pg_index_indoption, &isnull);
+	Assert(!isnull);
+	indoption = (int2vector *) DatumGetPointer(indoptionDatum);
+
+	/* Fetch the pg_class tuple of the index relation */
+	ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexrelid));
+	if (!HeapTupleIsValid(ht_idxrel))
+		elog(ERROR, "cache lookup failed for relation with OID %u", indexrelid);
+	idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
+
+	/* Fetch the pg_am tuple of the index' access method */
+	ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
+	if (!HeapTupleIsValid(ht_am))
+		elog(ERROR, "cache lookup failed for access method with OID %u",
+			 idxrelrec->relam);
+	amrec = (Form_pg_am) GETSTRUCT(ht_am);
+
+	/*
+	 * Get the index expressions, if any.  (NOTE: we do not use the relcache
+	 * versions of the expressions and predicate, because we want to display
+	 * non-const-folded expressions.)
+	 */
+	if (!heap_attisnull(ht_idx, Anum_pg_index_indexprs, NULL))
+	{
+		Datum		exprsDatum;
+		char	   *exprsString;
+
+		exprsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
+									 Anum_pg_index_indexprs, &isnull);
+		Assert(!isnull);
+		exprsString = TextDatumGetCString(exprsDatum);
+		indexprs = (List *) stringToNode(exprsString);
+		pfree(exprsString);
+	}
+	else
+		indexprs = NIL;
+
+	indexpr_item = list_head(indexprs);
+
+	context = deparse_context_for(get_rel_name(indrelid), indrelid);
+
+	initStringInfo(&definitionBuf);
+
+	/* Output index AM */
+	*index_am = pstrdup(quote_identifier(NameStr(amrec->amname)));
+
+	/* Fetch the index AM's API struct */
+	amroutine = GetIndexAmRoutine(amrec->amhandler);
+
+	/*
+	 * Output index definition.  Note the outer parens must be supplied by
+	 * caller.
+	 */
+	appendStringInfoString(&definitionBuf, "(");
+	for (keyno = 0; keyno < idxrec->indnatts; keyno++)
+	{
+		AttrNumber	attnum = idxrec->indkey.values[keyno];
+		int16		opt = indoption->values[keyno];
+		Oid			keycoltype;
+		Oid			keycolcollation;
+
+		/* Print INCLUDE to divide key and non-key attrs. */
+		if (keyno == idxrec->indnkeyatts)
+		{
+			appendStringInfoString(&definitionBuf, ") INCLUDE (");
+		}
+		else
+			appendStringInfoString(&definitionBuf, keyno == 0 ? "" : ", ");
+
+		if (attnum != 0)
+		{
+			/* Simple index column */
+			char	   *attname;
+			int32		keycoltypmod;
+
+			attname = get_attname(indrelid, attnum, false);
+			appendStringInfoString(&definitionBuf, quote_identifier(attname));
+			get_atttypetypmodcoll(indrelid, attnum,
+								  &keycoltype, &keycoltypmod,
+								  &keycolcollation);
+		}
+		else
+		{
+			/* Expressional index */
+			Node	   *indexkey;
+			char	   *str;
+
+			if (indexpr_item == NULL)
+				elog(ERROR, "too few entries in indexprs list");
+			indexkey = (Node *) lfirst(indexpr_item);
+			indexpr_item = lnext(indexprs, indexpr_item);
+
+			/* Deparse */
+			str = deparse_expression(indexkey, context, false, false);
+
+			/* Need parens if it's not a bare function call */
+			if (indexkey && IsA(indexkey, FuncExpr) &&
+				((FuncExpr *) indexkey)->funcformat == COERCE_EXPLICIT_CALL)
+				appendStringInfoString(&definitionBuf, str);
+			else
+				appendStringInfo(&definitionBuf, "(%s)", str);
+
+			keycoltype = exprType(indexkey);
+			keycolcollation = exprCollation(indexkey);
+		}
+
+		/* Print additional decoration for (selected) key columns, even if default */
+		if (keyno < idxrec->indnkeyatts)
+		{
+			Oid indcoll = indcollation->values[keyno];
+			if (OidIsValid(indcoll))
+				appendStringInfo(&definitionBuf, " COLLATE %s",
+								generate_collation_name((indcoll)));
+
+			/* Add the operator class name, even if default */
+			get_opclass_name(indclass->values[keyno], InvalidOid, &definitionBuf);
+
+			/* Add options if relevant */
+			if (amroutine->amcanorder)
+			{
+				/* If it supports sort ordering, report DESC and NULLS opts */
+				if (opt & INDOPTION_DESC)
+				{
+					appendStringInfoString(&definitionBuf, " DESC");
+					/* NULLS FIRST is the default in this case */
+					if (!(opt & INDOPTION_NULLS_FIRST))
+						appendStringInfoString(&definitionBuf, " NULLS LAST");
+				}
+				else
+				{
+					if (opt & INDOPTION_NULLS_FIRST)
+						appendStringInfoString(&definitionBuf, " NULLS FIRST");
+				}
+			}
+
+			/* XXX excludeOps thingy was here; do we need anything? */
+		}
+	}
+	appendStringInfoString(&definitionBuf, ")");
+	*definition = definitionBuf.data;
+
+	/* Output reloptions */
+	*reloptions = flatten_reloptions(indexrelid);
+
+	/* Output tablespace */
+	{
+		Oid			tblspc;
+
+		tblspc = get_rel_tablespace(indexrelid);
+		if (OidIsValid(tblspc))
+			*tablespace = pstrdup(quote_identifier(get_tablespace_name(tblspc)));
+	}
+
+	/* Report index predicate, if any */
+	if (!heap_attisnull(ht_idx, Anum_pg_index_indpred, NULL))
+	{
+		Node	   *node;
+		Datum		predDatum;
+		char	   *predString;
+
+		/* Convert text string to node tree */
+		predDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
+									Anum_pg_index_indpred, &isnull);
+		Assert(!isnull);
+		predString = TextDatumGetCString(predDatum);
+		node = (Node *) stringToNode(predString);
+		pfree(predString);
+
+		/* Deparse */
+		*whereClause = deparse_expression(node, context, false, false);
+	}
+
+	/* Clean up */
+	ReleaseSysCache(ht_idx);
+	ReleaseSysCache(ht_idxrel);
+	ReleaseSysCache(ht_am);
+}
+
+/*
+ * Obtain the deparsed default value for the given column of the given table.
+ *
+ * Caller must have set a correct deparse context.
+ */
+static char *
+RelationGetColumnDefault(Relation rel, AttrNumber attno, List *dpcontext,
+						 List **exprs)
+{
+	Node	   *defval;
+	char	   *defstr;
+
+	defval = build_column_default(rel, attno);
+	defstr = deparse_expression(defval, dpcontext, false, false);
+
+	/* Collect the expression for later replication safety checks */
+	if (exprs)
+		*exprs = lappend(*exprs, defval);
+
+	return defstr;
+}
+
+/*
+ * Obtain the deparsed partition bound expression for the given table.
+ */
+static char *
+RelationGetPartitionBound(Oid relid)
+{
+	Datum		deparsed;
+	Datum		boundDatum;
+	bool		isnull;
+	HeapTuple	tuple;
+
+	tuple = SearchSysCache1(RELOID, relid);
+	if (!HeapTupleIsValid(tuple))
+		elog(ERROR, "cache lookup failed for relation with OID %u", relid);
+
+	boundDatum = SysCacheGetAttr(RELOID, tuple,
+								 Anum_pg_class_relpartbound,
+								 &isnull);
+
+	deparsed = DirectFunctionCall2(pg_get_expr,
+								   CStringGetTextDatum(TextDatumGetCString(boundDatum)),
+								   relid);
+
+	ReleaseSysCache(tuple);
+
+	return TextDatumGetCString(deparsed);
+}
+
+/*
+ * Deparse a ColumnDef node within a regular (non-typed) table creation.
+ *
+ * NOT NULL constraints in the column definition are emitted directly in the
+ * column definition by this routine; other constraints must be emitted
+ * elsewhere (the info in the parse node is incomplete anyway).
+ *
+ * Verbose syntax
+ * %{name}I %{coltype}T %{compression}s %{default}s %{not_null}s %{collation}s
+ */
+static ObjTree *
+deparse_ColumnDef(Relation relation, List *dpcontext, bool composite,
+				  ColumnDef *coldef, bool is_alter, List **exprs)
+{
+	ObjTree    *ret;
+	ObjTree    *tmp_obj;
+	Oid			relid = RelationGetRelid(relation);
+	HeapTuple	attrTup;
+	Form_pg_attribute attrForm;
+	Oid			typid;
+	int32		typmod;
+	Oid			typcollation;
+	bool		saw_notnull;
+	ListCell   *cell;
+
+	/*
+	 * Inherited columns without local definitions must not be emitted.
+	 *
+	 * XXX maybe it is useful to have them with "present = false" or some
+	 * such?
+	 */
+	if (!coldef->is_local)
+		return NULL;
+
+	attrTup = SearchSysCacheAttName(relid, coldef->colname);
+	if (!HeapTupleIsValid(attrTup))
+		elog(ERROR, "could not find cache entry for column \"%s\" of relation %u",
+			 coldef->colname, relid);
+	attrForm = (Form_pg_attribute) GETSTRUCT(attrTup);
+
+	get_atttypetypmodcoll(relid, attrForm->attnum,
+						  &typid, &typmod, &typcollation);
+
+	ret = new_objtree_VA("%{name}I %{coltype}T", 3,
+						 "type", ObjTypeString, "column",
+						 "name", ObjTypeString, coldef->colname,
+						 "coltype", ObjTypeObject,
+						 new_objtree_for_type(typid, typmod));
+
+	if (!composite)
+		append_string_object(ret, "STORAGE %{colstorage}s", "colstorage",
+							 get_type_storage(attrForm->attstorage));
+
+	/* USING clause */
+	tmp_obj = new_objtree("COMPRESSION");
+	if (coldef->compression)
+		append_string_object(tmp_obj, "%{compression_method}I",
+							 "compression_method", coldef->compression);
+	else
+	{
+		append_null_object(tmp_obj, "%{compression_method}I");
+		append_not_present(tmp_obj);
+	}
+	append_object_object(ret, "%{compression}s", tmp_obj);
+
+	tmp_obj = new_objtree("COLLATE");
+	if (OidIsValid(typcollation))
+		append_object_object(tmp_obj, "%{name}D",
+							 new_objtree_for_qualname_id(CollationRelationId,
+														 typcollation));
+	else
+		append_not_present(tmp_obj);
+	append_object_object(ret, "%{collation}s", tmp_obj);
+
+	if (!composite)
+	{
+		Oid			seqrelid = InvalidOid;
+
+		/*
+		 * Emit a NOT NULL declaration if necessary.  Note that we cannot
+		 * trust pg_attribute.attnotnull here, because that bit is also set
+		 * when primary keys are specified; we must not emit a NOT NULL
+		 * constraint in that case, unless explicitly specified.  Therefore,
+		 * we scan the list of constraints attached to this column to
+		 * determine whether we need to emit anything. (Fortunately, NOT NULL
+		 * constraints cannot be table constraints.)
+		 *
+		 * In the ALTER TABLE cases, we also add a NOT NULL if the colDef is
+		 * marked is_not_null.
+		 */
+		saw_notnull = false;
+		foreach(cell, coldef->constraints)
+		{
+			Constraint *constr = (Constraint *) lfirst(cell);
+
+			if (constr->contype == CONSTR_NOTNULL)
+			{
+				saw_notnull = true;
+				break;
+			}
+		}
+
+		if (is_alter && coldef->is_not_null)
+			saw_notnull = true;
+
+		append_string_object(ret, "%{not_null}s", "not_null",
+							 saw_notnull ? "NOT NULL" : "");
+
+		tmp_obj = new_objtree("DEFAULT");
+		if (attrForm->atthasdef &&
+			coldef->generated != ATTRIBUTE_GENERATED_STORED)
+		{
+			char	   *defstr;
+
+			defstr = RelationGetColumnDefault(relation, attrForm->attnum,
+											  dpcontext, exprs);
+
+			append_string_object(tmp_obj, "%{default}s", "default", defstr);
+		}
+		else
+			append_not_present(tmp_obj);
+		append_object_object(ret, "%{default}s", tmp_obj);
+
+		/* IDENTITY COLUMN */
+		if (coldef->identity)
+		{
+			Oid			attno = get_attnum(relid, coldef->colname);
+
+			seqrelid = getIdentitySequence(relid, attno, true);
+			if (OidIsValid(seqrelid) && coldef->identitySequence)
+				seqrelid = RangeVarGetRelid(coldef->identitySequence, NoLock, false);
+		}
+
+		if (OidIsValid(seqrelid))
+		{
+			tmp_obj = deparse_ColumnIdentity(seqrelid, coldef->identity, is_alter);
+			append_object_object(ret, "%{identity_column}s", tmp_obj);
+		}
+
+		/* GENERATED COLUMN EXPRESSION */
+		tmp_obj = new_objtree("GENERATED ALWAYS AS");
+		if (coldef->generated == ATTRIBUTE_GENERATED_STORED)
+		{
+			char	   *defstr;
+
+			defstr = RelationGetColumnDefault(relation, attrForm->attnum,
+											  dpcontext, exprs);
+			append_string_object(tmp_obj, "(%{generation_expr}s) STORED",
+								 "generation_expr", defstr);
+		}
+		else
+			append_not_present(tmp_obj);
+
+		append_object_object(ret, "%{generated_column}s", tmp_obj);
+	}
+
+	ReleaseSysCache(attrTup);
+
+	return ret;
+}
+
+/*
+ * Deparse a ColumnDef node within a typed table creation.	This is simpler
+ * than the regular case, because we don't have to emit the type declaration,
+ * collation, or default.  Here we only return something if the column is being
+ * declared NOT NULL.
+ *
+ * As in deparse_ColumnDef, any other constraint is processed elsewhere.
+ *
+ * Verbose syntax
+ * %{name}I WITH OPTIONS %{not_null}s %{default}s.
+ */
+static ObjTree *
+deparse_ColumnDef_typed(Relation relation, List *dpcontext, ColumnDef *coldef)
+{
+	ObjTree    *ret = NULL;
+	ObjTree    *tmp_obj;
+	Oid			relid = RelationGetRelid(relation);
+	HeapTuple	attrTup;
+	Form_pg_attribute attrForm;
+	Oid			typid;
+	int32		typmod;
+	Oid			typcollation;
+	bool		saw_notnull;
+	ListCell   *cell;
+
+	attrTup = SearchSysCacheAttName(relid, coldef->colname);
+	if (!HeapTupleIsValid(attrTup))
+		elog(ERROR, "could not find cache entry for column \"%s\" of relation %u",
+			 coldef->colname, relid);
+	attrForm = (Form_pg_attribute) GETSTRUCT(attrTup);
+
+	get_atttypetypmodcoll(relid, attrForm->attnum,
+						  &typid, &typmod, &typcollation);
+
+	/*
+	 * Search for a NOT NULL declaration. As in deparse_ColumnDef, we rely on
+	 * finding a constraint on the column rather than coldef->is_not_null.
+	 * (This routine is never used for ALTER cases.)
+	 */
+	saw_notnull = false;
+	foreach(cell, coldef->constraints)
+	{
+		Constraint *constr = (Constraint *) lfirst(cell);
+
+		if (constr->contype == CONSTR_NOTNULL)
+		{
+			saw_notnull = true;
+			break;
+		}
+	}
+
+	if (!saw_notnull && !attrForm->atthasdef)
+	{
+		ReleaseSysCache(attrTup);
+		return NULL;
+	}
+
+	tmp_obj = new_objtree("DEFAULT");
+	if (attrForm->atthasdef)
+	{
+		char	   *defstr;
+
+		defstr = RelationGetColumnDefault(relation, attrForm->attnum,
+										  dpcontext, NULL);
+
+		append_string_object(tmp_obj, "%{default}s", "default", defstr);
+	}
+	else
+		append_not_present(tmp_obj);
+
+	ret = new_objtree_VA("%{name}I WITH OPTIONS %{not_null}s %{default}s", 4,
+						 "type", ObjTypeString, "column",
+						 "name", ObjTypeString, coldef->colname,
+						 "not_null", ObjTypeString,
+						 saw_notnull ? "NOT NULL" : "",
+						 "default", ObjTypeObject, tmp_obj);
+
+	/* Generated columns are not supported on typed tables, so we are done */
+
+	ReleaseSysCache(attrTup);
+
+	return ret;
+}
+
+/*
+ * Deparse the definition of column identity.
+ *
+ * Verbose syntax
+ * SET GENERATED %{option}s %{identity_type}s %{seq_definition: }s
+ * 	OR
+ * GENERATED %{option}s AS IDENTITY %{identity_type}s ( %{seq_definition: }s )
+ */
+static ObjTree *
+deparse_ColumnIdentity(Oid seqrelid, char identity, bool alter_table)
+{
+	ObjTree    *ret;
+	ObjTree    *ident_obj;
+	List	   *elems = NIL;
+	Form_pg_sequence seqform;
+	Sequence_values *seqvalues;
+	char	   *identfmt;
+	char	   *objfmt;
+
+	if (alter_table)
+	{
+		identfmt = "SET GENERATED ";
+		objfmt = "%{option}s";
+	}
+	else
+	{
+		identfmt = "GENERATED ";
+		objfmt = "%{option}s AS IDENTITY";
+	}
+
+	ident_obj = new_objtree(identfmt);
+
+	if (identity == ATTRIBUTE_IDENTITY_ALWAYS)
+		append_string_object(ident_obj, objfmt, "option", "ALWAYS");
+	else if (identity == ATTRIBUTE_IDENTITY_BY_DEFAULT)
+		append_string_object(ident_obj, objfmt, "option", "BY DEFAULT");
+	else
+		append_not_present(ident_obj);
+
+	ret = new_objtree_VA("%{identity_type}s", 1,
+						 "identity_type", ObjTypeObject, ident_obj);
+
+	seqvalues = get_sequence_values(seqrelid);
+	seqform = seqvalues->seqform;
+
+	/* Definition elements */
+	elems = lappend(elems, deparse_Seq_Cache(seqform, alter_table));
+	elems = lappend(elems, deparse_Seq_Cycle(seqform, alter_table));
+	elems = lappend(elems, deparse_Seq_IncrementBy(seqform, alter_table));
+	elems = lappend(elems, deparse_Seq_Minvalue(seqform, alter_table));
+	elems = lappend(elems, deparse_Seq_Maxvalue(seqform, alter_table));
+	elems = lappend(elems, deparse_Seq_Startwith(seqform, alter_table));
+	elems = lappend(elems, deparse_Seq_Restart(seqvalues->last_value));
+	/* We purposefully do not emit OWNED BY here */
+
+	if (alter_table)
+		append_array_object(ret, "%{seq_definition: }s", elems);
+	else
+		append_array_object(ret, "( %{seq_definition: }s )", elems);
+
+	return ret;
+}
+
+/*
+ * ... ALTER COLUMN ... SET/RESET (...)
+ *
+ * Verbose syntax
+ * ALTER COLUMN %{column}I RESET|SET (%{options:, }s)
+ */
+static ObjTree *
+deparse_ColumnSetOptions(AlterTableCmd *subcmd)
+{
+	List	   *sets = NIL;
+	ListCell   *cell;
+	ObjTree    *ret;
+	bool		is_reset = subcmd->subtype == AT_ResetOptions;
+
+	ret = new_objtree_VA("ALTER COLUMN %{column}I %{option}s", 2,
+						 "column", ObjTypeString, subcmd->name,
+						 "option", ObjTypeString, is_reset ? "RESET" : "SET");
+
+	foreach(cell, (List *) subcmd->def)
+	{
+		DefElem    *elem;
+		ObjTree    *set;
+
+		elem = (DefElem *) lfirst(cell);
+		set = deparse_DefElem(elem, is_reset);
+		sets = lappend(sets, new_object_object(set));
+	}
+
+	Assert(sets);
+	append_array_object(ret, "(%{options:, }s)", sets);
+
+	return ret;
+}
+
+/*
+ * ... ALTER COLUMN ... SET/RESET (...)
+ *
+ * Verbose syntax
+ * RESET|SET (%{options:, }s)
+ */
+static ObjTree *
+deparse_RelSetOptions(AlterTableCmd *subcmd)
+{
+	List	   *sets = NIL;
+	ListCell   *cell;
+	bool		is_reset = subcmd->subtype == AT_ResetRelOptions;
+
+	foreach(cell, (List *) subcmd->def)
+	{
+		DefElem    *elem;
+		ObjTree    *set;
+
+		elem = (DefElem *) lfirst(cell);
+		set = deparse_DefElem(elem, is_reset);
+		sets = lappend(sets, new_object_object(set));
+	}
+
+	Assert(sets);
+
+	return new_objtree_VA("%{set_reset}s (%{options:, }s)", 2,
+						  "set_reset", ObjTypeString, is_reset ? "RESET" : "SET",
+						  "options", ObjTypeArray, sets);
+}
+
+/*
+ * Deparse DefElems, as used e.g. by ALTER COLUMN ... SET, into a list of SET
+ * (...)  or RESET (...) contents.
+ *
+ * Verbose syntax
+ * %{label}s = %{value}L
+ */
+static ObjTree *
+deparse_DefElem(DefElem *elem, bool is_reset)
+{
+	ObjTree    *ret;
+	ObjTree    *optname = new_objtree("");
+
+	if (elem->defnamespace != NULL)
+		append_string_object(optname, "%{schema}I.", "schema",
+							 elem->defnamespace);
+
+	append_string_object(optname, "%{label}I", "label", elem->defname);
+
+	ret = new_objtree_VA("%{label}s", 1,
+						 "label", ObjTypeObject, optname);
+
+	if (!is_reset)
+		append_string_object(ret, "= %{value}L", "value",
+							 elem->arg ? defGetString(elem) :
+							 defGetBoolean(elem) ? "TRUE" : "FALSE");
+
+	return ret;
+}
+
+/*
+ * Deparse the INHERITS relations.
+ *
+ * Given a table OID, return a schema-qualified table list representing
+ * the parent tables.
+ */
+static List *
+deparse_InhRelations(Oid objectId)
+{
+	List	   *parents = NIL;
+	Relation	inhRel;
+	SysScanDesc scan;
+	ScanKeyData key;
+	HeapTuple	tuple;
+
+	inhRel = table_open(InheritsRelationId, RowExclusiveLock);
+
+	ScanKeyInit(&key,
+				Anum_pg_inherits_inhrelid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(objectId));
+
+	scan = systable_beginscan(inhRel, InheritsRelidSeqnoIndexId,
+							  true, NULL, 1, &key);
+
+	while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+	{
+		ObjTree    *parent;
+		Form_pg_inherits formInh = (Form_pg_inherits) GETSTRUCT(tuple);
+
+		parent = new_objtree_for_qualname_id(RelationRelationId,
+											 formInh->inhparent);
+		parents = lappend(parents, new_object_object(parent));
+	}
+
+	systable_endscan(scan);
+	table_close(inhRel, RowExclusiveLock);
+
+	return parents;
+}
+
+/*
+ * Deparse the ON COMMIT ... clause for CREATE ... TEMPORARY ...
+ *
+ * Verbose syntax
+ * ON COMMIT %{on_commit_value}s
+ */
+static ObjTree *
+deparse_OnCommitClause(OnCommitAction option)
+{
+	ObjTree    *ret  = new_objtree("ON COMMIT");
+	switch (option)
+	{
+		case ONCOMMIT_DROP:
+			append_string_object(ret, "%{on_commit_value}s",
+								 "on_commit_value", "DROP");
+			break;
+
+		case ONCOMMIT_DELETE_ROWS:
+			append_string_object(ret, "%{on_commit_value}s",
+								 "on_commit_value", "DELETE ROWS");
+			break;
+
+		case ONCOMMIT_PRESERVE_ROWS:
+			append_string_object(ret, "%{on_commit_value}s",
+								 "on_commit_value", "PRESERVE ROWS");
+			break;
+
+		case ONCOMMIT_NOOP:
+			append_null_object(ret, "%{on_commit_value}s");
+			append_not_present(ret);
+			break;
+	}
+
+	return ret;
+}
+
+/*
+ * Deparse the sequence CACHE option.
+ *
+ * Verbose syntax
+ * SET CACHE %{value}s
+ * OR
+ * CACHE %{value}
+ */
+static inline ObjElem *
+deparse_Seq_Cache(Form_pg_sequence seqdata, bool alter_table)
+{
+	ObjTree    *ret;
+	char	   *tmpstr;
+	char	   *fmt;
+
+	fmt = alter_table ? "SET CACHE %{value}s" : "CACHE %{value}s";
+
+	tmpstr = psprintf(INT64_FORMAT, seqdata->seqcache);
+	ret = new_objtree_VA(fmt, 2,
+						 "clause", ObjTypeString, "cache",
+						 "value", ObjTypeString, tmpstr);
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the sequence CYCLE option.
+ *
+ * Verbose syntax
+ * SET %{no}s CYCLE
+ * OR
+ * %{no}s CYCLE
+ */
+static inline ObjElem *
+deparse_Seq_Cycle(Form_pg_sequence seqdata, bool alter_table)
+{
+	ObjTree    *ret;
+	char	   *fmt;
+
+	fmt = alter_table ? "SET %{no}s CYCLE" : "%{no}s CYCLE";
+
+	ret = new_objtree_VA(fmt, 2,
+						 "clause", ObjTypeString, "cycle",
+						 "no", ObjTypeString,
+						 seqdata->seqcycle ? "" : "NO");
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the sequence INCREMENT BY option.
+ *
+ * Verbose syntax
+ * SET INCREMENT BY %{value}s
+ * OR
+ * INCREMENT BY %{value}s
+ */
+static inline ObjElem *
+deparse_Seq_IncrementBy(Form_pg_sequence seqdata, bool alter_table)
+{
+	ObjTree    *ret;
+	char	   *tmpstr;
+	char	   *fmt;
+
+	fmt = alter_table ? "SET INCREMENT BY %{value}s" : "INCREMENT BY %{value}s";
+
+	tmpstr = psprintf(INT64_FORMAT, seqdata->seqincrement);
+	ret = new_objtree_VA(fmt, 2,
+						 "clause", ObjTypeString, "seqincrement",
+						 "value", ObjTypeString, tmpstr);
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the sequence MAXVALUE option.
+ *
+ * Verbose syntax
+ * SET MAXVALUE %{value}s
+ * OR
+ * MAXVALUE %{value}s
+ */
+static inline ObjElem *
+deparse_Seq_Maxvalue(Form_pg_sequence seqdata, bool alter_table)
+{
+	ObjTree    *ret;
+	char	   *tmpstr;
+	char	   *fmt;
+
+	fmt = alter_table ? "SET MAXVALUE %{value}s" : "MAXVALUE %{value}s";
+
+	tmpstr = psprintf(INT64_FORMAT, seqdata->seqmax);
+	ret = new_objtree_VA(fmt, 2,
+						 "clause", ObjTypeString, "maxvalue",
+						 "value", ObjTypeString, tmpstr);
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the sequence MINVALUE option.
+ *
+ * Verbose syntax
+ * SET MINVALUE %{value}s
+ * OR
+ * MINVALUE %{value}s
+ */
+static inline ObjElem *
+deparse_Seq_Minvalue(Form_pg_sequence seqdata, bool alter_table)
+{
+	ObjTree    *ret;
+	char	   *tmpstr;
+	char	   *fmt;
+
+	fmt = alter_table ? "SET MINVALUE %{value}s" : "MINVALUE %{value}s";
+
+	tmpstr = psprintf(INT64_FORMAT, seqdata->seqmin);
+	ret = new_objtree_VA(fmt, 2,
+						 "clause", ObjTypeString, "minvalue",
+						 "value", ObjTypeString, tmpstr);
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the sequence RESTART option.
+ *
+ * Verbose syntax
+ * RESTART %{value}s
+ */
+static inline ObjElem *
+deparse_Seq_Restart(int64 last_value)
+{
+	ObjTree    *ret;
+	char	   *tmpstr;
+
+	tmpstr = psprintf(INT64_FORMAT, last_value);
+	ret = new_objtree_VA("RESTART %{value}s", 2,
+						 "clause", ObjTypeString, "restart",
+						 "value", ObjTypeString, tmpstr);
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the sequence AS option.
+ *
+ * Verbose syntax
+ * AS %{seqtype}T
+ */
+static inline ObjElem *
+deparse_Seq_As(Form_pg_sequence seqdata)
+{
+	ObjTree    *ret;
+
+	ret = new_objtree("AS");
+	if (OidIsValid(seqdata->seqtypid))
+		append_object_object(ret, "%{seqtype}T",
+							 new_objtree_for_type(seqdata->seqtypid, -1));
+	else
+		append_not_present(ret);
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the sequence START WITH option.
+ *
+ * Verbose syntax
+ * SET START WITH %{value}s
+ * OR
+ * START WITH %{value}s
+ */
+static inline ObjElem *
+deparse_Seq_Startwith(Form_pg_sequence seqdata, bool alter_table)
+{
+	ObjTree    *ret;
+	char	   *tmpstr;
+	char	   *fmt;
+
+	fmt = alter_table ? "SET START WITH %{value}s" : "START WITH %{value}s";
+
+	tmpstr = psprintf(INT64_FORMAT, seqdata->seqstart);
+	ret = new_objtree_VA(fmt, 2,
+						 "clause", ObjTypeString, "start",
+						 "value", ObjTypeString, tmpstr);
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the type STORAGE option.
+ *
+ * Verbose syntax
+ * STORAGE=%{value}s
+ */
+static inline ObjElem *
+deparse_Type_Storage(Form_pg_type typForm)
+{
+	ObjTree    *ret;
+	ret = new_objtree_VA("STORAGE = %{value}s", 2,
+						 "clause", ObjTypeString, "storage",
+						 "value", ObjTypeString, get_type_storage(typForm->typstorage));
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the type RECEIVE option.
+ *
+ * Verbose syntax
+ * RECEIVE=%{procedure}D
+ */
+static inline ObjElem *
+deparse_Type_Receive(Form_pg_type typForm)
+{
+	ObjTree    *ret;
+
+	ret = new_objtree_VA("RECEIVE=", 1,
+						 "clause", ObjTypeString, "receive");
+	if (OidIsValid(typForm->typreceive))
+		append_object_object(ret, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 typForm->typreceive));
+	else
+		append_not_present(ret);
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the type SEND option.
+ *
+ * Verbose syntax
+ * SEND=%{procedure}D
+ */
+static inline ObjElem *
+deparse_Type_Send(Form_pg_type typForm)
+{
+	ObjTree    *ret;
+
+	ret = new_objtree_VA("SEND=", 1,
+						 "clause", ObjTypeString, "send");
+	if (OidIsValid(typForm->typsend))
+		append_object_object(ret, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 typForm->typsend));
+	else
+		append_not_present(ret);
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the type typmod_in option.
+ *
+ * Verbose syntax
+ * TYPMOD_IN=%{procedure}D
+ */
+static inline ObjElem *
+deparse_Type_Typmod_In(Form_pg_type typForm)
+{
+	ObjTree    *ret;
+
+	ret = new_objtree_VA("TYPMOD_IN=", 1,
+						 "clause", ObjTypeString, "typmod_in");
+	if (OidIsValid(typForm->typmodin))
+		append_object_object(ret, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 typForm->typmodin));
+	else
+		append_not_present(ret);
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the type typmod_out option.
+ *
+ * Verbose syntax
+ * TYPMOD_OUT=%{procedure}D
+ */
+static inline ObjElem *
+deparse_Type_Typmod_Out(Form_pg_type typForm)
+{
+	ObjTree    *ret;
+
+	ret = new_objtree_VA("TYPMOD_OUT=", 1,
+						 "clause", ObjTypeString, "typmod_out");
+	if (OidIsValid(typForm->typmodout))
+		append_object_object(ret, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 typForm->typmodout));
+	else
+		append_not_present(ret);
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the type analyze option.
+ *
+ * Verbose syntax
+ * ANALYZE=%{procedure}D
+ */
+static inline ObjElem *
+deparse_Type_Analyze(Form_pg_type typForm)
+{
+	ObjTree    *ret;
+
+	ret = new_objtree_VA("ANALYZE=", 1,
+						 "clause", ObjTypeString, "analyze");
+	if (OidIsValid(typForm->typanalyze))
+		append_object_object(ret, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 typForm->typanalyze));
+	else
+		append_not_present(ret);
+
+	return new_object_object(ret);
+}
+
+/*
+ * Deparse the type subscript option.
+ *
+ * Verbose syntax
+ * SUBSCRIPT=%{procedure}D
+ */
+static inline ObjElem *
+deparse_Type_Subscript(Form_pg_type typForm)
+{
+	ObjTree    *ret;
+
+	ret = new_objtree_VA("SUBSCRIPT=", 1,
+						 "clause", ObjTypeString, "subscript");
+	if (OidIsValid(typForm->typsubscript))
+		append_object_object(ret, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 typForm->typsubscript));
+	else
+		append_not_present(ret);
+
+	return new_object_object(ret);
+}
+
+/*
+ * Subroutine for CREATE TABLE deparsing.
+ *
+ * Deal with all the table elements (columns and constraints).
+ *
+ * Note we ignore constraints in the parse node here; they are extracted from
+ * system catalogs instead.
+ */
+static List *
+deparse_TableElements(Relation relation, List *tableElements, List *dpcontext,
+					  bool typed, bool composite)
+{
+	List	   *elements = NIL;
+	ListCell   *lc;
+
+	foreach(lc, tableElements)
+	{
+		Node	   *elt = (Node *) lfirst(lc);
+
+		switch (nodeTag(elt))
+		{
+			case T_ColumnDef:
+				{
+					ObjTree    *tree;
+
+					tree = typed ?
+						deparse_ColumnDef_typed(relation, dpcontext,
+												(ColumnDef *) elt) :
+						deparse_ColumnDef(relation, dpcontext,
+										  composite, (ColumnDef *) elt,
+										  false, NULL);
+					if (tree != NULL)
+						elements = lappend(elements, new_object_object(tree));
+				}
+				break;
+			case T_Constraint:
+				break;
+			default:
+				elog(ERROR, "invalid node type %d", nodeTag(elt));
+		}
+	}
+
+	return elements;
+}
+
+/*
+ * Deparse a CreateSeqStmt.
+ *
+ * Given a sequence OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE %{persistence}s SEQUENCE %{identity}D
+ */
+static ObjTree *
+deparse_CreateSeqStmt(Oid objectId, Node *parsetree)
+{
+	ObjTree    *ret;
+	Relation	relation;
+	List	   *elems = NIL;
+	Form_pg_sequence seqform;
+	Sequence_values *seqvalues;
+	CreateSeqStmt *createSeqStmt = (CreateSeqStmt *) parsetree;
+
+	/*
+	 * Sequence for IDENTITY COLUMN output separately (via CREATE TABLE or
+	 * ALTER TABLE); return empty here.
+	 */
+	if (createSeqStmt->for_identity)
+		return NULL;
+
+	seqvalues = get_sequence_values(objectId);
+	seqform = seqvalues->seqform;
+
+	/* Definition elements */
+	elems = lappend(elems, deparse_Seq_Cache(seqform, false));
+	elems = lappend(elems, deparse_Seq_Cycle(seqform, false));
+	elems = lappend(elems, deparse_Seq_IncrementBy(seqform, false));
+	elems = lappend(elems, deparse_Seq_Minvalue(seqform, false));
+	elems = lappend(elems, deparse_Seq_Maxvalue(seqform, false));
+	elems = lappend(elems, deparse_Seq_Startwith(seqform, false));
+	elems = lappend(elems, deparse_Seq_Restart(seqvalues->last_value));
+	elems = lappend(elems, deparse_Seq_As(seqform));
+
+	/* We purposefully do not emit OWNED BY here */
+
+	relation = relation_open(objectId, AccessShareLock);
+
+	ret = new_objtree_VA("CREATE %{persistence}s SEQUENCE %{if_not_exists}s %{identity}D %{definition: }s", 4,
+						 "persistence", ObjTypeString,
+						 get_persistence_str(relation->rd_rel->relpersistence),
+						 "if_not_exists", ObjTypeString,
+						 createSeqStmt->if_not_exists ? "IF NOT EXISTS" : "",
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(relation->rd_rel->relnamespace,
+												  RelationGetRelationName(relation)),
+						 "definition", ObjTypeArray, elems);
+
+	relation_close(relation, AccessShareLock);
+
+	return ret;
+}
+
+/*
+ * Deparse an IndexStmt.
+ *
+ * Given an index OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * If the index corresponds to a constraint, NULL is returned.
+ *
+ * Verbose syntax
+ * CREATE %{unique}s INDEX %{concurrently}s %{if_not_exists}s %{name}I ON
+ * %{table}D USING %{index_am}s %{definition}s %{with}s %{tablespace}s
+ * %{where_clause}s %{nulls_not_distinct}s
+ */
+static ObjTree *
+deparse_IndexStmt(Oid objectId, Node *parsetree)
+{
+	IndexStmt  *node = (IndexStmt *) parsetree;
+	ObjTree    *ret;
+	ObjTree    *tmp_obj;
+	Relation	idxrel;
+	Relation	heaprel;
+	char	   *index_am;
+	char	   *definition;
+	char	   *reloptions;
+	char	   *tablespace;
+	char	   *whereClause;
+
+	if (node->primary || node->isconstraint)
+	{
+		/*
+		 * Indexes for PRIMARY KEY and other constraints are output
+		 * separately; return empty here.
+		 */
+		return NULL;
+	}
+
+	idxrel = relation_open(objectId, AccessShareLock);
+	heaprel = relation_open(idxrel->rd_index->indrelid, AccessShareLock);
+
+	pg_get_indexdef_detailed(objectId,
+							 &index_am, &definition, &reloptions,
+							 &tablespace, &whereClause);
+
+	ret = new_objtree_VA("CREATE %{unique}s INDEX %{concurrently}s %{if_not_exists}s %{name}I ON %{only}s %{table}D USING %{index_am}s %{definition}s", 8,
+						 "unique", ObjTypeString,
+						 node->unique ? "UNIQUE" : "",
+						 "concurrently", ObjTypeString,
+						 node->concurrent ? "CONCURRENTLY" : "",
+						 "if_not_exists", ObjTypeString,
+						 node->if_not_exists ? "IF NOT EXISTS" : "",
+						 "only", ObjTypeString,
+						 node->relation->inh ? "" : "ONLY",
+						 "name", ObjTypeString,
+						 RelationGetRelationName(idxrel),
+						 "table", ObjTypeObject,
+						 new_objtree_for_qualname(heaprel->rd_rel->relnamespace,
+												  RelationGetRelationName(heaprel)),
+						 "index_am", ObjTypeString, index_am,
+						 "definition", ObjTypeString, definition);
+
+	/* reloptions */
+	tmp_obj = new_objtree("WITH");
+	if (reloptions)
+		append_string_object(tmp_obj, "(%{opts}s)", "opts", reloptions);
+	else
+		append_not_present(tmp_obj);
+	append_object_object(ret, "%{with}s", tmp_obj);
+
+	/* tablespace */
+	tmp_obj = new_objtree("TABLESPACE");
+	if (tablespace)
+		append_string_object(tmp_obj, "%{tablespace}s", "tablespace", tablespace);
+	else
+		append_not_present(tmp_obj);
+	append_object_object(ret, "%{tablespace}s", tmp_obj);
+
+	/* WHERE clause */
+	tmp_obj = new_objtree("WHERE");
+	if (whereClause)
+		append_string_object(tmp_obj, "%{where}s", "where", whereClause);
+	else
+		append_not_present(tmp_obj);
+	append_object_object(ret, "%{where_clause}s", tmp_obj);
+
+	/* nulls_not_distinct */
+	if (node->nulls_not_distinct)
+		append_format_string(ret, "NULLS NOT DISTINCT");
+	else
+		append_format_string(ret, "NULLS DISTINCT");
+
+	table_close(idxrel, AccessShareLock);
+	table_close(heaprel, AccessShareLock);
+
+	return ret;
+}
+
+/*
+ * Deparse a CreateStmt (CREATE TABLE).
+ *
+ * Given a table OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D [OF
+ * %{of_type}T | PARTITION OF %{parent_identity}D] %{table_elements}s
+ * %{inherits}s %{partition_by}s %{access_method}s %{with_clause}s
+ * %{on_commit}s %{tablespace}s
+ */
+static ObjTree *
+deparse_CreateStmt(Oid objectId, Node *parsetree)
+{
+	CreateStmt *node = (CreateStmt *) parsetree;
+	Relation	relation = relation_open(objectId, AccessShareLock);
+	List	   *dpcontext;
+	ObjTree    *ret;
+	ObjTree    *tmp_obj;
+	List	   *list = NIL;
+	ListCell   *cell;
+
+	ret = new_objtree_VA("CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D", 3,
+						 "persistence", ObjTypeString,
+						 get_persistence_str(relation->rd_rel->relpersistence),
+						 "if_not_exists", ObjTypeString,
+						 node->if_not_exists ? "IF NOT EXISTS" : "",
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(relation->rd_rel->relnamespace,
+												  RelationGetRelationName(relation)));
+
+	dpcontext = deparse_context_for(RelationGetRelationName(relation),
+									objectId);
+
+	/*
+	 * Typed tables and partitions use a slightly different format string: we
+	 * must not put table_elements with parents directly in the fmt string,
+	 * because if there are no options the parentheses must not be emitted;
+	 * and also, typed tables do not allow for inheritance.
+	 */
+	if (node->ofTypename || node->partbound)
+	{
+		List	   *tableelts = NIL;
+
+		/*
+		 * We can't put table elements directly in the fmt string as an array
+		 * surrounded by parentheses here, because an empty clause would cause
+		 * a syntax error.  Therefore, we use an indirection element and set
+		 * present=false when there are no elements.
+		 */
+		if (node->ofTypename)
+		{
+			tmp_obj = new_objtree_for_type(relation->rd_rel->reloftype, -1);
+			append_object_object(ret, "OF %{of_type}T", tmp_obj);
+		}
+		else
+		{
+			List	   *parents;
+			ObjElem    *elem;
+
+			parents = deparse_InhRelations(objectId);
+			elem = (ObjElem *) linitial(parents);
+
+			Assert(list_length(parents) == 1);
+
+			append_format_string(ret, "PARTITION OF");
+
+			append_object_object(ret, "%{parent_identity}D",
+								 elem->value.object);
+		}
+
+		tableelts = deparse_TableElements(relation, node->tableElts, dpcontext,
+										  true, /* typed table */
+										  false);	/* not composite */
+		tableelts = obtainConstraints(tableelts, objectId, InvalidOid);
+
+		tmp_obj = new_objtree("");
+		if (tableelts)
+			append_array_object(tmp_obj, "(%{elements:, }s)", tableelts);
+		else
+			append_not_present(tmp_obj);
+
+		append_object_object(ret, "%{table_elements}s", tmp_obj);
+	}
+	else
+	{
+		List	   *tableelts = NIL;
+
+		/*
+		 * There is no need to process LIKE clauses separately; they have
+		 * already been transformed into columns and constraints.
+		 */
+
+		/*
+		 * Process table elements: column definitions and constraints.  Only
+		 * the column definitions are obtained from the parse node itself.  To
+		 * get constraints we rely on pg_constraint, because the parse node
+		 * might be missing some things such as the name of the constraints.
+		 */
+		tableelts = deparse_TableElements(relation, node->tableElts, dpcontext,
+										  false,	/* not typed table */
+										  false);	/* not composite */
+		tableelts = obtainConstraints(tableelts, objectId, InvalidOid);
+
+		if (tableelts)
+			append_array_object(ret, "(%{table_elements:, }s)", tableelts);
+		else
+			append_format_string(ret, "()");
+
+		/*
+		 * Add inheritance specification.  We cannot simply scan the list of
+		 * parents from the parser node, because that may lack the actual
+		 * qualified names of the parent relations.  Rather than trying to
+		 * re-resolve them from the information in the parse node, it seems
+		 * more accurate and convenient to grab it from pg_inherits.
+		 */
+		tmp_obj = new_objtree("INHERITS");
+		if (node->inhRelations != NIL)
+			append_array_object(tmp_obj, "(%{parents:, }D)", deparse_InhRelations(objectId));
+		else
+		{
+			append_null_object(tmp_obj, "(%{parents:, }D)");
+			append_not_present(tmp_obj);
+		}
+		append_object_object(ret, "%{inherits}s", tmp_obj);
+	}
+
+	/* FOR VALUES clause */
+	if (node->partbound)
+	{
+		/*
+		 * Get pg_class.relpartbound. We cannot use partbound in the parsetree
+		 * directly as it's the original partbound expression which haven't
+		 * been transformed.
+		 */
+		append_string_object(ret, "%{partition_bound}s", "partition_bound",
+							 RelationGetPartitionBound(objectId));
+	}
+
+	/* PARTITION BY clause */
+	tmp_obj = new_objtree("PARTITION BY");
+	if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+		append_string_object(tmp_obj, "%{definition}s", "definition",
+							 pg_get_partkeydef_string(objectId));
+	else
+	{
+		append_null_object(tmp_obj, "%{definition}s");
+		append_not_present(tmp_obj);
+	}
+	append_object_object(ret, "%{partition_by}s", tmp_obj);
+
+	/* USING clause */
+	tmp_obj = new_objtree("USING");
+	if (node->accessMethod)
+		append_string_object(tmp_obj, "%{access_method}I", "access_method",
+							 node->accessMethod);
+	else
+	{
+		append_null_object(tmp_obj, "%{access_method}I");
+		append_not_present(tmp_obj);
+	}
+	append_object_object(ret, "%{access_method}s", tmp_obj);
+
+	/* WITH clause */
+	tmp_obj = new_objtree("WITH");
+
+	foreach(cell, node->options)
+	{
+		ObjTree    *tmp_obj2;
+		DefElem    *opt = (DefElem *) lfirst(cell);
+
+		tmp_obj2 = deparse_DefElem(opt, false);
+		list = lappend(list, new_object_object(tmp_obj2));
+	}
+
+	if (list)
+		append_array_object(tmp_obj, "(%{with:, }s)", list);
+	else
+		append_not_present(tmp_obj);
+
+	append_object_object(ret, "%{with_clause}s", tmp_obj);
+
+	append_object_object(ret, "%{on_commit}s",
+						 deparse_OnCommitClause(node->oncommit));
+
+	tmp_obj = new_objtree("TABLESPACE");
+	if (node->tablespacename)
+		append_string_object(tmp_obj, "%{tablespace}I", "tablespace",
+							 node->tablespacename);
+	else
+	{
+		append_null_object(tmp_obj, "%{tablespace}I");
+		append_not_present(tmp_obj);
+	}
+	append_object_object(ret, "%{tablespace}s", tmp_obj);
+
+	relation_close(relation, AccessShareLock);
+
+	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.
+ *
+ * Verbose syntax
+ * ALTER reltype %{identity}D %{subcmds:, }s
+ */
+static ObjTree *
+deparse_AlterRelation(CollectedCommand *cmd)
+{
+	ObjTree    *ret;
+	ObjTree    *tmp_obj;
+	ObjTree    *tmp_obj2;
+	List	   *dpcontext;
+	Relation	rel;
+	List	   *subcmds = NIL;
+	ListCell   *cell;
+	const char *reltype;
+	bool		istype = false;
+	List	   *exprs = NIL;
+	Oid			relId = cmd->d.alterTable.objectId;
+	AlterTableStmt *stmt = NULL;
+
+	Assert(cmd->type == SCT_AlterTable);
+	stmt = (AlterTableStmt *) cmd->parsetree;
+	Assert(IsA(stmt, AlterTableStmt));
+
+	/*
+	 * ALTER TABLE subcommands generated for TableLikeClause is processed in
+	 * the top level CREATE TABLE command; return empty here.
+	 */
+	if (stmt->table_like)
+		return NULL;
+
+	rel = relation_open(relId, AccessShareLock);
+	dpcontext = deparse_context_for(RelationGetRelationName(rel),
+									relId);
+
+	switch (rel->rd_rel->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_PARTITIONED_TABLE:
+			reltype = "TABLE";
+			break;
+		case RELKIND_INDEX:
+		case RELKIND_PARTITIONED_INDEX:
+			reltype = "INDEX";
+			break;
+		case RELKIND_VIEW:
+			reltype = "VIEW";
+			break;
+		case RELKIND_COMPOSITE_TYPE:
+			reltype = "TYPE";
+			istype = true;
+			break;
+		case RELKIND_FOREIGN_TABLE:
+			reltype = "FOREIGN TABLE";
+			break;
+		case RELKIND_MATVIEW:
+			reltype = "MATERIALIZED VIEW";
+			break;
+
+			/* TODO support for partitioned table */
+
+		default:
+			elog(ERROR, "unexpected relkind %d", rel->rd_rel->relkind);
+	}
+
+	ret = new_objtree_VA("ALTER %{objtype}s %{identity}D", 2,
+						 "objtype", ObjTypeString, reltype,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(rel->rd_rel->relnamespace,
+												  RelationGetRelationName(rel)));
+
+	foreach(cell, cmd->d.alterTable.subcmds)
+	{
+		CollectedATSubcmd *sub = (CollectedATSubcmd *) lfirst(cell);
+		AlterTableCmd *subcmd = (AlterTableCmd *) sub->parsetree;
+		ObjTree    *tree;
+
+		Assert(IsA(subcmd, AlterTableCmd));
+
+	   /*
+		* If the ALTER TABLE command for the parent table includes subcommands
+		* for child table(s), do not deparse the subcommand for child
+		* table(s).
+		*/
+		if (sub->address.objectId != relId &&
+			has_superclass(sub->address.objectId))
+			continue;
+
+		switch (subcmd->subtype)
+		{
+			case AT_AddColumn:
+				/* XXX need to set the "recurse" bit somewhere? */
+				Assert(IsA(subcmd->def, ColumnDef));
+				tree = deparse_ColumnDef(rel, dpcontext, false,
+										 (ColumnDef *) subcmd->def, true, &exprs);
+				tmp_obj = new_objtree_VA("ADD %{objtype}s %{if_not_exists}s %{definition}s", 4,
+										"objtype", ObjTypeString,
+										istype ? "ATTRIBUTE" : "COLUMN",
+										"type", ObjTypeString, "add column",
+										"if_not_exists", ObjTypeString,
+										subcmd->missing_ok ? "IF NOT EXISTS" : "",
+										"definition", ObjTypeObject, tree);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_AddIndexConstraint:
+				{
+					IndexStmt  *istmt;
+					Relation	idx;
+					Oid			constrOid = sub->address.objectId;
+
+					Assert(IsA(subcmd->def, IndexStmt));
+					istmt = (IndexStmt *) subcmd->def;
+
+					Assert(istmt->isconstraint && istmt->unique);
+
+					idx = relation_open(istmt->indexOid, AccessShareLock);
+
+					/*
+					 * Verbose syntax
+					 *
+					 * ADD CONSTRAINT %{name}I %{constraint_type}s USING INDEX
+					 * %index_name}I %{deferrable}s %{init_deferred}s
+					 */
+					tmp_obj = new_objtree_VA("ADD CONSTRAINT %{name}I %{constraint_type}s USING INDEX %{index_name}I %{deferrable}s %{init_deferred}s", 6,
+											"type", ObjTypeString, "add constraint using index",
+											"name", ObjTypeString, get_constraint_name(constrOid),
+											"constraint_type", ObjTypeString,
+											istmt->primary ? "PRIMARY KEY" : "UNIQUE",
+											"index_name", ObjTypeString,
+											RelationGetRelationName(idx),
+											"deferrable", ObjTypeString,
+											istmt->deferrable ? "DEFERRABLE" : "NOT DEFERRABLE",
+											"init_deferred", ObjTypeString,
+											istmt->initdeferred ? "INITIALLY DEFERRED" : "INITIALLY IMMEDIATE");
+
+					subcmds = lappend(subcmds, new_object_object(tmp_obj));
+
+					relation_close(idx, AccessShareLock);
+				}
+				break;
+
+			case AT_ReAddIndex:
+			case AT_ReAddConstraint:
+			case AT_ReAddDomainConstraint:
+			case AT_ReAddComment:
+			case AT_ReplaceRelOptions:
+			case AT_CheckNotNull:
+			case AT_ReAddStatistics:
+				/* Subtypes used for internal operations; nothing to do here */
+				break;
+
+			case AT_CookedColumnDefault:
+				{
+					Relation	attrrel;
+					HeapTuple	atttup;
+					Form_pg_attribute attStruct;
+
+					attrrel = table_open(AttributeRelationId, RowExclusiveLock);
+					atttup = SearchSysCacheCopy2(ATTNUM,
+												 ObjectIdGetDatum(RelationGetRelid(rel)),
+												 Int16GetDatum(subcmd->num));
+					if (!HeapTupleIsValid(atttup))
+						elog(ERROR, "cache lookup failed for attribute %d of relation with OID %u",
+							 subcmd->num, RelationGetRelid(rel));
+					attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
+
+					/*
+					 * Both default and generation expression not supported
+					 * together.
+					 */
+					if (!attStruct->attgenerated)
+						elog(WARNING, "unsupported alter table subtype %d",
+							 subcmd->subtype);
+
+					heap_freetuple(atttup);
+					table_close(attrrel, RowExclusiveLock);
+					break;
+				}
+
+			case AT_AddColumnToView:
+				/* CREATE OR REPLACE VIEW -- nothing to do here */
+				break;
+
+			case AT_ColumnDefault:
+				if (subcmd->def == NULL)
+					tmp_obj = new_objtree_VA("ALTER COLUMN %{column}I DROP DEFAULT", 2,
+											"type", ObjTypeString, "drop default",
+											"column", ObjTypeString, subcmd->name);
+				else
+				{
+					List	   *dpcontext_rel;
+					HeapTuple	attrtup;
+					AttrNumber	attno;
+
+					tmp_obj = new_objtree_VA("ALTER COLUMN %{column}I SET DEFAULT", 2,
+											"type", ObjTypeString, "set default",
+											"column", ObjTypeString, subcmd->name);
+
+					dpcontext_rel = deparse_context_for(RelationGetRelationName(rel),
+														RelationGetRelid(rel));
+					attrtup = SearchSysCacheAttName(RelationGetRelid(rel), subcmd->name);
+					attno = ((Form_pg_attribute) GETSTRUCT(attrtup))->attnum;
+					append_string_object(tmp_obj, "%{definition}s", "definition",
+										 RelationGetColumnDefault(rel, attno,
+																  dpcontext_rel,
+																  NULL));
+					ReleaseSysCache(attrtup);
+				}
+
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_DropNotNull:
+				tmp_obj = new_objtree_VA("ALTER COLUMN %{column}I DROP NOT NULL", 2,
+										"type", ObjTypeString, "drop not null",
+										"column", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_ForceRowSecurity:
+				tmp_obj = new_objtree("FORCE ROW LEVEL SECURITY");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_NoForceRowSecurity:
+				tmp_obj = new_objtree("NO FORCE ROW LEVEL SECURITY");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_SetNotNull:
+				tmp_obj = new_objtree_VA("ALTER COLUMN %{column}I SET NOT NULL", 2,
+										"type", ObjTypeString, "set not null",
+										"column", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_DropExpression:
+				tmp_obj = new_objtree_VA("ALTER COLUMN %{column}I DROP EXPRESSION %{if_exists}s", 3,
+										"type", ObjTypeString, "drop expression",
+										"column", ObjTypeString, subcmd->name,
+										"if_exists", ObjTypeString,
+										subcmd->missing_ok ? "IF EXISTS" : "");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_SetStatistics:
+				{
+					Assert(IsA(subcmd->def, Integer));
+					if (subcmd->name)
+						tmp_obj = new_objtree_VA("ALTER COLUMN %{column}I SET STATISTICS %{statistics}n", 3,
+												"type", ObjTypeString, "set statistics",
+												"column", ObjTypeString, subcmd->name,
+												"statistics", ObjTypeInteger,
+												intVal((Integer *) subcmd->def));
+					else
+						tmp_obj = new_objtree_VA("ALTER COLUMN %{column}n SET STATISTICS %{statistics}n", 3,
+												"type", ObjTypeString, "set statistics",
+												"column", ObjTypeInteger, subcmd->num,
+												"statistics", ObjTypeInteger,
+												intVal((Integer *) subcmd->def));
+					subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				}
+				break;
+
+			case AT_SetOptions:
+			case AT_ResetOptions:
+				subcmds = lappend(subcmds, new_object_object(
+															 deparse_ColumnSetOptions(subcmd)));
+				break;
+
+			case AT_SetStorage:
+				Assert(IsA(subcmd->def, String));
+				tmp_obj = new_objtree_VA("ALTER COLUMN %{column}I SET STORAGE %{storage}s", 3,
+										"type", ObjTypeString, "set storage",
+										"column", ObjTypeString, subcmd->name,
+										"storage", ObjTypeString,
+										strVal((String *) subcmd->def));
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_SetCompression:
+				Assert(IsA(subcmd->def, String));
+				tmp_obj = new_objtree_VA("ALTER COLUMN %{column}I SET COMPRESSION %{compression_method}s", 3,
+										"type", ObjTypeString, "set compression",
+										"column", ObjTypeString, subcmd->name,
+										"compression_method", ObjTypeString,
+										strVal((String *) subcmd->def));
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_DropColumn:
+				tmp_obj = new_objtree_VA("DROP %{objtype}s %{if_exists}s %{column}I", 4,
+										"objtype", ObjTypeString,
+										istype ? "ATTRIBUTE" : "COLUMN",
+										"type", ObjTypeString, "drop column",
+										"if_exists", ObjTypeString,
+										subcmd->missing_ok ? "IF EXISTS" : "",
+										"column", ObjTypeString, subcmd->name);
+				tmp_obj2 = new_objtree_VA("CASCADE", 1,
+										 "present", ObjTypeBool, subcmd->behavior);
+				append_object_object(tmp_obj, "%{cascade}s", tmp_obj2);
+
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_AddIndex:
+				{
+					Oid			idxOid = sub->address.objectId;
+					IndexStmt  *istmt;
+					Relation	idx;
+					const char *idxname;
+					Oid			constrOid;
+
+					Assert(IsA(subcmd->def, IndexStmt));
+					istmt = (IndexStmt *) subcmd->def;
+
+					if (!istmt->isconstraint)
+						break;
+
+					idx = relation_open(idxOid, AccessShareLock);
+					idxname = RelationGetRelationName(idx);
+
+					constrOid = get_relation_constraint_oid(
+															cmd->d.alterTable.objectId, idxname, false);
+
+					tmp_obj = new_objtree_VA("ADD CONSTRAINT %{name}I %{definition}s", 3,
+											"type", ObjTypeString, "add constraint",
+											"name", ObjTypeString, idxname,
+											"definition", ObjTypeString,
+											pg_get_constraintdef_string(constrOid));
+					subcmds = lappend(subcmds, new_object_object(tmp_obj));
+
+					relation_close(idx, AccessShareLock);
+				}
+				break;
+
+			case AT_AddConstraint:
+				{
+					/* XXX need to set the "recurse" bit somewhere? */
+					Oid			constrOid = sub->address.objectId;
+					bool		isnull;
+					HeapTuple	tup;
+					Datum		val;
+					Constraint *constr;
+
+					/* Skip adding constraint for inherits table sub command */
+					if (!constrOid)
+						continue;
+
+					Assert(IsA(subcmd->def, Constraint));
+					constr = castNode(Constraint, subcmd->def);
+
+					if (!constr->skip_validation)
+					{
+						tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constrOid));
+
+						if (HeapTupleIsValid(tup))
+						{
+							char	   *conbin;
+
+							/* Fetch constraint expression in parsetree form */
+							val = SysCacheGetAttr(CONSTROID, tup,
+												  Anum_pg_constraint_conbin, &isnull);
+
+							if (!isnull)
+							{
+								conbin = TextDatumGetCString(val);
+								exprs = lappend(exprs, stringToNode(conbin));
+							}
+
+							ReleaseSysCache(tup);
+						}
+					}
+
+					tmp_obj = new_objtree_VA("ADD CONSTRAINT %{name}I %{definition}s", 3,
+											"type", ObjTypeString, "add constraint",
+											"name", ObjTypeString, get_constraint_name(constrOid),
+											"definition", ObjTypeString,
+											pg_get_constraintdef_string(constrOid));
+					subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				}
+				break;
+
+			case AT_AlterConstraint:
+				{
+					Oid			constrOid = sub->address.objectId;
+					Constraint *c = (Constraint *) subcmd->def;
+
+					/* If no constraint was altered, silently skip it */
+					if (!OidIsValid(constrOid))
+						break;
+
+					Assert(IsA(c, Constraint));
+					tmp_obj = new_objtree_VA("ALTER CONSTRAINT %{name}I %{deferrable}s %{init_deferred}s", 4,
+											"type", ObjTypeString, "alter constraint",
+											"name", ObjTypeString, get_constraint_name(constrOid),
+											"deferrable", ObjTypeString,
+											c->deferrable ? "DEFERRABLE" : "NOT DEFERRABLE",
+											"init_deferred", ObjTypeString,
+											c->initdeferred ? "INITIALLY DEFERRED" : "INITIALLY IMMEDIATE");
+
+					subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				}
+				break;
+
+			case AT_ValidateConstraint:
+				tmp_obj = new_objtree_VA("VALIDATE CONSTRAINT %{constraint}I", 2,
+										"type", ObjTypeString, "validate constraint",
+										"constraint", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_DropConstraint:
+				tmp_obj = new_objtree_VA("DROP CONSTRAINT %{if_exists}s %{constraint}I %{cascade}s", 4,
+										"type", ObjTypeString, "drop constraint",
+										"if_exists", ObjTypeString,
+										subcmd->missing_ok ? "IF EXISTS" : "",
+										"constraint", ObjTypeString, subcmd->name,
+										"cascade", ObjTypeString,
+										subcmd->behavior == DROP_CASCADE ? "CASCADE" : "");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_AlterColumnType:
+				{
+					TupleDesc	tupdesc = RelationGetDescr(rel);
+					Form_pg_attribute att;
+					ColumnDef  *def;
+
+					att = &(tupdesc->attrs[sub->address.objectSubId - 1]);
+					def = (ColumnDef *) subcmd->def;
+					Assert(IsA(def, ColumnDef));
+
+					/*
+					 * Verbose syntax
+					 *
+					 * Composite types: ALTER reltype %{column}I SET DATA TYPE
+					 * %{datatype}T %{collation}s ATTRIBUTE %{cascade}s
+					 *
+					 * Normal types: ALTER reltype %{column}I SET DATA TYPE
+					 * %{datatype}T %{collation}s COLUMN %{using}s
+					 */
+					tmp_obj = new_objtree_VA("ALTER %{objtype}s %{column}I SET DATA TYPE %{datatype}T", 4,
+											"objtype", ObjTypeString,
+											istype ? "ATTRIBUTE" : "COLUMN",
+											"type", ObjTypeString, "alter column type",
+											"column", ObjTypeString, subcmd->name,
+											"datatype", ObjTypeObject,
+											new_objtree_for_type(att->atttypid,
+																 att->atttypmod));
+
+					/* Add a COLLATE clause, if needed */
+					tmp_obj2 = new_objtree("COLLATE");
+					if (OidIsValid(att->attcollation))
+					{
+						ObjTree    *collname;
+
+						collname = new_objtree_for_qualname_id(CollationRelationId,
+															   att->attcollation);
+						append_object_object(tmp_obj2, "%{name}D", collname);
+					}
+					else
+						append_not_present(tmp_obj2);
+					append_object_object(tmp_obj, "%{collation}s", tmp_obj2);
+
+					/* If not a composite type, add the USING clause */
+					if (!istype)
+					{
+						/*
+						 * If there's a USING clause, transformAlterTableStmt
+						 * ran it through transformExpr and stored the
+						 * resulting node in cooked_default, which we can use
+						 * here.
+						 */
+						tmp_obj2 = new_objtree("USING");
+						if (def->raw_default)
+							append_string_object(tmp_obj2, "%{expression}s",
+												 "expression",
+												 sub->usingexpr);
+						else
+							append_not_present(tmp_obj2);
+						append_object_object(tmp_obj, "%{using}s", tmp_obj2);
+					}
+
+					/* If it's a composite type, add the CASCADE clause */
+					if (istype)
+					{
+						tmp_obj2 = new_objtree("CASCADE");
+						if (subcmd->behavior != DROP_CASCADE)
+							append_not_present(tmp_obj2);
+						append_object_object(tmp_obj, "%{cascade}s", tmp_obj2);
+					}
+
+					subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				}
+				break;
+
+#ifdef TODOLIST
+			case AT_AlterColumnGenericOptions:
+				tmp_obj = deparse_FdwOptions((List *) subcmd->def,
+											subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+#endif
+			case AT_ChangeOwner:
+				tmp_obj = new_objtree_VA("OWNER TO %{owner}I", 2,
+										"type", ObjTypeString, "change owner",
+										"owner", ObjTypeString,
+										get_rolespec_name(subcmd->newowner));
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_ClusterOn:
+				tmp_obj = new_objtree_VA("CLUSTER ON %{index}I", 2,
+										"type", ObjTypeString, "cluster on",
+										"index", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_DropCluster:
+				tmp_obj = new_objtree_VA("SET WITHOUT CLUSTER", 1,
+										"type", ObjTypeString, "set without cluster");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_SetLogged:
+				tmp_obj = new_objtree_VA("SET LOGGED", 1,
+										"type", ObjTypeString, "set logged");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_SetUnLogged:
+				tmp_obj = new_objtree_VA("SET UNLOGGED", 1,
+										"type", ObjTypeString, "set unlogged");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_DropOids:
+				tmp_obj = new_objtree_VA("SET WITHOUT OIDS", 1,
+										"type", ObjTypeString, "set without oids");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+			case AT_SetAccessMethod:
+				tmp_obj = new_objtree_VA("SET ACCESS METHOD %{access_method}I", 2,
+										"type", ObjTypeString, "set access method",
+										"access_method", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+			case AT_SetTableSpace:
+				tmp_obj = new_objtree_VA("SET TABLESPACE %{tablespace}I", 2,
+										"type", ObjTypeString, "set tablespace",
+										"tablespace", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_SetRelOptions:
+			case AT_ResetRelOptions:
+				subcmds = lappend(subcmds, new_object_object(
+															 deparse_RelSetOptions(subcmd)));
+				break;
+
+			case AT_EnableTrig:
+				tmp_obj = new_objtree_VA("ENABLE TRIGGER %{trigger}I", 2,
+										"type", ObjTypeString, "enable trigger",
+										"trigger", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_EnableAlwaysTrig:
+				tmp_obj = new_objtree_VA("ENABLE ALWAYS TRIGGER %{trigger}I", 2,
+										"type", ObjTypeString, "enable always trigger",
+										"trigger", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_EnableReplicaTrig:
+				tmp_obj = new_objtree_VA("ENABLE REPLICA TRIGGER %{trigger}I", 2,
+										"type", ObjTypeString, "enable replica trigger",
+										"trigger", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_DisableTrig:
+				tmp_obj = new_objtree_VA("DISABLE TRIGGER %{trigger}I", 2,
+										"type", ObjTypeString, "disable trigger",
+										"trigger", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_EnableTrigAll:
+				tmp_obj = new_objtree_VA("ENABLE TRIGGER ALL", 1,
+										"type", ObjTypeString, "enable trigger all");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_DisableTrigAll:
+				tmp_obj = new_objtree_VA("DISABLE TRIGGER ALL", 1,
+										"type", ObjTypeString, "disable trigger all");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_EnableTrigUser:
+				tmp_obj = new_objtree_VA("ENABLE TRIGGER USER", 1,
+										"type", ObjTypeString, "enable trigger user");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_DisableTrigUser:
+				tmp_obj = new_objtree_VA("DISABLE TRIGGER USER", 1,
+										"type", ObjTypeString, "disable trigger user");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_EnableRule:
+				tmp_obj = new_objtree_VA("ENABLE RULE %{rule}I", 2,
+										"type", ObjTypeString, "enable rule",
+										"rule", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_EnableAlwaysRule:
+				tmp_obj = new_objtree_VA("ENABLE ALWAYS RULE %{rule}I", 2,
+										"type", ObjTypeString, "enable always rule",
+										"rule", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_EnableReplicaRule:
+				tmp_obj = new_objtree_VA("ENABLE REPLICA RULE %{rule}I", 2,
+										"type", ObjTypeString, "enable replica rule",
+										"rule", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_DisableRule:
+				tmp_obj = new_objtree_VA("DISABLE RULE %{rule}I", 2,
+										"type", ObjTypeString, "disable rule",
+										"rule", ObjTypeString, subcmd->name);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_AddInherit:
+				tmp_obj = new_objtree_VA("INHERIT %{parent}D", 2,
+										"type", ObjTypeString, "inherit",
+										"parent", ObjTypeObject,
+										new_objtree_for_qualname_id(RelationRelationId,
+																	sub->address.objectId));
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_DropInherit:
+				tmp_obj = new_objtree_VA("NO INHERIT %{parent}D", 2,
+										"type", ObjTypeString, "drop inherit",
+										"parent", ObjTypeObject,
+										new_objtree_for_qualname_id(RelationRelationId,
+																	sub->address.objectId));
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_AddOf:
+				tmp_obj = new_objtree_VA("OF %{type_of}T", 2,
+										"type", ObjTypeString, "add of",
+										"type_of", ObjTypeObject,
+										new_objtree_for_type(sub->address.objectId, -1));
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_DropOf:
+				tmp_obj = new_objtree_VA("NOT OF", 1,
+										"type", ObjTypeString, "not of");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_ReplicaIdentity:
+				tmp_obj = new_objtree_VA("REPLICA IDENTITY", 1,
+										"type", ObjTypeString, "replica identity");
+				switch (((ReplicaIdentityStmt *) subcmd->def)->identity_type)
+				{
+					case REPLICA_IDENTITY_DEFAULT:
+						append_string_object(tmp_obj, "%{ident}s", "ident",
+											 "DEFAULT");
+						break;
+					case REPLICA_IDENTITY_FULL:
+						append_string_object(tmp_obj, "%{ident}s", "ident",
+											 "FULL");
+						break;
+					case REPLICA_IDENTITY_NOTHING:
+						append_string_object(tmp_obj, "%{ident}s", "ident",
+											 "NOTHING");
+						break;
+					case REPLICA_IDENTITY_INDEX:
+						tmp_obj2 = new_objtree_VA("USING INDEX %{index}I", 1,
+												 "index", ObjTypeString,
+												 ((ReplicaIdentityStmt *) subcmd->def)->name);
+						append_object_object(tmp_obj, "%{ident}s", tmp_obj2);
+						break;
+				}
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_EnableRowSecurity:
+				tmp_obj = new_objtree_VA("ENABLE ROW LEVEL SECURITY", 1,
+										"type", ObjTypeString, "enable row security");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+
+			case AT_DisableRowSecurity:
+				tmp_obj = new_objtree_VA("DISABLE ROW LEVEL SECURITY", 1,
+										"type", ObjTypeString, "disable row security");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+#ifdef TODOLIST
+			case AT_GenericOptions:
+				tmp_obj = deparse_FdwOptions((List *) subcmd->def, NULL);
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+#endif
+			case AT_AttachPartition:
+				tmp_obj = new_objtree_VA("ATTACH PARTITION %{partition_identity}D", 2,
+										"type", ObjTypeString, "attach partition",
+										"partition_identity", ObjTypeObject,
+										new_objtree_for_qualname_id(RelationRelationId,
+																	sub->address.objectId));
+
+				if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+					append_string_object(tmp_obj, "%{partition_bound}s",
+										 "partition_bound",
+										 RelationGetPartitionBound(sub->address.objectId));
+
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+			case AT_DetachPartition:
+			{
+				PartitionCmd *cmd;
+
+				Assert(IsA(subcmd->def, PartitionCmd));
+				cmd = (PartitionCmd *) subcmd->def;
+
+				tmp_obj = new_objtree_VA("DETACH PARTITION %{partition_identity}D %{concurrent}s", 3,
+										"type", ObjTypeString,
+										"detach partition",
+										"partition_identity", ObjTypeObject,
+										new_objtree_for_qualname_id(RelationRelationId,
+																	sub->address.objectId),
+										cmd->concurrent ? "CONCURRENTLY" : "");
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+			}
+			case AT_DetachPartitionFinalize:
+				tmp_obj = new_objtree_VA("DETACH PARTITION %{partition_identity}D FINALIZE", 2,
+										"type", ObjTypeString, "detach partition finalize",
+										"partition_identity", ObjTypeObject,
+										new_objtree_for_qualname_id(RelationRelationId,
+																	sub->address.objectId));
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+			case AT_AddIdentity:
+				{
+					AttrNumber	attnum;
+					Oid			seq_relid;
+					ObjTree    *seqdef;
+					ColumnDef  *coldef = (ColumnDef *) subcmd->def;
+
+					tmp_obj = new_objtree_VA("ALTER COLUMN %{column}I", 2,
+											"type", ObjTypeString, "add identity",
+											"column", ObjTypeString, subcmd->name);
+
+					attnum = get_attnum(RelationGetRelid(rel), subcmd->name);
+					seq_relid = getIdentitySequence(RelationGetRelid(rel), attnum, true);
+
+					if (OidIsValid(seq_relid))
+					{
+						seqdef = deparse_ColumnIdentity(seq_relid, coldef->identity, false);
+						append_object_object(tmp_obj, "ADD %{identity_column}s", seqdef);
+					}
+
+					subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				}
+				break;
+			case AT_SetIdentity:
+				{
+					DefElem    *defel;
+					char		identity = 0;
+					ObjTree    *seqdef;
+					AttrNumber	attnum;
+					Oid			seq_relid;
+
+
+					tmp_obj = new_objtree_VA("ALTER COLUMN %{column}I", 2,
+											"type", ObjTypeString, "set identity",
+											"column", ObjTypeString, subcmd->name);
+
+					if (subcmd->def)
+					{
+						List	   *def = (List *) subcmd->def;
+
+						Assert(IsA(subcmd->def, List));
+
+						defel = linitial_node(DefElem, def);
+						identity = defGetInt32(defel);
+					}
+
+					attnum = get_attnum(RelationGetRelid(rel), subcmd->name);
+					seq_relid = getIdentitySequence(RelationGetRelid(rel), attnum, true);
+
+					if (OidIsValid(seq_relid))
+					{
+						seqdef = deparse_ColumnIdentity(seq_relid, identity, true);
+						append_object_object(tmp_obj, "%{definition}s", seqdef);
+					}
+
+					subcmds = lappend(subcmds, new_object_object(tmp_obj));
+					break;
+				}
+			case AT_DropIdentity:
+				tmp_obj = new_objtree_VA("ALTER COLUMN %{column}I DROP IDENTITY", 2,
+										"type", ObjTypeString, "drop identity",
+										"column", ObjTypeString, subcmd->name);
+
+				append_string_object(tmp_obj, "%{if_exists}s",
+									 "if_exists",
+									 subcmd->missing_ok ? "IF EXISTS" : "");
+
+				subcmds = lappend(subcmds, new_object_object(tmp_obj));
+				break;
+			default:
+				elog(WARNING, "unsupported alter table subtype %d",
+					 subcmd->subtype);
+				break;
+		}
+
+		/*
+		 * We don't support replicating ALTER TABLE which contains volatile
+		 * functions because It's possible the functions contain DDL/DML in
+		 * which case these operations will be executed twice and cause
+		 * duplicate data. In addition, we don't know whether the tables being
+		 * accessed by these DDL/DML are published or not. So blindly allowing
+		 * such functions can allow unintended clauses like the tables
+		 * accessed in those functions may not even exist on the subscriber.
+		 */
+		if (contain_volatile_functions((Node *) exprs))
+			elog(ERROR, "ALTER TABLE command using volatile function cannot be replicated");
+
+		/*
+		 * Clean the list as we already confirmed there is no volatile
+		 * function.
+		 */
+		list_free(exprs);
+		exprs = NIL;
+	}
+
+	table_close(rel, AccessShareLock);
+
+	if (list_length(subcmds) == 0)
+		return NULL;
+
+	append_array_object(ret, "%{subcmds:, }s", subcmds);
+
+	return ret;
+}
+
+/*
+ * Handle deparsing of DROP commands.
+ *
+ * Verbose syntax
+ * DROP %s IF EXISTS %%{objidentity}s %{cascade}s
+ */
+char *
+deparse_drop_command(const char *objidentity, const char *objecttype,
+					 DropBehavior behavior)
+{
+	StringInfoData str;
+	char	   *command;
+	char	   *identity = (char *) objidentity;
+	ObjTree    *stmt;
+	ObjTree    *tmp_obj;
+	Jsonb	   *jsonb;
+
+	initStringInfo(&str);
+
+	stmt = new_objtree_VA("DROP %{objtype}s IF EXISTS %{objidentity}s", 2,
+						  "objtype", ObjTypeString, objecttype,
+						  "objidentity", ObjTypeString, identity);
+
+	tmp_obj = new_objtree_VA("CASCADE", 1,
+							"present", ObjTypeBool, behavior == DROP_CASCADE);
+	append_object_object(stmt, "%{cascade}s", tmp_obj);
+
+	jsonb = objtree_to_jsonb(stmt);
+	command = JsonbToCString(&str, &jsonb->root, JSONB_ESTIMATED_LEN);
+
+	return command;
+}
+
+/*
+ * Handle deparsing of simple commands.
+ *
+ * This function should cover all cases handled in ProcessUtilitySlow.
+ */
+static ObjTree *
+deparse_simple_command(CollectedCommand *cmd)
+{
+	Oid			objectId;
+	Node	   *parsetree;
+
+	Assert(cmd->type == SCT_Simple);
+
+	parsetree = cmd->parsetree;
+	objectId = cmd->d.simple.address.objectId;
+
+	if (cmd->in_extension && (nodeTag(parsetree) != T_CreateExtensionStmt))
+		return NULL;
+
+	/* This switch needs to handle everything that ProcessUtilitySlow does */
+	switch (nodeTag(parsetree))
+	{
+		case T_CreateSeqStmt:
+			return deparse_CreateSeqStmt(objectId, parsetree);
+
+		case T_CreateStmt:
+			return deparse_CreateStmt(objectId, parsetree);
+
+		case T_IndexStmt:
+			return deparse_IndexStmt(objectId, parsetree);
+
+		default:
+			elog(LOG, "unrecognized node type in deparse command: %d",
+				 (int) nodeTag(parsetree));
+	}
+
+	return NULL;
+}
+
+/*
+ * Workhorse to deparse a CollectedCommand.
+ */
+char *
+deparse_utility_command(CollectedCommand *cmd, bool verbose_mode)
+{
+	OverrideSearchPath *overridePath;
+	MemoryContext oldcxt;
+	MemoryContext tmpcxt;
+	ObjTree    *tree;
+	char	   *command = NULL;
+	StringInfoData str;
+
+	/*
+	 * Allocate everything done by the deparsing routines into a temp context,
+	 * to avoid having to sprinkle them with memory handling code, but
+	 * allocate the output StringInfo before switching.
+	 */
+	initStringInfo(&str);
+	tmpcxt = AllocSetContextCreate(CurrentMemoryContext,
+								   "deparse ctx",
+								   ALLOCSET_DEFAULT_MINSIZE,
+								   ALLOCSET_DEFAULT_INITSIZE,
+								   ALLOCSET_DEFAULT_MAXSIZE);
+	oldcxt = MemoryContextSwitchTo(tmpcxt);
+
+	/*
+	 * Many routines underlying this one will invoke ruleutils.c functionality
+	 * to obtain deparsed versions of expressions.  In such results, we want
+	 * all object names to be qualified, 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);
+
+	verbose = verbose_mode;
+
+	switch (cmd->type)
+	{
+		case SCT_Simple:
+			tree = deparse_simple_command(cmd);
+			break;
+		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);
+	}
+
+	PopOverrideSearchPath();
+
+	if (tree)
+	{
+		Jsonb	   *jsonb;
+
+		jsonb = objtree_to_jsonb(tree);
+		command = JsonbToCString(&str, &jsonb->root, JSONB_ESTIMATED_LEN);
+	}
+
+	/*
+	 * Clean up.  Note that since we created the StringInfo in the caller's
+	 * context, the output string is not deleted here.
+	 */
+	MemoryContextSwitchTo(oldcxt);
+	MemoryContextDelete(tmpcxt);
+
+	return command;
+}
+
+/*
+ * Given a CollectedCommand, return a JSON representation of it.
+ *
+ * The command is expanded fully so that there are no ambiguities even in the
+ * face of search_path changes.
+ */
+Datum
+ddl_deparse_to_json(PG_FUNCTION_ARGS)
+{
+	CollectedCommand *cmd = (CollectedCommand *) PG_GETARG_POINTER(0);
+	char	   *command;
+
+	command = deparse_utility_command(cmd, true);
+
+	if (command)
+		PG_RETURN_TEXT_P(cstring_to_text(command));
+
+	PG_RETURN_NULL();
+}
diff --git a/src/backend/commands/ddl_json.c b/src/backend/commands/ddl_json.c
new file mode 100644
index 0000000..536c6d8
--- /dev/null
+++ b/src/backend/commands/ddl_json.c
@@ -0,0 +1,781 @@
+/*-------------------------------------------------------------------------
+ *
+ * ddl_json.c
+ *	  JSON code related to DDL command deparsing
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *	  src/backend/commands/ddl_json.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "lib/stringinfo.h"
+#include "tcop/ddl_deparse.h"
+#include "utils/builtins.h"
+#include "utils/jsonb.h"
+
+
+/*
+ * Conversion specifier which determines how to expand the JSON element
+ * into a string.
+ */
+typedef enum
+{
+	SpecDottedName,
+	SpecIdentifier,
+	SpecNumber,
+	SpecOperatorName,
+	SpecRole,
+	SpecString,
+	SpecStringLiteral,
+	SpecTypeName
+} convSpecifier;
+
+/*
+ * A ternary value that represents a boolean type JsonbValue.
+ */
+typedef enum
+{
+	tv_absent,
+	tv_true,
+	tv_false
+}			json_trivalue;
+
+static bool expand_one_jsonb_element(StringInfo buf, char *param,
+									 JsonbValue *jsonval, convSpecifier specifier,
+									 const char *fmt);
+static void expand_jsonb_array(StringInfo buf, char *param,
+							   JsonbValue *jsonarr, char *arraysep,
+							   convSpecifier specifier, const char *fmt);
+static void fmtstr_error_callback(void *arg);
+
+/*
+ * Given a JsonbContainer, find the JsonbValue with the given key name in it.
+ * If it's of a type other than jbvBool, an error is raised. If it doesn't
+ * exist, tv_absent is returned; otherwise return the actual json_trivalue.
+ */
+static json_trivalue
+find_bool_in_jsonbcontainer(JsonbContainer *container, char *keyname)
+{
+	JsonbValue	key;
+	JsonbValue *value;
+	json_trivalue result;
+
+	key.type = jbvString;
+	key.val.string.val = keyname;
+	key.val.string.len = strlen(keyname);
+	value = findJsonbValueFromContainer(container,
+										JB_FOBJECT, &key);
+	if (value == NULL)
+		return tv_absent;
+	if (value->type != jbvBool)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("element \"%s\" is not of type boolean",
+						keyname)));
+	result = value->val.boolean ? tv_true : tv_false;
+	pfree(value);
+
+	return result;
+}
+
+/*
+ * Given a JsonbContainer, find the JsonbValue with the given key name in it.
+ * If it's of a type other than jbvString, an error is raised.  If it doesn't
+ * exist, an error is raised unless missing_ok; otherwise return NULL.
+ *
+ * If it exists and is a string, a freshly palloc'ed copy is returned.
+ *
+ * If *length is not NULL, it is set to the length of the string.
+ */
+static char *
+find_string_in_jsonbcontainer(JsonbContainer *container, char *keyname,
+							  bool missing_ok, int *length)
+{
+	JsonbValue	key;
+	JsonbValue *value;
+	char	   *str;
+
+	/* XXX verify that this is an object, not an array */
+
+	key.type = jbvString;
+	key.val.string.val = keyname;
+	key.val.string.len = strlen(keyname);
+	value = findJsonbValueFromContainer(container,
+										JB_FOBJECT, &key);
+	if (value == NULL)
+	{
+		if (missing_ok)
+			return NULL;
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("missing element \"%s\" in JSON object", keyname)));
+	}
+
+	if (value->type != jbvString)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("element \"%s\" is not of type string", keyname)));
+
+	str = pnstrdup(value->val.string.val, value->val.string.len);
+	if (length)
+		*length = value->val.string.len;
+	pfree(value);
+	return str;
+}
+
+#define ADVANCE_PARSE_POINTER(ptr,end_ptr) \
+	do { \
+		if (++(ptr) >= (end_ptr)) \
+			ereport(ERROR, \
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE), \
+					 errmsg("unterminated format specifier"))); \
+	} while (0)
+
+/*
+ * Recursive helper for deparse_ddl_json_to_string.
+ *
+ * Find the "fmt" element in the given container, and expand it into the
+ * provided StringInfo.
+ */
+static void
+expand_fmt_recursive(StringInfo buf, JsonbContainer *container)
+{
+	JsonbValue	key;
+	JsonbValue *value;
+	const char *cp;
+	const char *start_ptr;
+	const char *end_ptr;
+	int			len;
+
+	start_ptr = find_string_in_jsonbcontainer(container, "fmt", false, &len);
+	end_ptr = start_ptr + len;
+
+	for (cp = start_ptr; cp < end_ptr; cp++)
+	{
+		convSpecifier specifier;
+		bool		is_array = false;
+		char	   *param = NULL;
+		char	   *arraysep = NULL;
+
+		if (*cp != '%')
+		{
+			appendStringInfoCharMacro(buf, *cp);
+			continue;
+		}
+
+		ADVANCE_PARSE_POINTER(cp, end_ptr);
+
+		/* Easy case: %% outputs a single % */
+		if (*cp == '%')
+		{
+			appendStringInfoCharMacro(buf, *cp);
+			continue;
+		}
+
+		/*
+		 * Scan the mandatory element name.  Allow for an array separator
+		 * (which may be the empty string) to be specified after a colon.
+		 */
+		if (*cp == '{')
+		{
+			StringInfoData parbuf;
+			StringInfoData arraysepbuf;
+			StringInfo	appendTo;
+
+			initStringInfo(&parbuf);
+			appendTo = &parbuf;
+
+			ADVANCE_PARSE_POINTER(cp, end_ptr);
+			while (cp < end_ptr)
+			{
+				if (*cp == ':')
+				{
+					/*
+					 * Found array separator delimiter; element name is now
+					 * complete, start filling the separator.
+					 */
+					initStringInfo(&arraysepbuf);
+					appendTo = &arraysepbuf;
+					is_array = true;
+					ADVANCE_PARSE_POINTER(cp, end_ptr);
+					continue;
+				}
+
+				if (*cp == '}')
+				{
+					ADVANCE_PARSE_POINTER(cp, end_ptr);
+					break;
+				}
+				appendStringInfoCharMacro(appendTo, *cp);
+				ADVANCE_PARSE_POINTER(cp, end_ptr);
+			}
+			param = parbuf.data;
+			if (is_array)
+				arraysep = arraysepbuf.data;
+		}
+		if (param == NULL)
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("missing conversion name in conversion specifier")));
+
+		switch (*cp)
+		{
+			case 'I':
+				specifier = SpecIdentifier;
+				break;
+			case 'D':
+				specifier = SpecDottedName;
+				break;
+			case 's':
+				specifier = SpecString;
+				break;
+			case 'L':
+				specifier = SpecStringLiteral;
+				break;
+			case 'T':
+				specifier = SpecTypeName;
+				break;
+			case 'O':
+				specifier = SpecOperatorName;
+				break;
+			case 'n':
+				specifier = SpecNumber;
+				break;
+			case 'R':
+				specifier = SpecRole;
+				break;
+			default:
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("invalid conversion specifier \"%c\"", *cp)));
+		}
+
+		/*
+		 * Obtain the element to be expanded.
+		 */
+		key.type = jbvString;
+		key.val.string.val = param;
+		key.val.string.len = strlen(param);
+
+		value = findJsonbValueFromContainer(container, JB_FOBJECT, &key);
+		Assert(value != NULL);
+
+		/*
+		 * Expand the data (possibly an array) into the output StringInfo.
+		 */
+		if (is_array)
+			expand_jsonb_array(buf, param, value, arraysep, specifier, start_ptr);
+		else
+			expand_one_jsonb_element(buf, param, value, specifier, start_ptr);
+	}
+}
+
+/*
+ * Expand a json value as a quoted identifier.  The value must be of type string.
+ */
+static void
+expand_jsonval_identifier(StringInfo buf, JsonbValue *jsonval)
+{
+	char	   *str;
+
+	Assert(jsonval->type == jbvString);
+
+	str = pnstrdup(jsonval->val.string.val, jsonval->val.string.len);
+	appendStringInfoString(buf, quote_identifier(str));
+	pfree(str);
+}
+
+/*
+ * Expand a json value as a dot-separated-name.  The value must be of type
+ * binary and may contain elements "schemaname" (optional), "objname"
+ * (mandatory), "attrname" (optional).  Double quotes are added to each element
+ * as necessary, and dot separators where needed.
+ *
+ * One day we might need a "catalog" element as well, but no current use case
+ * needs that.
+ */
+static void
+expand_jsonval_dottedname(StringInfo buf, JsonbValue *jsonval)
+{
+	char	   *str;
+	JsonbContainer *data = jsonval->val.binary.data;
+
+	Assert(jsonval->type == jbvBinary);
+
+	str = find_string_in_jsonbcontainer(data, "schemaname", true, NULL);
+	if (str)
+	{
+		appendStringInfo(buf, "%s.", quote_identifier(str));
+		pfree(str);
+	}
+
+	str = find_string_in_jsonbcontainer(data, "objname", false, NULL);
+	appendStringInfo(buf, "%s", quote_identifier(str));
+	pfree(str);
+
+	str = find_string_in_jsonbcontainer(data, "attrname", true, NULL);
+	if (str)
+	{
+		appendStringInfo(buf, ".%s", quote_identifier(str));
+		pfree(str);
+	}
+}
+
+/*
+ * Expand a JSON value as a type name.
+ */
+static void
+expand_jsonval_typename(StringInfo buf, JsonbValue *jsonval)
+{
+	char	   *schema = NULL;
+	char	   *typename;
+	char	   *typmodstr;
+	json_trivalue is_array;
+	char	   *array_decor;
+	JsonbContainer *data = jsonval->val.binary.data;
+
+	/*
+	 * We omit schema-qualifying the output name if the schema element is
+	 * either the empty string or NULL; the difference between those two cases
+	 * is that in the latter we quote the type name, in the former we don't.
+	 * This allows for types with special typmod needs, such as interval and
+	 * timestamp (see format_type_detailed), while at the same time allowing
+	 * for the schema name to be omitted from type names that require quotes
+	 * but are to be obtained from a user schema.
+	 */
+
+	schema = find_string_in_jsonbcontainer(data, "schemaname", true, NULL);
+	typename = find_string_in_jsonbcontainer(data, "typename", false, NULL);
+	typmodstr = find_string_in_jsonbcontainer(data, "typmod", true, NULL);
+	is_array = find_bool_in_jsonbcontainer(data, "typarray");
+	switch (is_array)
+	{
+		case tv_true:
+			array_decor = "[]";
+			break;
+
+		case tv_false:
+			array_decor = "";
+			break;
+
+		case tv_absent:
+		default:
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("missing typarray element")));
+	}
+
+	if (schema == NULL)
+		appendStringInfo(buf, "%s", quote_identifier(typename));
+	else if (schema[0] == '\0')
+		appendStringInfo(buf, "%s", typename);	/* Special typmod needs */
+	else
+		appendStringInfo(buf, "%s.%s", quote_identifier(schema),
+						 quote_identifier(typename));
+
+	appendStringInfo(buf, "%s%s", typmodstr ? typmodstr : "", array_decor);
+	pfree(schema);
+	pfree(typename);
+	pfree(typmodstr);
+}
+
+/*
+ * Expand a JSON value as an operator name. The value may contain element
+ * "schemaname" (optional).
+ */
+static void
+expand_jsonval_operator(StringInfo buf, JsonbValue *jsonval)
+{
+	char	   *str;
+	JsonbContainer *data = jsonval->val.binary.data;
+
+	str = find_string_in_jsonbcontainer(data, "schemaname", true, NULL);
+	/* Schema might be NULL or empty */
+	if (str != NULL && str[0] != '\0')
+	{
+		appendStringInfo(buf, "%s.", quote_identifier(str));
+		pfree(str);
+	}
+
+	str = find_string_in_jsonbcontainer(data, "objname", false, NULL);
+	if (!str)
+		ereport(ERROR,
+				errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				errmsg("missing operator name"));
+
+	appendStringInfoString(buf, str);
+	pfree(str);
+}
+
+/*
+ * Expand a JSON value as a string.  The value must be of type string or of
+ * type Binary.  In the latter case, it must contain a "fmt" element which will
+ * be recursively expanded; also, if the object contains an element "present"
+ * and it is set to false, the expansion is the empty string.
+ *
+ * Returns false if no actual expansion was made due to the "present" flag
+ * being set to "false".
+ *
+ * The caller is responsible to check jsonval is of type jbvString or jbvBinary.
+ */
+static bool
+expand_jsonval_string(StringInfo buf, JsonbValue *jsonval)
+{
+	bool expanded = false;
+
+	if (jsonval->type == jbvString)
+	{
+		appendBinaryStringInfo(buf, jsonval->val.string.val,
+							   jsonval->val.string.len);
+		expanded = true;
+	}
+	else if (jsonval->type == jbvBinary)
+	{
+		json_trivalue present;
+
+		present = find_bool_in_jsonbcontainer(jsonval->val.binary.data,
+											  "present");
+
+		/*
+		 * If "present" is set to false, this element expands to empty;
+		 * otherwise (either true or absent), expand "fmt".
+		 */
+		if (present != tv_false)
+		{
+			expand_fmt_recursive(buf, jsonval->val.binary.data);
+			expanded = true;
+		}
+	}
+
+	return expanded;
+}
+
+/*
+ * Expand a JSON value as a string literal.
+ */
+static void
+expand_jsonval_strlit(StringInfo buf, JsonbValue *jsonval)
+{
+	char	   *str;
+	StringInfoData dqdelim;
+	static const char dqsuffixes[] = "_XYZZYX_";
+	int			dqnextchar = 0;
+
+	str = pnstrdup(jsonval->val.string.val, jsonval->val.string.len);
+
+	/* Easy case: if there are no ' and no \, just use a single quote */
+	if (strpbrk(str, "\'\\") == NULL)
+	{
+		appendStringInfo(buf, "'%s'", str);
+		pfree(str);
+		return;
+	}
+
+	/* Otherwise need to find a useful dollar-quote delimiter */
+	initStringInfo(&dqdelim);
+	appendStringInfoString(&dqdelim, "$");
+	while (strstr(str, dqdelim.data) != NULL)
+	{
+		appendStringInfoChar(&dqdelim, dqsuffixes[dqnextchar++]);
+		dqnextchar = dqnextchar % (sizeof(dqsuffixes) - 1);
+	}
+	/* Add trailing $ */
+	appendStringInfoChar(&dqdelim, '$');
+
+	/* And finally produce the quoted literal into the output StringInfo */
+	appendStringInfo(buf, "%s%s%s", dqdelim.data, str, dqdelim.data);
+	pfree(dqdelim.data);
+	pfree(str);
+}
+
+/*
+ * Expand a JSON value as an integer quantity.
+ */
+static void
+expand_jsonval_number(StringInfo buf, JsonbValue *jsonval)
+{
+	char	   *strdatum;
+
+	Assert(jsonval->type == jbvNumeric);
+
+	strdatum = DatumGetCString(DirectFunctionCall1(numeric_out,
+												   NumericGetDatum(jsonval->val.numeric)));
+	appendStringInfoString(buf, strdatum);
+	pfree(strdatum);
+}
+
+/*
+ * Expand a JSON value as a role name.  If the 'is_public' element is set to
+ * true, PUBLIC is expanded (no quotes); otherwise, expand the given role name,
+ * quoting as an identifier.
+ */
+static void
+expand_jsonval_role(StringInfo buf, JsonbValue *jsonval)
+{
+	json_trivalue is_public;
+
+	is_public = find_bool_in_jsonbcontainer(jsonval->val.binary.data,
+											"is_public");
+	if (is_public == tv_true)
+		appendStringInfoString(buf, "PUBLIC");
+	else
+	{
+		char	   *rolename;
+
+		rolename = find_string_in_jsonbcontainer(jsonval->val.binary.data,
+												 "rolename", false, NULL);
+		if (rolename)
+		{
+			appendStringInfoString(buf, quote_identifier(rolename));
+			pfree(rolename);
+		}
+	}
+}
+
+/*
+ * Expand one JSON element into the output StringInfo according to the
+ * conversion specifier.  The element type is validated, and an error is raised
+ * if it doesn't match what we expect for the conversion specifier.
+ *
+ * Returns true, except for the formatted string case if no actual expansion
+ * was made (due to the "present" flag being set to "false").
+ */
+static bool
+expand_one_jsonb_element(StringInfo buf, char *param, JsonbValue *jsonval,
+						 convSpecifier specifier, const char *fmt)
+{
+	bool		string_expanded = true;
+	ErrorContextCallback sqlerrcontext;
+
+	/* If we were given a format string, setup an ereport() context callback */
+	if (fmt)
+	{
+		sqlerrcontext.callback = fmtstr_error_callback;
+		sqlerrcontext.arg = (void *) fmt;
+		sqlerrcontext.previous = error_context_stack;
+		error_context_stack = &sqlerrcontext;
+	}
+
+	if (!jsonval)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("element \"%s\" not found", param)));
+
+	switch (specifier)
+	{
+		case SpecIdentifier:
+			if (jsonval->type != jbvString)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("expected JSON string for %%I element \"%s\", got %d",
+								param, jsonval->type)));
+			expand_jsonval_identifier(buf, jsonval);
+			break;
+
+		case SpecDottedName:
+			if (jsonval->type != jbvBinary)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("expected JSON struct for %%D element \"%s\", got %d",
+								param, jsonval->type)));
+			expand_jsonval_dottedname(buf, jsonval);
+			break;
+
+		case SpecString:
+			if (jsonval->type != jbvString &&
+				jsonval->type != jbvBinary)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("expected JSON string or struct for %%s element \"%s\", got %d",
+								param, jsonval->type)));
+			string_expanded = expand_jsonval_string(buf, jsonval);
+			break;
+
+		case SpecStringLiteral:
+			if (jsonval->type != jbvString)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("expected JSON string for %%L element \"%s\", got %d",
+								param, jsonval->type)));
+			expand_jsonval_strlit(buf, jsonval);
+			break;
+
+		case SpecTypeName:
+			if (jsonval->type != jbvBinary)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("expected JSON struct for %%T element \"%s\", got %d",
+								param, jsonval->type)));
+			expand_jsonval_typename(buf, jsonval);
+			break;
+
+		case SpecOperatorName:
+			if (jsonval->type != jbvBinary)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("expected JSON struct for %%O element \"%s\", got %d",
+								param, jsonval->type)));
+			expand_jsonval_operator(buf, jsonval);
+			break;
+
+		case SpecNumber:
+			if (jsonval->type != jbvNumeric)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("expected JSON numeric for %%n element \"%s\", got %d",
+								param, jsonval->type)));
+			expand_jsonval_number(buf, jsonval);
+			break;
+
+		case SpecRole:
+			if (jsonval->type != jbvBinary)
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+						 errmsg("expected JSON struct for %%R element \"%s\", got %d",
+								param, jsonval->type)));
+			expand_jsonval_role(buf, jsonval);
+			break;
+	}
+
+	if (fmt)
+		error_context_stack = sqlerrcontext.previous;
+
+	return string_expanded;
+}
+
+/*
+ * Iterate on the elements of a JSON array, expanding each one into the output
+ * StringInfo per the given conversion specifier, separated by the given
+ * separator.
+ */
+static void
+expand_jsonb_array(StringInfo buf, char *param,
+				   JsonbValue *jsonarr, char *arraysep, convSpecifier specifier,
+				   const char *fmt)
+{
+	ErrorContextCallback sqlerrcontext;
+	JsonbContainer *container;
+	JsonbIterator *it;
+	JsonbValue	v;
+	int			type;
+	bool		first = true;
+	StringInfoData arrayelem;
+
+	/* If we were given a format string, setup an ereport() context callback */
+	if (fmt)
+	{
+		sqlerrcontext.callback = fmtstr_error_callback;
+		sqlerrcontext.arg = (void *) fmt;
+		sqlerrcontext.previous = error_context_stack;
+		error_context_stack = &sqlerrcontext;
+	}
+
+	if (!jsonarr)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("element \"%s\" not found", param)));
+
+	if (jsonarr->type != jbvBinary)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("element \"%s\" is not a JSON array", param)));
+
+	container = jsonarr->val.binary.data;
+	if (!JsonContainerIsArray(container))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("element \"%s\" is not a JSON array", param)));
+
+	initStringInfo(&arrayelem);
+
+	it = JsonbIteratorInit(container);
+	while ((type = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
+	{
+		if (type == WJB_ELEM)
+		{
+			resetStringInfo(&arrayelem);
+
+			if (expand_one_jsonb_element(&arrayelem, param, &v, specifier, NULL))
+			{
+				if (!first)
+					appendStringInfoString(buf, arraysep);
+
+				appendBinaryStringInfo(buf, arrayelem.data, arrayelem.len);
+				first = false;
+			}
+		}
+	}
+
+	if (fmt)
+		error_context_stack = sqlerrcontext.previous;
+}
+
+/*
+ * Workhorse for ddl_deparse_expand_command.
+ */
+char *
+deparse_ddl_json_to_string(char *json_str)
+{
+	Datum		d;
+	Jsonb	   *jsonb;
+	StringInfo	buf = (StringInfo) palloc0(sizeof(StringInfoData));
+
+	initStringInfo(buf);
+
+	d = DirectFunctionCall1(jsonb_in, PointerGetDatum(json_str));
+	jsonb = (Jsonb *) DatumGetPointer(d);
+
+	expand_fmt_recursive(buf, &jsonb->root);
+
+	return buf->data;
+}
+
+/*------
+ * Returns a formatted string from a JSON object.
+ *
+ * The starting point is the element named "fmt" (which must be a string).
+ * This format string may contain zero or more %-escapes, which consist of an
+ * element name enclosed in { }, possibly followed by a conversion modifier,
+ * followed by a conversion specifier.  Possible conversion specifiers are:
+ *
+ * %		expand to a literal %
+ * I		expand as a single, non-qualified identifier
+ * D		expand as a possibly-qualified identifier
+ * T		expand as a type name
+ * O		expand as an operator name
+ * L		expand as a string literal (quote using single quotes)
+ * s		expand as a simple string (no quoting)
+ * n		expand as a simple number (no quoting)
+ * R		expand as a role name (possibly quoted name, or PUBLIC)
+ *
+ * The element name may have an optional separator specification preceded
+ * by a colon.  Its presence indicates that the element is expected to be
+ * an array; the specified separator is used to join the array elements.
+ *------
+ */
+Datum
+ddl_deparse_expand_command(PG_FUNCTION_ARGS)
+{
+	text	   *json = PG_GETARG_TEXT_P(0);
+	char	   *json_str;
+
+	json_str = text_to_cstring(json);
+
+	PG_RETURN_TEXT_P(cstring_to_text(deparse_ddl_json_to_string(json_str)));
+}
+
+/*
+ * Error context callback for JSON format string expansion.
+ *
+ * XXX: indicate which element we're expanding, if applicable.
+ */
+static void
+fmtstr_error_callback(void *arg)
+{
+	errcontext("while expanding format string \"%s\"", (char *) arg);
+}
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index b380e39..1928e59 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -1856,6 +1856,7 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
 			case SCT_CreateOpClass:
 			case SCT_AlterTSConfig:
 			case SCT_SecurityLabel:
+			case SCT_CreateTableAs:
 				{
 					char	   *identity;
 					char	   *type;
@@ -1875,6 +1876,8 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
 						addr = cmd->d.atscfg.address;
 					else if (cmd->type == SCT_SecurityLabel)
 						addr = cmd->d.seclabel.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/meson.build b/src/backend/commands/meson.build
index 42cced9..2844d36 100644
--- a/src/backend/commands/meson.build
+++ b/src/backend/commands/meson.build
@@ -17,6 +17,8 @@ backend_sources += files(
   'copyto.c',
   'createas.c',
   'dbcommands.c',
+  'ddl_deparse.c',
+  'ddl_json.c',
   'define.c',
   'discard.c',
   'dropcmds.c',
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 5055956..e04de52 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -11939,4 +11939,11 @@
   proname => 'any_value_transfn', prorettype => 'anyelement',
   proargtypes => 'anyelement anyelement', prosrc => 'any_value_transfn' },
 
+{ oid => '4642', descr => 'deparse the DDL command into a JSON format string',
+  proname => 'ddl_deparse_to_json', prorettype => 'text',
+  proargtypes => 'pg_ddl_command', prosrc => 'ddl_deparse_to_json' },
+{ oid => '4643', descr => 'expand JSON format DDL to a plain text DDL command',
+  proname => 'ddl_deparse_expand_command', prorettype => 'text',
+  proargtypes => 'text', prosrc => 'ddl_deparse_expand_command' },
+
 ]
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 371aa0f..8589820 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2059,6 +2059,7 @@ typedef struct AlterTableStmt
 	List	   *cmds;			/* list of subcommands */
 	ObjectType	objtype;		/* type of object */
 	bool		missing_ok;		/* skip error if table missing */
+	bool        table_like;		/* internally generated for TableLikeClause */
 } AlterTableStmt;
 
 typedef enum AlterTableType
diff --git a/src/include/tcop/ddl_deparse.h b/src/include/tcop/ddl_deparse.h
new file mode 100644
index 0000000..1a2702c
--- /dev/null
+++ b/src/include/tcop/ddl_deparse.h
@@ -0,0 +1,22 @@
+/*-------------------------------------------------------------------------
+ *
+ * ddl_deparse.h
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/tcop/ddl_deparse.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DDL_DEPARSE_H
+#define DDL_DEPARSE_H
+
+#include "tcop/deparse_utility.h"
+
+extern char *deparse_utility_command(CollectedCommand *cmd, bool verbose_mode);
+extern char *deparse_ddl_json_to_string(char *jsonb);
+extern char *deparse_drop_command(const char *objidentity, const char *objecttype,
+								  DropBehavior behavior);
+
+#endif							/* DDL_DEPARSE_H */
diff --git a/src/include/tcop/deparse_utility.h b/src/include/tcop/deparse_utility.h
index a1e06da..9e262d7 100644
--- a/src/include/tcop/deparse_utility.h
+++ b/src/include/tcop/deparse_utility.h
@@ -30,7 +30,8 @@ typedef enum CollectedCommandType
 	SCT_AlterDefaultPrivileges,
 	SCT_CreateOpClass,
 	SCT_AlterTSConfig,
-	SCT_SecurityLabel
+	SCT_SecurityLabel,
+	SCT_CreateTableAs
 } CollectedCommandType;
 
 /*
@@ -40,6 +41,7 @@ typedef struct CollectedATSubcmd
 {
 	ObjectAddress address;		/* affected column, constraint, index, ... */
 	Node	   *parsetree;
+	char	   *usingexpr;
 } CollectedATSubcmd;
 
 typedef struct CollectedCommand
@@ -108,6 +110,13 @@ typedef struct CollectedCommand
 			ObjectAddress address;
 			char		 *provider;
 		}			seclabel;
+
+		/* CREATE TABLE AS */
+		struct
+		{
+			ObjectAddress address;
+			Node		 *real_create;
+		}			ctas;
 	}			d;
 
 	struct CollectedCommand *parent;	/* when nested */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 428689a..4a31818 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1622,6 +1622,9 @@ OSInfo
 OSSLCipher
 OSSLDigest
 OVERLAPPED
+ObjElem
+ObjTree
+ObjType
 ObjectAccessDrop
 ObjectAccessNamespaceSearch
 ObjectAccessPostAlter
@@ -3198,6 +3201,7 @@ compare_context
 config_var_value
 contain_aggs_of_level_context
 convert_testexpr_context
+convSpecifier
 copy_data_dest_cb
 copy_data_source_cb
 core_YYSTYPE
-- 
1.8.3.1



  [application/octet-stream] v80-0003-Support-DDL-deparse-of-the-rest-commands.patch (205.1K, 6-v80-0003-Support-DDL-deparse-of-the-rest-commands.patch)
  download | inline diff:
From d4ce2f1671a047abf21318e5d87e92fb3ed12e8f Mon Sep 17 00:00:00 2001
From: Ajin Cherian <ajinc@fast.au.fujitsu.com>
Date: Mon, 13 Mar 2023 23:41:58 -0400
Subject: [PATCH v80 3/8] Support DDL deparse of the rest commands.

    CREATE/DROP ACCESS METHOD
    CREATE/ALTER/DROP AGGREGATE
    CREATE/ALTER/DROP CAST
    CREATE/ALTER/DROP COLLATION
    COMMENT
    CREATE/ALTER/DROP CONVERSION
    ALTER DEFAULT PRIVILEGES
    CREATE/ALTER/DROP DOMAIN
    CREATE/ALTER/DROP EXTENSION
    CREATE/ALTER/DROP FOREIGN DATA WRAPPER
    CREATE/ALTER/DROP FOREIGN TABLE
    CREATE/ALTER FUNCTION/PROCEDURE
    GRANT
    CREATE/DROP INDEX
    CREATE/ALTER/DROP LANGUAGE
    CREATE/ALTER/DROP MATERIALIZED VIEW
    CREATE/DROP OPERATOR [CLASS/FAMILY]
    CREATE/ALTER/DROP PUBLICATION
    CREATE/ALTER/DROP POLICY
    REFRESH MATERIALIZED VIEW
    REVOKE
    ALTER/DROP ROUTINE
    CREATE/ALTER/DROP RULE
    CREATE/ALTER/DROP SCHEMA
    SECURITY LABEL
    CREATE/ALTER/DROP SEQUENCE
    CREATE/ALTER/DROP SERVER
    CREATE/ALTER/DROP STATISTICS
    CREATE/ALTER/DROP TEXT SEARCH CONFIGURATION/PARSER/DICTIONARY/TEMPLATE
    CREATE/DROP TRANSFORM
    CREATE/ALTER TRIGGER
    CREATE/ALTER/DROP TYPE
    CREATE/ALTER/DROP USER MAPPING
    CREATE/ALTER/DROP VIEW -- Note #4

(Note #3) Removed an undesirable 'on' from the identity string for TRANSFORM
in getObjectIdentityParts. This is needed to make deparse of DROP
TRANSFORM command work since 'on' is not present in the current
DROP TRANSFORM syntax. For example, the correct syntax is
DROP TRANSFORM trf FOR INT LANGUAGE SQL;
instead of DROP TRANSFORM trf FOR INT ON LANGUAGE SQL;

(Note #4) For VIEWSTMT, we created pg_get_viewdef_internal to get the
SELECT query of the pending VIEWSTMT. In the case that the CREATE VIEW command
is still in progress, we would need to search the system cache RULERELNAME to get the
rewrite rule of the view as oppose to querying pg_rewrite as in pg_get_viewdef_worker(),
the latter will return empty result.
---
 src/backend/commands/ddl_deparse.c | 6643 +++++++++++++++++++++++++++++++++++-
 src/include/tcop/ddl_deparse.h     |    2 +
 2 files changed, 6586 insertions(+), 59 deletions(-)

diff --git a/src/backend/commands/ddl_deparse.c b/src/backend/commands/ddl_deparse.c
index 4e248de..373aab7 100644
--- a/src/backend/commands/ddl_deparse.c
+++ b/src/backend/commands/ddl_deparse.c
@@ -58,6 +58,8 @@
 #include "catalog/pg_opfamily.h"
 #include "catalog/pg_policy.h"
 #include "catalog/pg_proc.h"
+#include "catalog/pg_publication_rel.h"
+#include "catalog/pg_publication_namespace.h"
 #include "catalog/pg_range.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_sequence.h"
@@ -70,6 +72,7 @@
 #include "catalog/pg_type.h"
 #include "catalog/pg_user_mapping.h"
 #include "commands/defrem.h"
+#include "commands/publicationcmds.h"
 #include "commands/sequence.h"
 #include "commands/tablespace.h"
 #include "foreign/foreign.h"
@@ -151,6 +154,7 @@ bool		verbose = true;
 
 static void append_array_object(ObjTree *tree, char *sub_fmt, List *array);
 static void append_bool_object(ObjTree *tree, char *sub_fmt, bool value);
+static void append_float_object(ObjTree *tree, char *sub_fmt, float8 value);
 static void append_null_object(ObjTree *tree, char *sub_fmt);
 static void append_object_object(ObjTree *tree, char *sub_fmt, ObjTree *value);
 static char *append_object_to_format_string(ObjTree *tree, char *sub_fmt);
@@ -160,10 +164,14 @@ static void append_string_object(ObjTree *tree, char *sub_fmt, char *name,
 static void format_type_detailed(Oid type_oid, int32 typemod,
 								 Oid *nspid, char **typname, char **typemodstr,
 								 bool *typarray);
+static List *FunctionGetDefaults(text *proargdefaults);
 static ObjElem *new_object(ObjType type, char *name);
 static ObjTree *new_objtree_for_qualname_id(Oid classId, Oid objectId);
+static ObjTree *new_objtree_for_rolespec(RoleSpec *spec);
 static ObjElem *new_object_object(ObjTree *value);
 static ObjTree *new_objtree_VA(char *fmt, int numobjs,...);
+static ObjTree *new_objtree(char *fmt);
+static ObjElem *new_string_object(char *value);
 static JsonbValue *objtree_to_jsonb_rec(ObjTree *tree, JsonbParseState *state);
 static void pg_get_indexdef_detailed(Oid indexrelid,
 									 char **index_am,
@@ -178,8 +186,18 @@ static ObjTree *deparse_ColumnDef(Relation relation, List *dpcontext, bool compo
 								  ColumnDef *coldef, bool is_alter, List **exprs);
 static ObjTree *deparse_ColumnIdentity(Oid seqrelid, char identity, bool alter_table);
 static ObjTree *deparse_ColumnSetOptions(AlterTableCmd *subcmd);
+static ObjTree *deparse_DefineStmt_Aggregate(Oid objectId, DefineStmt *define);
+static ObjTree *deparse_DefineStmt_Collation(Oid objectId, DefineStmt *define,
+											 ObjectAddress fromCollid);
+static ObjTree *deparse_DefineStmt_Operator(Oid objectId, DefineStmt *define);
+static ObjTree *deparse_DefineStmt_Type(Oid objectId, DefineStmt *define);
+static ObjTree *deparse_DefineStmt_TSConfig(Oid objectId, DefineStmt *define, ObjectAddress copied);
+static ObjTree *deparse_DefineStmt_TSParser(Oid objectId, DefineStmt *define);
+static ObjTree *deparse_DefineStmt_TSDictionary(Oid objectId, DefineStmt *define);
+static ObjTree *deparse_DefineStmt_TSTemplate(Oid objectId, DefineStmt *define);
 
 static ObjTree *deparse_DefElem(DefElem *elem, bool is_reset);
+static ObjTree *deparse_FunctionSet(VariableSetKind kind, char *name, char *value);
 static ObjTree *deparse_OnCommitClause(OnCommitAction option);
 static ObjTree *deparse_RelSetOptions(AlterTableCmd *subcmd);
 
@@ -188,6 +206,7 @@ static inline ObjElem *deparse_Seq_Cycle(Form_pg_sequence seqdata, bool alter_ta
 static inline ObjElem *deparse_Seq_IncrementBy(Form_pg_sequence seqdata, bool alter_table);
 static inline ObjElem *deparse_Seq_Minvalue(Form_pg_sequence seqdata, bool alter_table);
 static inline ObjElem *deparse_Seq_Maxvalue(Form_pg_sequence seqdata, bool alter_table);
+static ObjElem *deparse_Seq_OwnedBy(Oid sequenceId, bool alter_table);
 static inline ObjElem *deparse_Seq_Restart(int64 last_value);
 static inline ObjElem *deparse_Seq_Startwith(Form_pg_sequence seqdata, bool alter_table);
 static inline ObjElem *deparse_Seq_As(Form_pg_sequence seqdata);
@@ -199,10 +218,15 @@ static inline ObjElem *deparse_Type_Typmod_Out(Form_pg_type typForm);
 static inline ObjElem *deparse_Type_Analyze(Form_pg_type typForm);
 static inline ObjElem *deparse_Type_Subscript(Form_pg_type typForm);
 
+static ObjTree *deparse_FdwOptions(List *options, char *colname,
+								   bool altercoloptions);
+
 static List *deparse_InhRelations(Oid objectId);
 static List *deparse_TableElements(Relation relation, List *tableElements, List *dpcontext,
 								   bool typed, bool composite);
 
+static char *DomainGetDefault(HeapTuple domTup, bool missing_ok);
+
 /*
  * Append present as false to a tree.
  */
@@ -213,6 +237,42 @@ append_not_present(ObjTree *tree)
 }
 
 /*
+ * Append an int32 parameter to a tree.
+ */
+static void
+append_int_object(ObjTree *tree, char *sub_fmt, int32 value)
+{
+	ObjElem    *param;
+	char	   *object_name;
+
+	Assert(sub_fmt);
+
+	object_name = append_object_to_format_string(tree, sub_fmt);
+
+	param = new_object(ObjTypeInteger, object_name);
+	param->value.flt = value;
+	append_premade_object(tree, param);
+}
+
+/*
+ * Append a float8 parameter to a tree.
+ */
+static void
+append_float_object(ObjTree *tree, char *sub_fmt, float8 value)
+{
+	ObjElem    *param;
+	char	   *object_name;
+
+	Assert(sub_fmt);
+
+	object_name = append_object_to_format_string(tree, sub_fmt);
+
+	param = new_object(ObjTypeFloat, object_name);
+	param->value.flt = value;
+	append_premade_object(tree, param);
+}
+
+/*
  * Append an array parameter to a tree.
  */
 static void
@@ -419,6 +479,34 @@ append_string_object(ObjTree *tree, char *sub_fmt, char * object_name,
 }
 
 /*
+ * Append a NULL-or-quoted-literal clause.  Useful for COMMENT and SECURITY
+ * LABEL.
+ *
+ * Verbose syntax
+ * %{null}s %{literal}s
+ */
+static void
+append_literal_or_null(ObjTree *parent, char *elemname, char *value)
+{
+	ObjTree    *top;
+	ObjTree    *part;
+
+	top = new_objtree("");
+	part = new_objtree_VA("NULL", 1,
+						  "present", ObjTypeBool, !value);
+	append_object_object(top, "%{null}s", part);
+
+	part = new_objtree_VA("", 1,
+						  "present", ObjTypeBool, value != NULL);
+
+	if (value)
+		append_string_object(part, "%{value}L", "value", value);
+	append_object_object(top, "%{literal}s", part);
+
+	append_object_object(parent, elemname, top);
+}
+
+/*
  * Similar to format_type_extended, except we return each bit of information
  * separately:
  *
@@ -521,6 +609,31 @@ format_type_detailed(Oid type_oid, int32 typemod,
 }
 
 /*
+ * Return the default values of arguments to a function, as a list of
+ * deparsed expressions.
+ */
+static List *
+FunctionGetDefaults(text *proargdefaults)
+{
+	List	   *nodedefs;
+	List	   *strdefs = NIL;
+	ListCell   *cell;
+
+	nodedefs = (List *) stringToNode(text_to_cstring(proargdefaults));
+	if (!IsA(nodedefs, List))
+		elog(ERROR, "proargdefaults is not a list");
+
+	foreach(cell, nodedefs)
+	{
+		Node	   *onedef = lfirst(cell);
+
+		strdefs = lappend(strdefs, deparse_expression(onedef, NIL, false, false));
+	}
+
+	return strdefs;
+}
+
+/*
  * Return the string representation of the given RELPERSISTENCE value.
  */
 static char *
@@ -710,6 +823,57 @@ new_objtree_for_type(Oid typeId, int32 typmod)
 }
 
 /*
+ * Helper routine for %{}R objects, with role specified by RoleSpec node.
+ * Special values such as ROLESPEC_CURRENT_USER are expanded to their final
+ * names.
+ */
+static ObjTree *
+new_objtree_for_rolespec(RoleSpec *spec)
+{
+	char	   *roletype;
+
+	if (spec->roletype != ROLESPEC_PUBLIC)
+		roletype = get_rolespec_name(spec);
+	else
+		roletype = pstrdup("");
+
+	return new_objtree_VA(NULL, 2,
+						  "is_public", ObjTypeBool, spec->roletype == ROLESPEC_PUBLIC,
+						  "rolename", ObjTypeString, roletype);
+}
+
+/*
+ * Helper routine for %{}R objects, with role specified by OID. (ACL_ID_PUBLIC
+ * means to use "public").
+ */
+static ObjTree *
+new_objtree_for_role_id(Oid roleoid)
+{
+	ObjTree    *role;
+
+	if (roleoid != ACL_ID_PUBLIC)
+	{
+		HeapTuple	roltup;
+		char	   *role_name;
+
+		roltup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleoid));
+		if (!HeapTupleIsValid(roltup))
+			elog(ERROR, "cache lookup failed for role with OID %u", roleoid);
+
+		role_name = NameStr(((Form_pg_authid) GETSTRUCT(roltup))->rolname);
+		role = new_objtree_VA("%{rolename}I", 1,
+							  "rolename", ObjTypeString, pstrdup(role_name));
+
+		ReleaseSysCache(roltup);
+	}
+	else
+		role = new_objtree_VA("%{rolename}I", 1,
+							  "rolename", ObjTypeString, "public");
+
+	return role;
+}
+
+/*
  * Allocate a new object tree to store parameter values -- varargs version.
  *
  * The "fmt" argument is used to append as a "fmt" element in the output blob.
@@ -787,6 +951,22 @@ new_objtree_VA(char *fmt, int numobjs,...)
 }
 
 /*
+ * Allocate a new string object.
+ */
+static ObjElem *
+new_string_object(char *value)
+{
+	ObjElem    *param;
+
+	Assert(value);
+
+	param = new_object(ObjTypeString, NULL);
+	param->value.string = value;
+
+	return param;
+}
+
+/*
  * Process the pre-built format string from the ObjTree into the output parse
  * state.
  */
@@ -1922,6 +2102,83 @@ deparse_Seq_Minvalue(Form_pg_sequence seqdata, bool alter_table)
 }
 
 /*
+ * Deparse the sequence OWNED BY command.
+ *
+ * Verbose syntax
+ * OWNED BY %{owner}D
+ */
+static ObjElem *
+deparse_Seq_OwnedBy(Oid sequenceId, bool alter_table)
+{
+	ObjTree    *ret = NULL;
+	Relation	depRel;
+	SysScanDesc scan;
+	ScanKeyData keys[3];
+	HeapTuple	tuple;
+
+	depRel = table_open(DependRelationId, AccessShareLock);
+	ScanKeyInit(&keys[0],
+				Anum_pg_depend_classid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(RelationRelationId));
+	ScanKeyInit(&keys[1],
+				Anum_pg_depend_objid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(sequenceId));
+	ScanKeyInit(&keys[2],
+				Anum_pg_depend_objsubid,
+				BTEqualStrategyNumber, F_INT4EQ,
+				Int32GetDatum(0));
+
+	scan = systable_beginscan(depRel, DependDependerIndexId, true,
+							  NULL, 3, keys);
+	while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+	{
+		Oid			ownerId;
+		Form_pg_depend depform;
+		ObjTree    *tmp_obj;
+		char	   *colname;
+
+		depform = (Form_pg_depend) GETSTRUCT(tuple);
+
+		/* Only consider AUTO dependencies on pg_class */
+		if (depform->deptype != DEPENDENCY_AUTO)
+			continue;
+		if (depform->refclassid != RelationRelationId)
+			continue;
+		if (depform->refobjsubid <= 0)
+			continue;
+
+		ownerId = depform->refobjid;
+		colname = get_attname(ownerId, depform->refobjsubid, false);
+		if (colname == NULL)
+			continue;
+
+		tmp_obj = new_objtree_for_qualname_id(RelationRelationId, ownerId);
+		append_string_object(tmp_obj, "attrname", "attrname", colname);
+		ret = new_objtree_VA("OWNED BY %{owner}D", 2,
+							 "clause", ObjTypeString, "owned",
+							 "owner", ObjTypeObject, tmp_obj);
+	}
+
+	systable_endscan(scan);
+	relation_close(depRel, AccessShareLock);
+
+	/*
+	 * If there's no owner column, emit an empty OWNED BY element, set up so
+	 * that it won't print anything.
+	 */
+	if (!ret)
+		/* XXX this shouldn't happen ... */
+		ret = new_objtree_VA("OWNED BY %{owner}D", 3,
+							 "clause", ObjTypeString, "owned",
+							 "owner", ObjTypeNull,
+							 "present", ObjTypeBool, false);
+
+	return new_object_object(ret);
+}
+
+/*
  * Deparse the sequence RESTART option.
  *
  * Verbose syntax
@@ -2588,7 +2845,7 @@ deparse_AlterRelation(CollectedCommand *cmd)
 
 	Assert(cmd->type == SCT_AlterTable);
 	stmt = (AlterTableStmt *) cmd->parsetree;
-	Assert(IsA(stmt, AlterTableStmt));
+	Assert(IsA(stmt, AlterTableStmt) || IsA(stmt, ViewStmt));
 
 	/*
 	 * ALTER TABLE subcommands generated for TableLikeClause is processed in
@@ -3064,13 +3321,12 @@ deparse_AlterRelation(CollectedCommand *cmd)
 				}
 				break;
 
-#ifdef TODOLIST
 			case AT_AlterColumnGenericOptions:
 				tmp_obj = deparse_FdwOptions((List *) subcmd->def,
-											subcmd->name);
+											subcmd->name, true);
 				subcmds = lappend(subcmds, new_object_object(tmp_obj));
 				break;
-#endif
+
 			case AT_ChangeOwner:
 				tmp_obj = new_objtree_VA("OWNER TO %{owner}I", 2,
 										"type", ObjTypeString, "change owner",
@@ -3462,87 +3718,6338 @@ deparse_drop_command(const char *objidentity, const char *objecttype,
 }
 
 /*
- * Handle deparsing of simple commands.
+ * Deparse an AlterCollationStmt (ALTER COLLATION)
  *
- * This function should cover all cases handled in ProcessUtilitySlow.
+ * Given a collation OID and the parse tree that created it, return an ObjTree
+ * representing the alter command.
+ *
+ * Verbose syntax:
+ * ALTER COLLATION %{identity}O REFRESH VERSION
  */
 static ObjTree *
-deparse_simple_command(CollectedCommand *cmd)
+deparse_AlterCollation(Oid objectId, Node *parsetree)
 {
-	Oid			objectId;
-	Node	   *parsetree;
+	ObjTree    *ret;
+	HeapTuple	colTup;
+	Form_pg_collation colForm;
 
-	Assert(cmd->type == SCT_Simple);
+	colTup = SearchSysCache1(COLLOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(colTup))
+		elog(ERROR, "cache lookup failed for collation with OID %u", objectId);
+	colForm = (Form_pg_collation) GETSTRUCT(colTup);
 
-	parsetree = cmd->parsetree;
-	objectId = cmd->d.simple.address.objectId;
+	ret = new_objtree_VA("ALTER COLLATION %{identity}O REFRESH VERSION", 1,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(colForm->collnamespace,
+												  NameStr(colForm->collname)));
 
-	if (cmd->in_extension && (nodeTag(parsetree) != T_CreateExtensionStmt))
-		return NULL;
+	ReleaseSysCache(colTup);
 
-	/* This switch needs to handle everything that ProcessUtilitySlow does */
-	switch (nodeTag(parsetree))
-	{
-		case T_CreateSeqStmt:
-			return deparse_CreateSeqStmt(objectId, parsetree);
+	return ret;
+}
 
-		case T_CreateStmt:
-			return deparse_CreateStmt(objectId, parsetree);
+/*
+ * Handle deparsing setting of Function
+ *
+ * Verbose syntax
+ * RESET ALL
+ * OR
+ * SET %{set_name}I TO %{set_value}s
+ * OR
+ * RESET %{set_name}I
+ */
+static ObjTree *
+deparse_FunctionSet(VariableSetKind kind, char *name, char *value)
+{
+	ObjTree    *ret;
 
-		case T_IndexStmt:
-			return deparse_IndexStmt(objectId, parsetree);
+	if (kind == VAR_RESET_ALL)
+		ret = new_objtree("RESET ALL");
+	else if (kind == VAR_SET_VALUE)
+	{
+		ret = new_objtree_VA("SET %{set_name}I", 1,
+							 "set_name", ObjTypeString, name);
 
-		default:
-			elog(LOG, "unrecognized node type in deparse command: %d",
-				 (int) nodeTag(parsetree));
+		/*
+		 * Some GUC variable names are 'LIST' type and hence must not be
+		 * quoted.
+		 */
+		if (GetConfigOptionFlags(name, true) & GUC_LIST_QUOTE)
+			append_string_object(ret, "TO %{set_value}s", "set_value", value);
+		else
+			append_string_object(ret, "TO %{set_value}L", "set_value", value);
 	}
+	else
+		ret = new_objtree_VA("RESET %{set_name}I", 1,
+							 "set_name", ObjTypeString, name);
 
-	return NULL;
+	return ret;
 }
 
 /*
- * Workhorse to deparse a CollectedCommand.
+ * Deparse an AlterFunctionStmt (ALTER FUNCTION/ROUTINE/PROCEDURE)
+ *
+ * Given a function OID and the parse tree that created it, return an ObjTree
+ * representing the alter command.
+ *
+ * Verbose syntax:
+ * ALTER FUNCTION/ROUTINE/PROCEDURE %{signature}s %{definition: }s
  */
-char *
-deparse_utility_command(CollectedCommand *cmd, bool verbose_mode)
+static ObjTree *
+deparse_AlterFunction(Oid objectId, Node *parsetree)
 {
-	OverrideSearchPath *overridePath;
-	MemoryContext oldcxt;
-	MemoryContext tmpcxt;
-	ObjTree    *tree;
-	char	   *command = NULL;
-	StringInfoData str;
+	AlterFunctionStmt *node = (AlterFunctionStmt *) parsetree;
+	ObjTree    *ret;
+	ObjTree    *sign;
+	HeapTuple	procTup;
+	Form_pg_proc procForm;
+	List	   *params = NIL;
+	List	   *elems = NIL;
+	ListCell   *cell;
+	int			i;
+
+	/* Get the pg_proc tuple */
+	procTup = SearchSysCache1(PROCOID, objectId);
+	if (!HeapTupleIsValid(procTup))
+		elog(ERROR, "cache lookup failed for function with OID %u", objectId);
+	procForm = (Form_pg_proc) GETSTRUCT(procTup);
+
+	if (procForm->prokind == PROKIND_PROCEDURE)
+		ret = new_objtree("ALTER PROCEDURE");
+	else
+		ret = new_objtree(node->objtype == OBJECT_ROUTINE ?
+						  "ALTER ROUTINE" : "ALTER FUNCTION");
 
 	/*
-	 * Allocate everything done by the deparsing routines into a temp context,
-	 * to avoid having to sprinkle them with memory handling code, but
-	 * allocate the output StringInfo before switching.
+	 * ALTER FUNCTION does not change signature so we can use catalog to get
+	 * input type Oids.
 	 */
-	initStringInfo(&str);
-	tmpcxt = AllocSetContextCreate(CurrentMemoryContext,
-								   "deparse ctx",
-								   ALLOCSET_DEFAULT_MINSIZE,
-								   ALLOCSET_DEFAULT_INITSIZE,
-								   ALLOCSET_DEFAULT_MAXSIZE);
-	oldcxt = MemoryContextSwitchTo(tmpcxt);
+	for (i = 0; i < procForm->pronargs; i++)
+	{
+		ObjTree    *tmp_obj;
+
+		tmp_obj = new_objtree_VA("%{type}T", 1,
+								"type", ObjTypeObject,
+								new_objtree_for_type(procForm->proargtypes.values[i], -1));
+		params = lappend(params, new_object_object(tmp_obj));
+	}
+
+	sign = new_objtree_VA("%{identity}D (%{arguments:, }s)", 2,
+						  "identity", ObjTypeObject,
+						  new_objtree_for_qualname_id(ProcedureRelationId, objectId),
+						  "arguments", ObjTypeArray, params);
+
+	append_object_object(ret, "%{signature}s", sign);
+
+	foreach(cell, node->actions)
+	{
+		DefElem    *defel = (DefElem *) lfirst(cell);
+		ObjTree    *tmp_obj = NULL;
+
+		if (strcmp(defel->defname, "volatility") == 0)
+			tmp_obj = new_objtree(strVal(defel->arg));
+		else if (strcmp(defel->defname, "strict") == 0)
+			tmp_obj = new_objtree(boolVal(defel->arg) ?
+								 "RETURNS NULL ON NULL INPUT" :
+								 "CALLED ON NULL INPUT");
+		else if (strcmp(defel->defname, "security") == 0)
+			tmp_obj = new_objtree(boolVal(defel->arg) ?
+								 "SECURITY DEFINER" : "SECURITY INVOKER");
+		else if (strcmp(defel->defname, "leakproof") == 0)
+			tmp_obj = new_objtree(boolVal(defel->arg) ?
+								 "LEAKPROOF" : "NOT LEAKPROOF");
+		else if (strcmp(defel->defname, "cost") == 0)
+			tmp_obj = new_objtree_VA("COST %{cost}n", 1,
+									"cost", ObjTypeFloat,
+									defGetNumeric(defel));
+		else if (strcmp(defel->defname, "rows") == 0)
+		{
+			tmp_obj = new_objtree("ROWS");
+			if (defGetNumeric(defel) == 0)
+				append_not_present(tmp_obj);
+			else
+				append_float_object(tmp_obj, "%{rows}n",
+									defGetNumeric(defel));
+		}
+		else if (strcmp(defel->defname, "set") == 0)
+		{
+			VariableSetStmt *sstmt = (VariableSetStmt *) defel->arg;
+			char	   *value = ExtractSetVariableArgs(sstmt);
+
+			tmp_obj = deparse_FunctionSet(sstmt->kind, sstmt->name, value);
+		}
+		else if (strcmp(defel->defname, "support") == 0)
+		{
+			Oid			argtypes[1];
+
+			tmp_obj = new_objtree("SUPPORT");
+
+			Assert(procForm->prosupport);
+
+			/*
+			 * We should qualify the support function's name if it wouldn't be
+			 * resolved by lookup in the current search path.
+			 */
+			argtypes[0] = INTERNALOID;
+			append_string_object(tmp_obj, "%{name}s", "name",
+								 generate_function_name(procForm->prosupport, 1,
+														NIL, argtypes,
+														false, NULL,
+														EXPR_KIND_NONE));
+		}
+		else if (strcmp(defel->defname, "parallel") == 0)
+			tmp_obj = new_objtree_VA("PARALLEL %{value}s", 1,
+									"value", ObjTypeString, strVal(defel->arg));
+
+		elems = lappend(elems, new_object_object(tmp_obj));
+	}
+
+	append_array_object(ret, "%{definition: }s", elems);
+
+	ReleaseSysCache(procTup);
+
+	return ret;
+}
+
+/*
+ * Deparse an AlterObjectSchemaStmt (ALTER ... SET SCHEMA command)
+ *
+ * Given the object address and the parse tree that created it, return an
+ * ObjTree representing the alter command.
+ *
+ * Verbose syntax
+ * ALTER %s %{identity}s SET SCHEMA %{newschema}I
+ */
+static ObjTree *
+deparse_AlterObjectSchemaStmt(ObjectAddress address, Node *parsetree,
+							  ObjectAddress old_schema)
+{
+	AlterObjectSchemaStmt *node = (AlterObjectSchemaStmt *) parsetree;
+	char	   *identity;
+	char	   *new_schema = node->newschema;
+	char	   *old_schname;
+	char	   *ident;
 
 	/*
-	 * Many routines underlying this one will invoke ruleutils.c functionality
-	 * to obtain deparsed versions of expressions.  In such results, we want
-	 * all object names to be qualified, 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.
+	 * Since the command has already taken place from the point of view of
+	 * catalogs, getObjectIdentity returns the object name with the already
+	 * changed schema.  The output of our deparsing must return the original
+	 * schema name, however, so we chop the schema name off the identity
+	 * string and then prepend the quoted schema name.
+	 *
+	 * XXX This is pretty clunky. Can we do better?
 	 */
-	overridePath = GetOverrideSearchPath(CurrentMemoryContext);
-	overridePath->schemas = NIL;
-	overridePath->addCatalog = false;
-	overridePath->addTemp = true;
-	PushOverrideSearchPath(overridePath);
+	identity = getObjectIdentity(&address, false);
+	old_schname = get_namespace_name(old_schema.objectId);
+	if (!old_schname)
+		elog(ERROR, "cache lookup failed for schema with OID %u",
+			 old_schema.objectId);
+
+	ident = psprintf("%s%s", quote_identifier(old_schname),
+					 identity + strlen(quote_identifier(new_schema)));
+
+	return new_objtree_VA("ALTER %{objtype}s %{identity}s SET SCHEMA %{newschema}I", 3,
+						  "objtype", ObjTypeString,
+						  stringify_objtype(node->objectType, false),
+						  "identity", ObjTypeString, ident,
+						  "newschema", ObjTypeString, new_schema);
+}
 
-	verbose = verbose_mode;
+/*
+ * Deparse a GRANT/REVOKE command.
+ *
+ * Verbose syntax
+ * GRANT %{privileges:, }s ON" %{objtype}s %{privtarget:, }s TO %{grantees:, }s
+ * %{grant_option}s GRANTED BY %{rolename}s
+ * 		OR
+ * REVOKE %{privileges:, }s ON" %{objtype}s %{privtarget:, }s
+ * FROM %{grantees:, }s %{grant_option}s %{cascade}s
+ */
+static ObjTree *
+deparse_GrantStmt(CollectedCommand *cmd)
+{
+	InternalGrant *istmt;
+	ObjTree    *ret;
+	List	   *list = NIL;
+	ListCell   *cell;
+	Oid			classId;
+	ObjTree    *tmp;
 
-	switch (cmd->type)
+	/* Don't deparse SQL commands generated while creating extension */
+	if (cmd->in_extension)
+		return NULL;
+
+	istmt = cmd->d.grant.istmt;
+
+	/*
+	 * If there are no objects from "ALL ... IN SCHEMA" to be granted, then
+	 * nothing to do.
+	 */
+	if (istmt->objects == NIL)
+		return NULL;
+
+	switch (istmt->objtype)
+	{
+		case OBJECT_COLUMN:
+		case OBJECT_TABLE:
+		case OBJECT_SEQUENCE:
+			classId = RelationRelationId;
+			break;
+		case OBJECT_DOMAIN:
+		case OBJECT_TYPE:
+			classId = TypeRelationId;
+			break;
+		case OBJECT_FDW:
+			classId = ForeignDataWrapperRelationId;
+			break;
+		case OBJECT_FOREIGN_SERVER:
+			classId = ForeignServerRelationId;
+			break;
+		case OBJECT_FUNCTION:
+		case OBJECT_PROCEDURE:
+		case OBJECT_ROUTINE:
+			classId = ProcedureRelationId;
+			break;
+		case OBJECT_LANGUAGE:
+			classId = LanguageRelationId;
+			break;
+		case OBJECT_LARGEOBJECT:
+			classId = LargeObjectRelationId;
+			break;
+		case OBJECT_SCHEMA:
+			classId = NamespaceRelationId;
+			break;
+		case OBJECT_DATABASE:
+		case OBJECT_TABLESPACE:
+			classId = InvalidOid;
+			elog(ERROR, "global objects not supported");
+			break;
+		default:
+			elog(ERROR, "invalid OBJECT value %d", istmt->objtype);
+	}
+
+	/* GRANT TO or REVOKE FROM */
+	ret = new_objtree(istmt->is_grant ? "GRANT" : "REVOKE");
+
+	/* Build a list of privileges to grant/revoke */
+	if (istmt->all_privs)
+	{
+		tmp = new_objtree("ALL PRIVILEGES");
+		list = list_make1(new_object_object(tmp));
+	}
+	else
+	{
+		char *priv;
+		if (istmt->privileges & ACL_INSERT)
+		{
+			priv = (char *)privilege_to_string(ACL_INSERT);
+			list = lappend(list, new_string_object(priv));
+		}
+		if (istmt->privileges & ACL_SELECT)
+		{
+			priv = (char *)privilege_to_string(ACL_SELECT);
+			list = lappend(list, new_string_object(priv));
+		}
+		if (istmt->privileges & ACL_UPDATE)
+		{
+			priv = (char *)privilege_to_string(ACL_UPDATE);
+			list = lappend(list, new_string_object(priv));
+		}
+		if (istmt->privileges & ACL_DELETE)
+		{
+			priv = (char *)privilege_to_string(ACL_DELETE);
+			list = lappend(list, new_string_object(priv));
+		}
+		if (istmt->privileges & ACL_TRUNCATE)
+		{
+			priv = (char *)privilege_to_string(ACL_TRUNCATE);
+			list = lappend(list, new_string_object(priv));
+		}
+		if (istmt->privileges & ACL_REFERENCES)
+		{
+			priv = (char *)privilege_to_string(ACL_REFERENCES);
+			list = lappend(list, new_string_object(priv));
+		}
+		if (istmt->privileges & ACL_TRIGGER)
+		{
+			priv = (char *)privilege_to_string(ACL_TRIGGER);
+			list = lappend(list, new_string_object(priv));
+		}
+		if (istmt->privileges & ACL_EXECUTE)
+		{
+			priv = (char *)privilege_to_string(ACL_EXECUTE);
+			list = lappend(list, new_string_object(priv));
+		}
+		if (istmt->privileges & ACL_USAGE)
+		{
+			priv = (char *)privilege_to_string(ACL_USAGE);
+			list = lappend(list, new_string_object(priv));
+		}
+		if (istmt->privileges & ACL_CREATE)
+		{
+			priv = (char *)privilege_to_string(ACL_CREATE);
+			list = lappend(list, new_string_object(priv));
+		}
+		if (istmt->privileges & ACL_CREATE_TEMP)
+		{
+			priv = (char *)privilege_to_string(ACL_CREATE_TEMP);
+			list = lappend(list, new_string_object(priv));
+		}
+		if (istmt->privileges & ACL_CONNECT)
+		{
+			priv = (char *)privilege_to_string(ACL_CONNECT);
+			list = lappend(list, new_string_object(priv));
+		}
+		if (istmt->privileges & ACL_MAINTAIN)
+		{
+			priv = (char *)privilege_to_string(ACL_MAINTAIN);
+			list = lappend(list, new_string_object(priv));
+		}
+
+		if (!istmt->is_grant && istmt->grant_option)
+			append_string_object(ret, "%{grant_option}s", "grant_option",
+								 istmt->grant_option ? "GRANT OPTION FOR" : "");
+
+		if (istmt->col_privs != NIL)
+		{
+			ListCell   *ocell;
+
+			foreach(ocell, istmt->col_privs)
+			{
+				AccessPriv *priv = lfirst(ocell);
+				List	   *cols = NIL;
+
+				foreach(cell, priv->cols)
+				{
+					String	   *colname = lfirst_node(String, cell);
+
+					cols = lappend(cols,
+								   new_string_object(strVal(colname)));
+				}
+
+				tmp = new_objtree_VA("(%{cols:, }s) %{priv}s", 2,
+									 "cols", ObjTypeArray, cols,
+									 "priv", ObjTypeString,
+									  priv->priv_name ? priv->priv_name : "ALL PRIVILEGES");
+
+				list = lappend(list, new_object_object(tmp));
+			}
+		}
+	}
+	append_array_object(ret, "%{privileges:, }s ON", list);
+
+	append_string_object(ret, "%{objtype}s", "objtype",
+						 (char *)stringify_objtype(istmt->objtype, true));
+
+	/* Target objects.  We use object identities here */
+	list = NIL;
+	foreach(cell, istmt->objects)
+	{
+		Oid			objid = lfirst_oid(cell);
+		ObjectAddress addr;
+
+		addr.classId = classId;
+		addr.objectId = objid;
+		addr.objectSubId = 0;
+
+		tmp = new_objtree_VA("%{identity}s", 1,
+							 "identity", ObjTypeString,
+							 getObjectIdentity(&addr, false));
+
+		list = lappend(list, new_object_object(tmp));
+	}
+	append_array_object(ret, "%{privtarget:, }s", list);
+
+	append_format_string(ret, istmt->is_grant ? "TO" : "FROM");
+
+	/* List of grantees */
+	list = NIL;
+	foreach(cell, istmt->grantees)
+	{
+		Oid			grantee = lfirst_oid(cell);
+
+		tmp = new_objtree_for_role_id(grantee);
+		list = lappend(list, new_object_object(tmp));
+	}
+
+	append_array_object(ret, "%{grantees:, }s", list);
+
+	/* The wording of the grant option is variable ... */
+	if (istmt->is_grant)
+		append_string_object(ret, "%{grant_option}s", "grant_option",
+							 istmt->grant_option ? "WITH GRANT OPTION" : "");
+
+	if (istmt->grantor_uid)
+	{
+		HeapTuple	roltup;
+		char	   *rolename;
+
+		roltup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(istmt->grantor_uid));
+		if (!HeapTupleIsValid(roltup))
+			elog(ERROR, "cache lookup failed for role with OID %u",
+				 istmt->grantor_uid);
+
+		rolename = NameStr(((Form_pg_authid) GETSTRUCT(roltup))->rolname);
+		append_string_object(ret, "GRANTED BY %{rolename}s",
+							 "rolename", rolename);
+		ReleaseSysCache(roltup);
+	}
+
+	if (!istmt->is_grant)
+		append_string_object(ret, "%{cascade}s", "cascade",
+							 istmt->behavior == DROP_CASCADE ? "CASCADE" : "");
+
+	return ret;
+}
+
+/*
+ * Deparse an AlterOperatorStmt (ALTER OPERATOR ... SET ...).
+ *
+ * Given an operator OID and the parse tree that created it, return an ObjTree
+ * representing the alter command.
+ *
+ * Verbose syntax
+ * ALTER OPERATOR %{identity}O (%{left_type}T, %{right_type}T)
+ * SET (%{elems:, }s)
+ */
+static ObjTree *
+deparse_AlterOperatorStmt(Oid objectId, Node *parsetree)
+{
+	HeapTuple	oprTup;
+	AlterOperatorStmt *node = (AlterOperatorStmt *) parsetree;
+	ObjTree    *ret;
+	Form_pg_operator oprForm;
+	ListCell   *cell;
+	List	   *list = NIL;
+
+	oprTup = SearchSysCache1(OPEROID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(oprTup))
+		elog(ERROR, "cache lookup failed for operator with OID %u", objectId);
+	oprForm = (Form_pg_operator) GETSTRUCT(oprTup);
+
+	ret = new_objtree_VA("ALTER OPERATOR %{identity}O", 1,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(oprForm->oprnamespace,
+												  NameStr(oprForm->oprname)));
+
+	/* LEFTARG */
+	if (OidIsValid(oprForm->oprleft))
+		append_object_object(ret, "(%{left_type}T",
+							 new_objtree_for_type(oprForm->oprleft, -1));
+	else
+		append_string_object(ret, "(%{left_type}s", "left_type", "NONE");
+
+	/* RIGHTARG */
+	Assert(OidIsValid(oprForm->oprleft));
+	append_object_object(ret, ", %{right_type}T)",
+						 new_objtree_for_type(oprForm->oprright, -1));
+
+	foreach(cell, node->options)
+	{
+		DefElem    *elem = (DefElem *) lfirst(cell);
+		ObjTree    *tmp_obj = NULL;
+
+		if (strcmp(elem->defname, "restrict") == 0)
+		{
+			tmp_obj = new_objtree_VA("RESTRICT=", 1,
+									"clause", ObjTypeString, "restrict");
+			if (OidIsValid(oprForm->oprrest))
+				append_object_object(tmp_obj, "%{procedure}D",
+									 new_objtree_for_qualname_id(ProcedureRelationId,
+																 oprForm->oprrest));
+			else
+				append_string_object(tmp_obj, "%{procedure}s", "procedure",
+									 "NONE");
+		}
+		else if (strcmp(elem->defname, "join") == 0)
+		{
+			tmp_obj = new_objtree_VA("JOIN=", 1,
+									"clause", ObjTypeString, "join");
+			if (OidIsValid(oprForm->oprjoin))
+				append_object_object(tmp_obj, "%{procedure}D",
+									 new_objtree_for_qualname_id(ProcedureRelationId,
+																 oprForm->oprjoin));
+			else
+				append_string_object(tmp_obj, "%{procedure}s", "procedure",
+									 "NONE");
+		}
+
+		Assert(tmp_obj);
+		list = lappend(list, new_object_object(tmp_obj));
+	}
+
+	append_array_object(ret, "SET (%{elems:, }s)", list);
+
+	ReleaseSysCache(oprTup);
+
+	return ret;
+}
+
+/*
+ * Deparse an ALTER OPERATOR FAMILY ADD/DROP command.
+ *
+ * Given the CollectedCommand, return an ObjTree representing the Alter
+ * Operator command.
+ *
+ * Verbose syntax
+ * ALTER OPERATOR FAMILY %{identity}D USING %{amname}I ADD/DROP %{items:,}s
+ */
+static ObjTree *
+deparse_AlterOpFamily(CollectedCommand *cmd)
+{
+	ObjTree    *ret;
+	AlterOpFamilyStmt *stmt = (AlterOpFamilyStmt *) cmd->parsetree;
+	HeapTuple	ftp;
+	Form_pg_opfamily opfForm;
+	List	   *list = NIL;
+	ListCell   *cell;
+
+	/* Don't deparse SQL commands generated while creating extension */
+	if (cmd->in_extension)
+		return NULL;
+
+	ftp = SearchSysCache1(OPFAMILYOID,
+						  ObjectIdGetDatum(cmd->d.opfam.address.objectId));
+	if (!HeapTupleIsValid(ftp))
+		elog(ERROR, "cache lookup failed for operator family with OID %u",
+			 cmd->d.opfam.address.objectId);
+	opfForm = (Form_pg_opfamily) GETSTRUCT(ftp);
+
+	ret = new_objtree_VA("ALTER OPERATOR FAMILY %{identity}D USING %{amname}I", 2,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(opfForm->opfnamespace,
+												  NameStr(opfForm->opfname)),
+						 "amname", ObjTypeString, stmt->amname);
+
+	foreach(cell, cmd->d.opfam.operators)
+	{
+		OpFamilyMember *oper = lfirst(cell);
+		ObjTree    *tmp_obj;
+
+		/*
+		 * Verbose syntax
+		 *
+		 * OPERATOR %{num}n %{operator}O(%{ltype}T, %{rtype}T) %{purpose}s
+		 */
+		tmp_obj = new_objtree_VA("OPERATOR %{num}n", 1,
+								"num", ObjTypeInteger, oper->number);
+
+		/* Add the operator name; the DROP case doesn't have this */
+		if (!stmt->isDrop)
+			append_object_object(tmp_obj, "%{operator}O",
+								 new_objtree_for_qualname_id(OperatorRelationId,
+															 oper->object));
+
+		/* Add the types */
+		append_object_object(tmp_obj, "(%{ltype}T,",
+							 new_objtree_for_type(oper->lefttype, -1));
+		append_object_object(tmp_obj, "%{rtype}T)",
+							 new_objtree_for_type(oper->righttype, -1));
+
+		/* Add the FOR SEARCH / FOR ORDER BY clause; not in the DROP case */
+		if (!stmt->isDrop)
+		{
+			if (oper->sortfamily == InvalidOid)
+				append_string_object(tmp_obj, "%{purpose}s", "purpose",
+									 "FOR SEARCH");
+			else
+			{
+				ObjTree    *orderby_obj;
+
+				orderby_obj = new_objtree_VA("FOR ORDER BY %{opfamily}D", 1,
+											"opfamily", ObjTypeObject,
+											new_objtree_for_qualname_id(OperatorFamilyRelationId,
+																		oper->sortfamily));
+				append_object_object(tmp_obj, "%{purpose}s", orderby_obj);
+			}
+		}
+
+		list = lappend(list, new_object_object(tmp_obj));
+	}
+
+	foreach(cell, cmd->d.opfam.procedures)
+	{
+		OpFamilyMember *proc = lfirst(cell);
+		ObjTree    *tmp_obj;
+
+		tmp_obj = new_objtree_VA("FUNCTION %{num}n (%{ltype}T, %{rtype}T)", 3,
+								"num", ObjTypeInteger, proc->number,
+								"ltype", ObjTypeObject,
+								new_objtree_for_type(proc->lefttype, -1),
+								"rtype", ObjTypeObject,
+								new_objtree_for_type(proc->righttype, -1));
+
+		/*
+		 * Add the function name and arg types; the DROP case doesn't have
+		 * this
+		 */
+		if (!stmt->isDrop)
+		{
+			HeapTuple	procTup;
+			Form_pg_proc procForm;
+			Oid		   *proargtypes;
+			List	   *arglist = NIL;
+			int			i;
+
+			procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc->object));
+			if (!HeapTupleIsValid(procTup))
+				elog(ERROR, "cache lookup failed for procedure with OID %u",
+					 proc->object);
+			procForm = (Form_pg_proc) GETSTRUCT(procTup);
+
+			proargtypes = procForm->proargtypes.values;
+			for (i = 0; i < procForm->pronargs; i++)
+			{
+				ObjTree    *arg;
+
+				arg = new_objtree_for_type(proargtypes[i], -1);
+				arglist = lappend(arglist, new_object_object(arg));
+			}
+
+			append_object_object(tmp_obj, "%{function}D",
+								 new_objtree_for_qualname(procForm->pronamespace,
+														  NameStr(procForm->proname)));
+
+			append_format_string(tmp_obj, "(");
+			append_array_object(tmp_obj, "%{argtypes:, }T", arglist);
+			append_format_string(tmp_obj, ")");
+
+			ReleaseSysCache(procTup);
+		}
+
+		list = lappend(list, new_object_object(tmp_obj));
+	}
+
+	if (stmt->isDrop)
+		append_format_string(ret, "DROP");
+	else
+		append_format_string(ret, "ADD");
+
+	append_array_object(ret, "%{items:, }s", list);
+
+	ReleaseSysCache(ftp);
+
+	return ret;
+}
+
+/*
+ * Deparse an AlterOwnerStmt (ALTER ... OWNER TO ...).
+ *
+ * Given the object address and the parse tree that created it, return an
+ * ObjTree representing the alter command.
+ *
+ * Verbose syntax
+ * ALTER %s %{identity}s OWNER TO %{newowner}I
+ */
+static ObjTree *
+deparse_AlterOwnerStmt(ObjectAddress address, Node *parsetree)
+{
+	AlterOwnerStmt *node = (AlterOwnerStmt *) parsetree;
+
+	return new_objtree_VA("ALTER %{objtype}s %{identity}s OWNER TO %{newowner}I", 3,
+						  "objtype", ObjTypeString,
+						  stringify_objtype(node->objectType, false),
+						  "identity", ObjTypeString,
+						  getObjectIdentity(&address, false),
+						  "newowner", ObjTypeString,
+						  get_rolespec_name(node->newowner));
+}
+
+/*
+ * Deparse an AlterSeqStmt.
+ *
+ * Given a sequence OID and a parse tree that modified it, return an ObjTree
+ * representing the alter command.
+ *
+ * Verbose syntax
+ * ALTER SEQUENCE %{identity}D %{definition: }s
+ */
+static ObjTree *
+deparse_AlterSeqStmt(Oid objectId, Node *parsetree)
+{
+	ObjTree    *ret;
+	Relation	relation;
+	List	   *elems = NIL;
+	ListCell   *cell;
+	Form_pg_sequence seqform;
+	Sequence_values *seqvalues;
+	AlterSeqStmt *alterSeqStmt = (AlterSeqStmt *) parsetree;
+
+	/*
+	 * Sequence for IDENTITY COLUMN output separately (via CREATE TABLE or
+	 * ALTER TABLE); return empty here.
+	 */
+	if (alterSeqStmt->for_identity)
+		return NULL;
+
+	seqvalues = get_sequence_values(objectId);
+	seqform = seqvalues->seqform;
+
+	foreach(cell, ((AlterSeqStmt *) parsetree)->options)
+	{
+		DefElem    *elem = (DefElem *) lfirst(cell);
+		ObjElem    *newelm;
+
+		if (strcmp(elem->defname, "cache") == 0)
+			newelm = deparse_Seq_Cache(seqform, false);
+		else if (strcmp(elem->defname, "cycle") == 0)
+			newelm = deparse_Seq_Cycle(seqform, false);
+		else if (strcmp(elem->defname, "increment") == 0)
+			newelm = deparse_Seq_IncrementBy(seqform, false);
+		else if (strcmp(elem->defname, "minvalue") == 0)
+			newelm = deparse_Seq_Minvalue(seqform, false);
+		else if (strcmp(elem->defname, "maxvalue") == 0)
+			newelm = deparse_Seq_Maxvalue(seqform, false);
+		else if (strcmp(elem->defname, "start") == 0)
+			newelm = deparse_Seq_Startwith(seqform, false);
+		else if (strcmp(elem->defname, "restart") == 0)
+			newelm = deparse_Seq_Restart(seqvalues->last_value);
+		else if (strcmp(elem->defname, "owned_by") == 0)
+			newelm = deparse_Seq_OwnedBy(objectId, false);
+		else if (strcmp(elem->defname, "as") == 0)
+			newelm = deparse_Seq_As(seqform);
+		else
+			elog(ERROR, "invalid sequence option %s", elem->defname);
+
+		elems = lappend(elems, newelm);
+	}
+
+	relation = relation_open(objectId, AccessShareLock);
+
+	ret = new_objtree_VA("ALTER SEQUENCE %{identity}D %{definition: }s", 2,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(relation->rd_rel->relnamespace,
+												  RelationGetRelationName(relation)),
+						 "definition", ObjTypeArray, elems);
+
+	relation_close(relation, AccessShareLock);
+
+	return ret;
+}
+
+/*
+ * Deparse an AlterTypeStmt.
+ *
+ * Given a type OID and a parse tree that modified it, return an ObjTree
+ * representing the alter type.
+ *
+ * Verbose syntax
+ * ALTER TYPE %{identity}D (%{definition: }s)
+ */
+static ObjTree *
+deparse_AlterTypeSetStmt(Oid objectId, Node *cmd)
+{
+	AlterTypeStmt *alterTypeSetStmt = (AlterTypeStmt *) cmd;
+	ListCell   *pl;
+	List	   *elems = NIL;
+	HeapTuple	typTup;
+	Form_pg_type typForm;
+
+	typTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(typTup))
+		elog(ERROR, "cache lookup failed for type with OID %u", objectId);
+	typForm = (Form_pg_type) GETSTRUCT(typTup);
+
+	foreach(pl, alterTypeSetStmt->options)
+	{
+		DefElem    *defel = (DefElem *) lfirst(pl);
+		ObjElem    *newelm;
+
+		if (strcmp(defel->defname, "storage") == 0)
+			newelm = deparse_Type_Storage(typForm);
+		else if (strcmp(defel->defname, "receive") == 0)
+			newelm = deparse_Type_Receive(typForm);
+		else if (strcmp(defel->defname, "send") == 0)
+			newelm = deparse_Type_Send(typForm);
+		else if (strcmp(defel->defname, "typmod_in") == 0)
+			newelm = deparse_Type_Typmod_In(typForm);
+		else if (strcmp(defel->defname, "typmod_out") == 0)
+			newelm = deparse_Type_Typmod_Out(typForm);
+		else if (strcmp(defel->defname, "analyze") == 0)
+			newelm = deparse_Type_Analyze(typForm);
+		else if (strcmp(defel->defname, "subscript") == 0)
+			newelm = deparse_Type_Subscript(typForm);
+		else
+			elog(ERROR, "invalid type option %s", defel->defname);
+
+		elems = lappend(elems, newelm);
+	}
+
+	ReleaseSysCache(typTup);
+
+	return new_objtree_VA("ALTER TYPE %{identity}D SET (%{definition:, }s)", 2,
+						  "identity", ObjTypeObject,
+						  new_objtree_for_qualname_id(TypeRelationId,
+													  objectId),
+						  "definition", ObjTypeArray, elems);
+}
+
+/*
+ * Deparse a CompositeTypeStmt (CREATE TYPE AS)
+ *
+ * Given a Composite type OID and the parse tree that created it, return an
+ * ObjTree representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE TYPE %{identity}D AS (%{columns:, }s)
+ */
+static ObjTree *
+deparse_CompositeTypeStmt(Oid objectId, Node *parsetree)
+{
+	CompositeTypeStmt *node = (CompositeTypeStmt *) parsetree;
+	HeapTuple	typtup;
+	Form_pg_type typform;
+	Relation	typerel;
+	List	   *dpcontext;
+	List	   *tableelts = NIL;
+
+	/* Find the pg_type entry and open the corresponding relation */
+	typtup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(typtup))
+		elog(ERROR, "cache lookup failed for type with OID %u", objectId);
+	typform = (Form_pg_type) GETSTRUCT(typtup);
+	typerel = relation_open(typform->typrelid, AccessShareLock);
+
+	dpcontext = deparse_context_for(RelationGetRelationName(typerel),
+									RelationGetRelid(typerel));
+
+	tableelts = deparse_TableElements(typerel, node->coldeflist, dpcontext,
+									  false,	/* not typed */
+									  true);	/* composite type */
+
+	table_close(typerel, AccessShareLock);
+	ReleaseSysCache(typtup);
+
+	return new_objtree_VA("CREATE TYPE %{identity}D AS (%{columns:, }s)", 2,
+						  "identity", ObjTypeObject,
+						  new_objtree_for_qualname_id(TypeRelationId, objectId),
+						  "columns", ObjTypeArray, tableelts);
+}
+
+/*
+ * Deparse a CreateConversionStmt
+ *
+ * Given a conversion OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE %{default}s CONVERSION %{identity}D FOR %{source}L TO %{dest}L
+ * FROM %{function}D
+ */
+static ObjTree *
+deparse_CreateConversion(Oid objectId, Node *parsetree)
+{
+	HeapTuple	conTup;
+	Relation	convrel;
+	Form_pg_conversion conForm;
+	ObjTree    *ret;
+
+	convrel = table_open(ConversionRelationId, AccessShareLock);
+	conTup = get_catalog_object_by_oid(convrel, Anum_pg_conversion_oid, objectId);
+	if (!HeapTupleIsValid(conTup))
+		elog(ERROR, "cache lookup failed for conversion with OID %u", objectId);
+	conForm = (Form_pg_conversion) GETSTRUCT(conTup);
+
+	ret = new_objtree_VA("CREATE %{default}s CONVERSION %{identity}D FOR %{source}L TO %{dest}L FROM %{function}D", 5,
+						  "default", ObjTypeString,
+						  conForm->condefault ? "DEFAULT" : "",
+						  "identity", ObjTypeObject,
+						  new_objtree_for_qualname(conForm->connamespace,
+												   NameStr(conForm->conname)),
+						  "source", ObjTypeString,
+						  (char *)pg_encoding_to_char(conForm->conforencoding),
+						  "dest", ObjTypeString,
+						  (char *)pg_encoding_to_char(conForm->contoencoding),
+						  "function", ObjTypeObject,
+						  new_objtree_for_qualname_id(ProcedureRelationId,
+													  conForm->conproc));
+
+	table_close(convrel, AccessShareLock);
+
+	return ret;
+}
+
+/*
+ * Deparse a CreateEnumStmt (CREATE TYPE AS ENUM)
+ *
+ * Given a Enum type OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE TYPE %{identity}D AS ENUM (%{values:, }L)
+ */
+static ObjTree *
+deparse_CreateEnumStmt(Oid objectId, Node *parsetree)
+{
+	CreateEnumStmt *node = (CreateEnumStmt *) parsetree;
+	List	   *values = NIL;
+	ListCell   *cell;
+
+	foreach(cell, node->vals)
+		values = lappend(values, new_string_object(strVal(lfirst_node(String, cell))));
+
+	return new_objtree_VA("CREATE TYPE %{identity}D AS ENUM (%{values:, }L)", 2,
+						  "identity", ObjTypeObject,
+						  new_objtree_for_qualname_id(TypeRelationId, objectId),
+						  "values", ObjTypeArray, values);
+}
+
+/*
+ * Deparse a CreateExtensionStmt
+ *
+ * Given an extension OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE EXTENSION %{if_not_exists}s %{name}I %{options: }s
+ */
+static ObjTree *
+deparse_CreateExtensionStmt(Oid objectId, Node *parsetree)
+{
+	CreateExtensionStmt *node = (CreateExtensionStmt *) parsetree;
+	Relation	pg_extension;
+	HeapTuple	extTup;
+	Form_pg_extension extForm;
+	ObjTree    *tmp;
+	List	   *list = NIL;
+	ListCell   *cell;
+
+	pg_extension = table_open(ExtensionRelationId, AccessShareLock);
+	extTup = get_catalog_object_by_oid(pg_extension, Anum_pg_extension_oid, objectId);
+	if (!HeapTupleIsValid(extTup))
+		elog(ERROR, "cache lookup failed for extension with OID %u", objectId);
+	extForm = (Form_pg_extension) GETSTRUCT(extTup);
+
+	/* List of options */
+	foreach(cell, node->options)
+	{
+		DefElem    *opt = (DefElem *) lfirst(cell);
+
+		if (strcmp(opt->defname, "schema") == 0)
+		{
+			/* Skip this one; we add one unconditionally below */
+			continue;
+		}
+		else if (strcmp(opt->defname, "new_version") == 0)
+		{
+			tmp = new_objtree_VA("VERSION %{version}L", 2,
+								 "type", ObjTypeString, "version",
+								 "version", ObjTypeString, defGetString(opt));
+			list = lappend(list, new_object_object(tmp));
+		}
+		else if (strcmp(opt->defname, "old_version") == 0)
+		{
+			tmp = new_objtree_VA("FROM %{version}L", 2,
+								 "type", ObjTypeString, "from",
+								 "version", ObjTypeString, defGetString(opt));
+			list = lappend(list, new_object_object(tmp));
+		}
+		else
+			elog(ERROR, "unsupported option %s", opt->defname);
+	}
+
+	/* Add the SCHEMA option */
+	tmp = new_objtree_VA("SCHEMA %{schema}I", 2,
+						 "type", ObjTypeString, "schema",
+						 "schema", ObjTypeString,
+						 get_namespace_name(extForm->extnamespace));
+	list = lappend(list, new_object_object(tmp));
+	table_close(pg_extension, AccessShareLock);
+
+	return new_objtree_VA("CREATE EXTENSION %{if_not_exists}s %{name}I %{options: }s", 3,
+						  "if_not_exists", ObjTypeString,
+						  node->if_not_exists ? "IF NOT EXISTS" : "",
+						  "name", ObjTypeString, node->extname,
+						  "options", ObjTypeArray, list);
+}
+
+/*
+ * If a column name is specified, add an element for it; otherwise it's a
+ * table-level option.
+ */
+static ObjTree *
+deparse_FdwOptions(List *options, char *colname, bool altercoloptions)
+{
+	ObjTree    *ret;
+
+	if (colname)
+		ret = new_objtree_VA("ALTER COLUMN %{column}I %{options}s", 2,
+							 "column", ObjTypeString, colname,
+							 "options", ObjTypeString,
+							 altercoloptions ? "OPTIONS" : "");
+	else
+		ret = new_objtree("OPTIONS");
+
+	if (options != NIL)
+	{
+		List	   *optout = NIL;
+		ListCell   *cell;
+
+		foreach(cell, options)
+		{
+			DefElem    *elem;
+			ObjTree    *opt;
+
+			elem = (DefElem *) lfirst(cell);
+
+			switch (elem->defaction)
+			{
+				case DEFELEM_UNSPEC:
+					opt = new_objtree_VA("%{label}I %{value}L", 2,
+										 "label", ObjTypeString, elem->defname,
+										 "value", ObjTypeString,
+										 elem->arg ? defGetString(elem) :
+										 defGetBoolean(elem) ? "TRUE" : "FALSE");
+					break;
+				case DEFELEM_SET:
+					opt = new_objtree_VA("SET %{label}I %{value}L", 2,
+										 "label", ObjTypeString, elem->defname,
+										 "value", ObjTypeString,
+										 elem->arg ? defGetString(elem) :
+										 defGetBoolean(elem) ? "TRUE" : "FALSE");
+					break;
+				case DEFELEM_ADD:
+					opt = new_objtree_VA("ADD %{label}I %{value}L", 2,
+										 "label", ObjTypeString, elem->defname,
+										 "value", ObjTypeString,
+										 elem->arg ? defGetString(elem) :
+										 defGetBoolean(elem) ? "TRUE" : "FALSE");
+					break;
+				case DEFELEM_DROP:
+					opt = new_objtree_VA("DROP %{label}I", 1,
+										 "label", ObjTypeString, elem->defname);
+					break;
+				default:
+					elog(ERROR, "invalid def action %d", elem->defaction);
+					opt = NULL;
+			}
+
+			optout = lappend(optout, new_object_object(opt));
+		}
+
+		append_array_object(ret, "(%{option: ,}s)", optout);
+	}
+	else
+		append_not_present(ret);
+
+	return ret;
+}
+
+/*
+ * Deparse a CreateFdwStmt (CREATE FOREIGN DATA WRAPPER)
+ *
+ * Given an FDW OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE FOREIGN DATA WRAPPER %{identity}I %{handler}s %{validator}s %{generic_options}s
+ */
+static ObjTree *
+deparse_CreateFdwStmt(Oid objectId, Node *parsetree)
+{
+	CreateFdwStmt *node = (CreateFdwStmt *) parsetree;
+	HeapTuple	fdwTup;
+	Form_pg_foreign_data_wrapper fdwForm;
+	Relation	rel;
+	ObjTree    *ret;
+	ObjTree    *tmp;
+
+	rel = table_open(ForeignDataWrapperRelationId, RowExclusiveLock);
+
+	fdwTup = SearchSysCache1(FOREIGNDATAWRAPPEROID,
+							 ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(fdwTup))
+		elog(ERROR, "cache lookup failed for foreign-data wrapper with OID %u",
+			 objectId);
+
+	fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(fdwTup);
+
+	ret = new_objtree_VA("CREATE FOREIGN DATA WRAPPER %{identity}I", 1,
+						 "identity", ObjTypeString, NameStr(fdwForm->fdwname));
+
+	/* Add HANDLER clause */
+	if (!OidIsValid(fdwForm->fdwhandler))
+		tmp = new_objtree("NO HANDLER");
+	else
+	{
+		tmp = new_objtree_VA("HANDLER %{procedure}D", 1,
+							 "procedure", ObjTypeObject,
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 fdwForm->fdwhandler));
+	}
+	append_object_object(ret, "%{handler}s", tmp);
+
+	/* Add VALIDATOR clause */
+	if (!OidIsValid(fdwForm->fdwvalidator))
+		tmp = new_objtree("NO VALIDATOR");
+	else
+	{
+		tmp = new_objtree_VA("VALIDATOR %{procedure}D", 1,
+							 "procedure", ObjTypeObject,
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 fdwForm->fdwvalidator));
+	}
+	append_object_object(ret, "%{validator}s", tmp);
+
+	/* Add an OPTIONS clause, if any */
+	append_object_object(ret, "%{generic_options}s",
+						 deparse_FdwOptions(node->options, NULL, false));
+
+	ReleaseSysCache(fdwTup);
+	table_close(rel, RowExclusiveLock);
+
+	return ret;
+}
+
+/*
+ * Deparse an AlterFdwStmt (ALTER FOREIGN DATA WRAPPER)
+ *
+ * Given an FDW OID and the parse tree that created it, return an ObjTree
+ * representing the alter command.
+ *
+ * Verbose syntax
+ * ALTER FOREIGN DATA WRAPPER %{identity}I %{fdw_options: }s %{generic_options}D
+ */
+static ObjTree *
+deparse_AlterFdwStmt(Oid objectId, Node *parsetree)
+{
+	AlterFdwStmt *node = (AlterFdwStmt *) parsetree;
+	HeapTuple	fdwTup;
+	Form_pg_foreign_data_wrapper fdwForm;
+	Relation	rel;
+	ObjTree    *ret;
+	List	   *fdw_options = NIL;
+	ListCell   *cell;
+
+	rel = table_open(ForeignDataWrapperRelationId, RowExclusiveLock);
+
+	fdwTup = SearchSysCache1(FOREIGNDATAWRAPPEROID,
+							 ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(fdwTup))
+		elog(ERROR, "cache lookup failed for foreign-data wrapper with OID %u",
+			 objectId);
+
+	fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(fdwTup);
+
+	ret = new_objtree_VA("ALTER FOREIGN DATA WRAPPER %{identity}I", 1,
+						 "identity", ObjTypeString, NameStr(fdwForm->fdwname));
+
+	/*
+	 * Iterate through options, to see what changed, but use catalog as a
+	 * basis for new values.
+	 */
+	foreach(cell, node->func_options)
+	{
+		DefElem    *elem;
+		ObjTree    *tmp;
+
+		elem = lfirst(cell);
+
+		if (pg_strcasecmp(elem->defname, "handler") == 0)
+		{
+			/* add HANDLER clause */
+			if (!OidIsValid(fdwForm->fdwhandler))
+				tmp = new_objtree("NO HANDLER");
+			else
+			{
+				tmp = new_objtree_VA("HANDLER %{procedure}D", 1,
+									 "procedure", ObjTypeObject,
+									 new_objtree_for_qualname_id(ProcedureRelationId,
+																 fdwForm->fdwhandler));
+			}
+			fdw_options = lappend(fdw_options, new_object_object(tmp));
+		}
+		else if (pg_strcasecmp(elem->defname, "validator") == 0)
+		{
+			/* add VALIDATOR clause */
+			if (!OidIsValid(fdwForm->fdwvalidator))
+				tmp = new_objtree("NO VALIDATOR");
+			else
+			{
+				tmp = new_objtree_VA("VALIDATOR %{procedure}D", 1,
+									 "procedure", ObjTypeObject,
+									 new_objtree_for_qualname_id(ProcedureRelationId,
+																 fdwForm->fdwvalidator));
+			}
+			fdw_options = lappend(fdw_options, new_object_object(tmp));
+		}
+	}
+
+	/* Add HANDLER/VALIDATOR if specified */
+	append_array_object(ret, "%{fdw_options: }s", fdw_options);
+
+	/* Add an OPTIONS clause, if any */
+	append_object_object(ret, "%{generic_options}D",
+						 deparse_FdwOptions(node->options, NULL, false));
+
+	ReleaseSysCache(fdwTup);
+	table_close(rel, RowExclusiveLock);
+
+	return ret;
+}
+
+/*
+ * Deparse a CREATE TYPE AS RANGE statement
+ *
+ * Given a Range type OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE TYPE %{identity}D AS RANGE (%{definition:, }s)
+ */
+static ObjTree *
+deparse_CreateRangeStmt(Oid objectId, Node *parsetree)
+{
+	ObjTree    *tmp;
+	List	   *definition = NIL;
+	Relation	pg_range;
+	HeapTuple	rangeTup;
+	Form_pg_range rangeForm;
+	ScanKeyData key[1];
+	SysScanDesc scan;
+
+	pg_range = table_open(RangeRelationId, RowExclusiveLock);
+
+	ScanKeyInit(&key[0],
+				Anum_pg_range_rngtypid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(objectId));
+
+	scan = systable_beginscan(pg_range, RangeTypidIndexId, true,
+							  NULL, 1, key);
+
+	rangeTup = systable_getnext(scan);
+	if (!HeapTupleIsValid(rangeTup))
+		elog(ERROR, "cache lookup failed for range with type OID %u",
+			 objectId);
+
+	rangeForm = (Form_pg_range) GETSTRUCT(rangeTup);
+
+	/* SUBTYPE */
+	tmp = new_objtree_VA("SUBTYPE = %{type}D", 2,
+						 "clause", ObjTypeString, "subtype",
+						 "type", ObjTypeObject,
+						 new_objtree_for_qualname_id(TypeRelationId, rangeForm->rngsubtype));
+	definition = lappend(definition, new_object_object(tmp));
+
+	/* SUBTYPE_OPCLASS */
+	if (OidIsValid(rangeForm->rngsubopc))
+	{
+		tmp = new_objtree_VA("SUBTYPE_OPCLASS = %{opclass}D", 2,
+							 "clause", ObjTypeString, "opclass",
+							 "opclass", ObjTypeObject,
+							 new_objtree_for_qualname_id(OperatorClassRelationId,
+														 rangeForm->rngsubopc));
+		definition = lappend(definition, new_object_object(tmp));
+	}
+
+	/* COLLATION */
+	if (OidIsValid(rangeForm->rngcollation))
+	{
+		tmp = new_objtree_VA("COLLATION = %{collation}D", 2,
+							 "clause", ObjTypeString, "collation",
+							 "collation", ObjTypeObject,
+							 new_objtree_for_qualname_id(CollationRelationId,
+														 rangeForm->rngcollation));
+		definition = lappend(definition, new_object_object(tmp));
+	}
+
+	/* CANONICAL */
+	if (OidIsValid(rangeForm->rngcanonical))
+	{
+		tmp = new_objtree_VA("CANONICAL = %{canonical}D", 2,
+							 "clause", ObjTypeString, "canonical",
+							 "canonical", ObjTypeObject,
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 rangeForm->rngcanonical));
+		definition = lappend(definition, new_object_object(tmp));
+	}
+
+	/* SUBTYPE_DIFF */
+	if (OidIsValid(rangeForm->rngsubdiff))
+	{
+		tmp = new_objtree_VA("SUBTYPE_DIFF = %{subtype_diff}D", 2,
+							 "clause", ObjTypeString, "subtype_diff",
+							 "subtype_diff", ObjTypeObject,
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 rangeForm->rngsubdiff));
+		definition = lappend(definition, new_object_object(tmp));
+	}
+
+	systable_endscan(scan);
+	table_close(pg_range, RowExclusiveLock);
+
+	return new_objtree_VA("CREATE TYPE %{identity}D AS RANGE (%{definition:, }s)", 2,
+						  "identity", ObjTypeObject,
+						  new_objtree_for_qualname_id(TypeRelationId, objectId),
+						  "definition", ObjTypeArray, definition);
+}
+
+/*
+ * Deparse an AlterEnumStmt.
+ *
+ * Given an enum OID and a parse tree that modified it, return an ObjTree
+ * representing the alter type.
+ *
+ * Verbose syntax
+ * ALTER TYPE %{identity}D ADD VALUE %{if_not_exists}s %{value}L
+ * %{after_or_before}s %{neighbor}L
+ * 	OR
+ * ALTER TYPE %{identity}D RENAME VALUE %{value}L TO %{newvalue}L
+ */
+static ObjTree *
+deparse_AlterEnumStmt(Oid objectId, Node *parsetree)
+{
+	AlterEnumStmt *node = (AlterEnumStmt *) parsetree;
+	ObjTree    *ret;
+
+	ret = new_objtree_VA("ALTER TYPE %{identity}D", 1,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname_id(TypeRelationId,
+													 objectId));
+
+	if (!node->oldVal)
+	{
+		append_format_string(ret, "ADD VALUE");
+		append_string_object(ret, "%{if_not_exists}s", "if_not_exists",
+							 node->skipIfNewValExists ? "IF NOT EXISTS" : "");
+
+		append_string_object(ret, "%{value}L", "value", node->newVal);
+
+		if (node->newValNeighbor)
+		{
+			append_string_object(ret, "%{after_or_before}s",
+								 "after_or_before",
+								 node->newValIsAfter ? "AFTER" : "BEFORE");
+			append_string_object(ret, "%{neighbor}L", "neighbor",
+								 node->newValNeighbor);
+		}
+	}
+	else
+	{
+		append_string_object(ret, "RENAME VALUE %{value}L TO", "value",
+							 node->oldVal);
+		append_string_object(ret, "%{newvalue}L", "newvalue", node->newVal);
+	}
+
+	return ret;
+}
+
+/*
+ * Deparse an AlterExtensionStmt (ALTER EXTENSION .. UPDATE TO VERSION)
+ *
+ * Given an extension OID and a parse tree that modified it, return an ObjTree
+ * representing the alter type.
+ *
+ * Verbose syntax
+ * ALTER EXTENSION %{identity}I UPDATE %{options: }s
+ */
+static ObjTree *
+deparse_AlterExtensionStmt(Oid objectId, Node *parsetree)
+{
+	AlterExtensionStmt *node = (AlterExtensionStmt *) parsetree;
+	Relation	pg_extension;
+	HeapTuple	extTup;
+	Form_pg_extension extForm;
+	ObjTree    *ret;
+	List	   *list = NIL;
+	ListCell   *cell;
+	DefElem    *d_new_version = NULL;
+
+	pg_extension = table_open(ExtensionRelationId, AccessShareLock);
+	extTup = get_catalog_object_by_oid(pg_extension, Anum_pg_extension_oid, objectId);
+	if (!HeapTupleIsValid(extTup))
+		elog(ERROR, "cache lookup failed for extension with OID %u",
+			 objectId);
+	extForm = (Form_pg_extension) GETSTRUCT(extTup);
+
+	foreach(cell, node->options)
+	{
+		DefElem    *opt = (DefElem *) lfirst(cell);
+
+		if (strcmp(opt->defname, "new_version") == 0)
+		{
+			ObjTree    *tmp;
+
+			if (d_new_version)
+				elog(ERROR, "conflicting or redundant options for extension with OID %u",
+					 objectId);
+
+			d_new_version = opt;
+
+			tmp = new_objtree_VA("TO %{version}L", 2,
+								 "type", ObjTypeString, "version",
+								 "version", ObjTypeString, defGetString(opt));
+			list = lappend(list, new_object_object(tmp));
+		}
+		else
+			elog(ERROR, "unsupported option %s", opt->defname);
+	}
+
+	ret = new_objtree_VA("ALTER EXTENSION %{identity}I UPDATE %{options: }s", 2,
+						 "identity", ObjTypeString, NameStr(extForm->extname),
+						 "options", ObjTypeArray, list);
+
+	table_close(pg_extension, AccessShareLock);
+
+	return ret;
+}
+
+/*
+ * Deparse an AlterExtensionContentsStmt (ALTER EXTENSION ext ADD/DROP object)
+ *
+ * Verbose syntax
+ * ALTER EXTENSION %{extidentity}I ADD/DROP %{objidentity}s
+ */
+static ObjTree *
+deparse_AlterExtensionContentsStmt(Oid objectId, Node *parsetree,
+								   ObjectAddress objectAddress)
+{
+	AlterExtensionContentsStmt *node = (AlterExtensionContentsStmt *) parsetree;
+
+	Assert(node->action == +1 || node->action == -1);
+
+	return new_objtree_VA("ALTER EXTENSION %{extidentity}I %{extoption}s %{extobjtype}s %{objidentity}s", 4,
+						  "extidentity", ObjTypeString, node->extname,
+						  "extoption", ObjTypeString,
+						  node->action == +1 ? "ADD" : "DROP",
+						  "extobjtype", ObjTypeString,
+						  stringify_objtype(node->objtype, false),
+						  "objidentity", ObjTypeString,
+						  getObjectIdentity(&objectAddress, false));
+}
+
+/*
+ * Deparse an CreateCastStmt.
+ *
+ * Given a sequence OID and a parse tree that modified it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE CAST (%{sourcetype}T AS %{targettype}T) %{mechanism}s %{context}s
+ */
+static ObjTree *
+deparse_CreateCastStmt(Oid objectId, Node *parsetree)
+{
+	CreateCastStmt *node = (CreateCastStmt *) parsetree;
+	Relation	castrel;
+	HeapTuple	castTup;
+	Form_pg_cast castForm;
+	ObjTree    *ret;
+	char	   *context;
+
+	castrel = table_open(CastRelationId, AccessShareLock);
+	castTup = get_catalog_object_by_oid(castrel, Anum_pg_cast_oid, objectId);
+	if (!HeapTupleIsValid(castTup))
+		elog(ERROR, "cache lookup failed for cast with OID %u", objectId);
+	castForm = (Form_pg_cast) GETSTRUCT(castTup);
+
+	ret = new_objtree_VA("CREATE CAST (%{sourcetype}T AS %{targettype}T)", 2,
+						 "sourcetype", ObjTypeObject,
+						 new_objtree_for_type(castForm->castsource, -1),
+						 "targettype", ObjTypeObject,
+						 new_objtree_for_type(castForm->casttarget, -1));
+
+	if (node->inout)
+		append_string_object(ret, "%{mechanism}s", "mechanism",
+							 "WITH INOUT");
+	else if (node->func == NULL)
+		append_string_object(ret, "%{mechanism}s", "mechanism",
+							 "WITHOUT FUNCTION");
+	else
+	{
+		ObjTree    *tmp_obj;
+		StringInfoData func;
+		HeapTuple	funcTup;
+		Form_pg_proc funcForm;
+		int			i;
+
+		funcTup = SearchSysCache1(PROCOID, castForm->castfunc);
+		funcForm = (Form_pg_proc) GETSTRUCT(funcTup);
+
+		initStringInfo(&func);
+		appendStringInfo(&func, "%s(",
+						 quote_qualified_identifier(get_namespace_name(funcForm->pronamespace),
+													NameStr(funcForm->proname)));
+		for (i = 0; i < funcForm->pronargs; i++)
+		{
+			if (i != 0)
+				appendStringInfoChar(&func, ',');
+
+			appendStringInfoString(&func,
+								   format_type_be_qualified(funcForm->proargtypes.values[i]));
+		}
+		appendStringInfoChar(&func, ')');
+
+		tmp_obj = new_objtree_VA("WITH FUNCTION %{castfunction}s", 1,
+								"castfunction", ObjTypeString, func.data);
+		append_object_object(ret, "%{mechanism}s", tmp_obj);
+
+		ReleaseSysCache(funcTup);
+	}
+
+	switch (node->context)
+	{
+		case COERCION_IMPLICIT:
+			context = "AS IMPLICIT";
+			break;
+		case COERCION_ASSIGNMENT:
+			context = "AS ASSIGNMENT";
+			break;
+		case COERCION_EXPLICIT:
+			context = "";
+			break;
+		default:
+			elog(ERROR, "invalid coercion code %c", node->context);
+			return NULL;		/* keep compiler quiet */
+	}
+	append_string_object(ret, "%{context}s", "context", context);
+
+	table_close(castrel, AccessShareLock);
+
+	return ret;
+}
+
+/*
+ * Deparse an ALTER DEFAULT PRIVILEGES statement.
+ *
+ * Verbose syntax
+ * ALTER DEFAULT PRIVILEGES %{in_schema}s %{for_roles}s %{grant}s
+ */
+static ObjTree *
+deparse_AlterDefaultPrivilegesStmt(CollectedCommand *cmd)
+{
+	ObjTree    *ret;
+	AlterDefaultPrivilegesStmt *stmt = (AlterDefaultPrivilegesStmt *) cmd->parsetree;
+	List	   *roles = NIL;
+	List	   *schemas = NIL;
+	List	   *grantees;
+	List	   *privs;
+	ListCell   *cell;
+	ObjTree    *tmp;
+	ObjTree    *grant;
+	char	   *objtype;
+
+	ret = new_objtree("ALTER DEFAULT PRIVILEGES");
+
+	/* Scan the parse node to dig out the FOR ROLE and IN SCHEMA clauses */
+	foreach(cell, stmt->options)
+	{
+		DefElem    *opt = (DefElem *) lfirst(cell);
+		ListCell   *cell2;
+
+		Assert(IsA(opt, DefElem));
+		Assert(IsA(opt->arg, List));
+		if (strcmp(opt->defname, "roles") == 0)
+		{
+			foreach(cell2, (List *) opt->arg)
+			{
+				RoleSpec   *rolespec = lfirst(cell2);
+				ObjTree    *obj = new_objtree_for_rolespec(rolespec);
+
+				roles = lappend(roles, new_object_object(obj));
+			}
+		}
+		else if (strcmp(opt->defname, "schemas") == 0)
+		{
+			foreach(cell2, (List *) opt->arg)
+			{
+				String	   *val = lfirst_node(String, cell2);
+
+				schemas = lappend(schemas, new_string_object(strVal(val)));
+			}
+		}
+	}
+
+	/* Add the IN SCHEMA clause, if any */
+	tmp = new_objtree("IN SCHEMA");
+	append_array_object(tmp, "%{schemas:, }I", schemas);
+	if (schemas == NIL)
+		append_not_present(tmp);
+	append_object_object(ret, "%{in_schema}s", tmp);
+
+	/* Add the FOR ROLE clause, if any */
+	tmp = new_objtree("FOR ROLE");
+	append_array_object(tmp, "%{roles:, }R", roles);
+	if (roles == NIL)
+		append_not_present(tmp);
+	append_object_object(ret, "%{for_roles}s", tmp);
+
+	/*
+	 * Add the GRANT subcommand
+	 * Verbose syntax
+	 * GRANT %{privileges:, }s ON %{target}s TO %{grantees:, }R %{grant_option}s
+	 * or
+	 * REVOKE %{grant_option}s %{privileges:, }s ON %{target}s FROM %{grantees:, }R
+	 */
+	if (stmt->action->is_grant)
+		grant = new_objtree("GRANT");
+	else
+	{
+		grant = new_objtree("REVOKE");
+
+		/* Add the GRANT OPTION clause for REVOKE subcommand */
+		tmp = new_objtree_VA("GRANT OPTION FOR", 1,
+							 "present", ObjTypeBool,
+							 stmt->action->grant_option);
+		append_object_object(grant, "%{grant_option}s", tmp);
+	}
+
+	/*
+	 * Add the privileges list.  This uses the parser struct, as opposed to
+	 * the InternalGrant format used by GRANT.  There are enough other
+	 * differences that this doesn't seem worth improving.
+	 */
+	if (stmt->action->privileges == NIL)
+		privs = list_make1(new_string_object("ALL PRIVILEGES"));
+	else
+	{
+		privs = NIL;
+
+		foreach(cell, stmt->action->privileges)
+		{
+			AccessPriv *priv = lfirst(cell);
+
+			Assert(priv->cols == NIL);
+			privs = lappend(privs, new_string_object(priv->priv_name));
+		}
+	}
+
+	append_array_object(grant, "%{privileges:, }s", privs);
+
+	switch (cmd->d.defprivs.objtype)
+	{
+		case OBJECT_TABLE:
+			objtype = "TABLES";
+			break;
+		case OBJECT_FUNCTION:
+			objtype = "FUNCTIONS";
+			break;
+		case OBJECT_ROUTINE:
+			objtype = "ROUTINES";
+			break;
+		case OBJECT_SEQUENCE:
+			objtype = "SEQUENCES";
+			break;
+		case OBJECT_TYPE:
+			objtype = "TYPES";
+			break;
+		case OBJECT_SCHEMA:
+			objtype = "SCHEMAS";
+			break;
+		default:
+			elog(ERROR, "invalid OBJECT value %d for default privileges", cmd->d.defprivs.objtype);
+	}
+
+	/* Add the target object type */
+	append_string_object(grant, "ON %{target}s", "target", objtype);
+
+	/* Add the grantee list */
+	grantees = NIL;
+	foreach(cell, stmt->action->grantees)
+	{
+		RoleSpec   *spec = (RoleSpec *) lfirst(cell);
+		ObjTree    *obj = new_objtree_for_rolespec(spec);
+
+		grantees = lappend(grantees, new_object_object(obj));
+	}
+
+	if (stmt->action->is_grant)
+	{
+		append_array_object(grant, "TO %{grantees:, }R", grantees);
+
+		/* Add the WITH GRANT OPTION clause for GRANT subcommand */
+		tmp = new_objtree_VA("WITH GRANT OPTION", 1,
+							 "present", ObjTypeBool,
+							 stmt->action->grant_option);
+		append_object_object(grant, "%{grant_option}s", tmp);
+	}
+	else
+		append_array_object(grant, "FROM %{grantees:, }R", grantees);
+
+	append_object_object(ret, "%{grant}s", grant);
+
+	return ret;
+}
+
+/*
+ * Deparse the CREATE DOMAIN
+ *
+ * Given a function OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE DOMAIN %{identity}D AS %{type}T %{not_null}s %{constraints}s
+ * %{collation}s
+ */
+static ObjTree *
+deparse_CreateDomain(Oid objectId, Node *parsetree)
+{
+	ObjTree    *ret;
+	ObjTree    *tmp_obj;
+	HeapTuple	typTup;
+	Form_pg_type typForm;
+	List	   *constraints;
+	char	   *defval;
+
+	typTup = SearchSysCache1(TYPEOID, objectId);
+	if (!HeapTupleIsValid(typTup))
+		elog(ERROR, "cache lookup failed for domain with OID %u", objectId);
+	typForm = (Form_pg_type) GETSTRUCT(typTup);
+
+	ret = new_objtree_VA("CREATE DOMAIN %{identity}D AS %{type}T %{not_null}s", 3,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname_id(TypeRelationId, objectId),
+						 "type", ObjTypeObject,
+						 new_objtree_for_type(typForm->typbasetype,
+											  typForm->typtypmod),
+						 "not_null", ObjTypeString,
+						 typForm->typnotnull ? "NOT NULL" : "");
+
+	constraints = obtainConstraints(NIL, InvalidOid, objectId);
+	if (constraints == NIL)
+	{
+		tmp_obj = new_objtree("");
+		append_not_present(tmp_obj);
+	}
+	else
+		tmp_obj = new_objtree_VA("%{elements:, }s", 1,
+								"elements", ObjTypeArray, constraints);
+	append_object_object(ret, "%{constraints}s", tmp_obj);
+
+	tmp_obj = new_objtree("COLLATE");
+	if (OidIsValid(typForm->typcollation))
+	{
+		ObjTree    *collname;
+
+		collname = new_objtree_for_qualname_id(CollationRelationId,
+											   typForm->typcollation);
+		append_object_object(tmp_obj, "%{name}D", collname);
+	}
+	else
+		append_not_present(tmp_obj);
+	append_object_object(ret, "%{collation}s", tmp_obj);
+
+	defval = DomainGetDefault(typTup, true);
+	if (defval)
+		append_string_object(ret, "DEFAULT %{default}s", "default", defval);
+
+	ReleaseSysCache(typTup);
+
+	return ret;
+}
+
+/*
+ * Deparse a CreateFunctionStmt (CREATE FUNCTION)
+ *
+ * Given a function OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ *
+ * CREATE %{or_replace}s FUNCTION %{signature}s RETURNS %{return_type}s
+ * LANGUAGE %{transform_type}s %{language}I %{window}s %{volatility}s
+ * %{parallel_safety}s %{leakproof}s %{strict}s %{security_definer}s
+ * %{cost}s %{rows}s %{support}s %{set_options: }s AS %{objfile}L,
+ * %{symbol}L
+ */
+static ObjTree *
+deparse_CreateFunction(Oid objectId, Node *parsetree)
+{
+	CreateFunctionStmt *node = (CreateFunctionStmt *) parsetree;
+	ObjTree    *ret;
+	ObjTree    *tmp_obj;
+	Datum		tmpdatum;
+	char	   *source;
+	char	   *probin = NULL;
+	List	   *params;
+	List	   *defaults;
+	List	   *sets = NIL;
+	List	   *types = NIL;
+	ListCell   *cell;
+	ListCell   *curdef;
+	ListCell   *table_params = NULL;
+	HeapTuple	procTup;
+	Form_pg_proc procForm;
+	HeapTuple	langTup;
+	Oid		   *typarray;
+	Oid		   *trftypes;
+	Form_pg_language langForm;
+	int			i;
+	int			typnum;
+	int			ntypes;
+	int			paramcount = list_length(node->parameters);
+	bool		isnull;
+	bool		isfunction;
+
+	/* Get the pg_proc tuple */
+	procTup = SearchSysCache1(PROCOID, objectId);
+	if (!HeapTupleIsValid(procTup))
+		elog(ERROR, "cache lookup failed for function with OID %u",
+			 objectId);
+	procForm = (Form_pg_proc) GETSTRUCT(procTup);
+
+	/* Get the corresponding pg_language tuple */
+	langTup = SearchSysCache1(LANGOID, procForm->prolang);
+	if (!HeapTupleIsValid(langTup))
+		elog(ERROR, "cache lookup failed for language with OID %u",
+			 procForm->prolang);
+	langForm = (Form_pg_language) GETSTRUCT(langTup);
+
+	/*
+	 * Determine useful values for prosrc and probin.  We cope with probin
+	 * being either NULL or "-", but prosrc must have a valid value.
+	 */
+	tmpdatum = SysCacheGetAttr(PROCOID, procTup,
+							   Anum_pg_proc_prosrc, &isnull);
+	if (isnull)
+		elog(ERROR, "null prosrc in function with OID %u", objectId);
+	source = TextDatumGetCString(tmpdatum);
+
+	/* Determine a useful value for probin */
+	tmpdatum = SysCacheGetAttr(PROCOID, procTup,
+							   Anum_pg_proc_probin, &isnull);
+	if (!isnull)
+	{
+		probin = TextDatumGetCString(tmpdatum);
+		if (probin[0] == '\0' || strcmp(probin, "-") == 0)
+			probin = NULL;
+	}
+
+	ret = new_objtree_VA("CREATE %{or_replace}s", 1,
+						 "or_replace", ObjTypeString,
+						 node->replace ? "OR REPLACE" : "");
+
+	/*
+	 * To construct the arguments array, extract the type OIDs from the
+	 * function's pg_proc entry.  If pronargs equals the parameter list
+	 * length, there are no OUT parameters and thus we can extract the type
+	 * OID from proargtypes; otherwise we need to decode proallargtypes, which
+	 * is a bit more involved.
+	 */
+	typarray = palloc(paramcount * sizeof(Oid));
+	if (paramcount > procForm->pronargs)
+	{
+		Datum		alltypes;
+		Datum	   *values;
+		bool	   *nulls;
+		int			nelems;
+
+		alltypes = SysCacheGetAttr(PROCOID, procTup,
+								   Anum_pg_proc_proallargtypes, &isnull);
+		if (isnull)
+			elog(ERROR, "null proallargtypes, more number of parameters than args in function with OID %u",
+				 objectId);
+		deconstruct_array(DatumGetArrayTypeP(alltypes),
+						  OIDOID, 4, 't', 'i',
+						  &values, &nulls, &nelems);
+		if (nelems != paramcount)
+			elog(ERROR, "mismatched proallargatypes");
+		for (i = 0; i < paramcount; i++)
+			typarray[i] = values[i];
+	}
+	else
+	{
+		for (i = 0; i < paramcount; i++)
+			typarray[i] = procForm->proargtypes.values[i];
+	}
+
+	/*
+	 * If there are any default expressions, we read the deparsed expression
+	 * as a list so that we can attach them to each argument.
+	 */
+	tmpdatum = SysCacheGetAttr(PROCOID, procTup,
+							   Anum_pg_proc_proargdefaults, &isnull);
+	if (!isnull)
+	{
+		defaults = FunctionGetDefaults(DatumGetTextP(tmpdatum));
+		curdef = list_head(defaults);
+	}
+	else
+	{
+		defaults = NIL;
+		curdef = NULL;
+	}
+
+	/*
+	 * Now iterate over each parameter in the parse tree to create the
+	 * parameters array.
+	 */
+	params = NIL;
+	typnum = 0;
+	foreach(cell, node->parameters)
+	{
+		FunctionParameter *param = (FunctionParameter *) lfirst(cell);
+		ObjTree    *param_obj;
+		ObjTree    *defaultval;
+		ObjTree    *name;
+
+		/*
+		 * A PARAM_TABLE parameter indicates the end of input arguments; the
+		 * following parameters are part of the return type.  We ignore them
+		 * here, but keep track of the current position in the list so that we
+		 * can easily produce the return type below.
+		 */
+		if (param->mode == FUNC_PARAM_TABLE)
+		{
+			table_params = cell;
+			break;
+		}
+
+		/*
+		 * Verbose syntax for paramater: %{mode}s %{name}s %{type}T
+		 * %{default}s
+		 */
+		param_obj = new_objtree_VA("%{mode}s", 1,
+								  "mode", ObjTypeString,
+								  param->mode == FUNC_PARAM_OUT ? "OUT" :
+								  param->mode == FUNC_PARAM_INOUT ? "INOUT" :
+								  param->mode == FUNC_PARAM_VARIADIC ? "VARIADIC" :
+								  "IN");
+
+		/* Optional wholesale suppression of "name" occurs here */
+		name = new_objtree("");
+		if (param->name)
+			append_string_object(name, "%{name}I", "name", param->name);
+		else
+		{
+			append_null_object(name, "%{name}I");
+			append_not_present(name);
+		}
+
+		append_object_object(param_obj, "%{name}s", name);
+
+		defaultval = new_objtree("DEFAULT");
+		if (PointerIsValid(param->defexpr))
+		{
+			char	   *expr;
+
+			if (curdef == NULL)
+				elog(ERROR, "proargdefaults list too short");
+			expr = lfirst(curdef);
+
+			append_string_object(defaultval, "%{value}s", "value", expr);
+			curdef = lnext(defaults, curdef);
+		}
+		else
+			append_not_present(defaultval);
+
+		append_object_object(param_obj, "%{type}T",
+							 new_objtree_for_type(typarray[typnum++], -1));
+
+		append_object_object(param_obj, "%{default}s", defaultval);
+
+		params = lappend(params, new_object_object(param_obj));
+	}
+
+	tmp_obj = new_objtree_VA("%{identity}D", 1,
+							"identity", ObjTypeObject,
+							new_objtree_for_qualname_id(ProcedureRelationId,
+														objectId));
+
+	append_format_string(tmp_obj, "(");
+	append_array_object(tmp_obj, "%{arguments:, }s", params);
+	append_format_string(tmp_obj, ")");
+
+	isfunction = (procForm->prokind != PROKIND_PROCEDURE);
+
+	if (isfunction)
+		append_object_object(ret, "FUNCTION %{signature}s", tmp_obj);
+	else
+		append_object_object(ret, "PROCEDURE %{signature}s", tmp_obj);
+
+	/*
+	 * A return type can adopt one of two forms: either a [SETOF] some_type,
+	 * or a TABLE(list-of-types).  We can tell the second form because we saw
+	 * a table param above while scanning the argument list.
+	 */
+	if (table_params == NULL)
+	{
+		tmp_obj = new_objtree_VA("", 1,
+								"return_form", ObjTypeString, "plain");
+		append_string_object(tmp_obj, "%{setof}s", "setof",
+							 procForm->proretset ? "SETOF" : "");
+		append_object_object(tmp_obj, "%{rettype}T",
+							 new_objtree_for_type(procForm->prorettype, -1));
+	}
+	else
+	{
+		List	   *rettypes = NIL;
+		ObjTree    *param_obj;
+
+		tmp_obj = new_objtree_VA("TABLE", 1,
+								"return_form", ObjTypeString, "table");
+		for (; table_params != NULL; table_params = lnext(node->parameters, table_params))
+		{
+			FunctionParameter *param = lfirst(table_params);
+
+			param_obj = new_objtree_VA("%{name}I %{type}T", 2,
+									  "name", ObjTypeString, param->name,
+									  "type", ObjTypeObject,
+									  new_objtree_for_type(typarray[typnum++], -1));
+			rettypes = lappend(rettypes, new_object_object(param_obj));
+		}
+
+		append_array_object(tmp_obj, "(%{rettypes:, }s)", rettypes);
+	}
+
+	if (isfunction)
+		append_object_object(ret, "RETURNS %{return_type}s", tmp_obj);
+
+	/* TRANSFORM FOR TYPE */
+	tmp_obj = new_objtree("TRANSFORM");
+
+	ntypes = get_func_trftypes(procTup, &trftypes);
+	for (i = 0; i < ntypes; i++)
+	{
+		tmp_obj = new_objtree_VA("FOR TYPE %{type}T", 1,
+								"type", ObjTypeObject,
+								new_objtree_for_type(trftypes[i], -1));
+		types = lappend(types, tmp_obj);
+	}
+
+	if (types)
+		append_array_object(tmp_obj, "%{for_type:, }s", types);
+	else
+		append_not_present(tmp_obj);
+
+	append_object_object(ret, "%{transform_type}s", tmp_obj);
+
+	append_string_object(ret, "LANGUAGE %{language}I", "language",
+						 NameStr(langForm->lanname));
+
+	if (isfunction)
+	{
+		append_string_object(ret, "%{window}s", "window",
+							 procForm->prokind == PROKIND_WINDOW ? "WINDOW" : "");
+		append_string_object(ret, "%{volatility}s", "volatility",
+							 procForm->provolatile == PROVOLATILE_VOLATILE ?
+							 "VOLATILE" :
+							 procForm->provolatile == PROVOLATILE_STABLE ?
+							 "STABLE" : "IMMUTABLE");
+
+		append_string_object(ret, "%{parallel_safety}s",
+							 "parallel_safety",
+							 procForm->proparallel == PROPARALLEL_SAFE ?
+							 "PARALLEL SAFE" :
+							 procForm->proparallel == PROPARALLEL_RESTRICTED ?
+							 "PARALLEL RESTRICTED" : "PARALLEL UNSAFE");
+
+		append_string_object(ret, "%{leakproof}s", "leakproof",
+							 procForm->proleakproof ? "LEAKPROOF" : "");
+		append_string_object(ret, "%{strict}s", "strict",
+							 procForm->proisstrict ?
+							 "RETURNS NULL ON NULL INPUT" :
+							 "CALLED ON NULL INPUT");
+
+		append_string_object(ret, "%{security_definer}s",
+							 "security_definer",
+							 procForm->prosecdef ?
+							 "SECURITY DEFINER" : "SECURITY INVOKER");
+
+		append_object_object(ret, "%{cost}s",
+							 new_objtree_VA("COST %{cost}n", 1,
+											"cost", ObjTypeFloat,
+											procForm->procost));
+
+		tmp_obj = new_objtree("ROWS");
+		if (procForm->prorows == 0)
+			append_not_present(tmp_obj);
+		else
+			append_float_object(tmp_obj, "%{rows}n", procForm->prorows);
+		append_object_object(ret, "%{rows}s", tmp_obj);
+
+		tmp_obj = new_objtree("SUPPORT %{name}s");
+		if (procForm->prosupport)
+		{
+			Oid			argtypes[] = { INTERNALOID };
+
+			/*
+			 * We should qualify the support function's name if it wouldn't be
+			 * resolved by lookup in the current search path.
+			 */
+			append_string_object(tmp_obj, "%{name}s", "name",
+								 generate_function_name(procForm->prosupport, 1,
+														NIL, argtypes,
+														false, NULL,
+														EXPR_KIND_NONE));
+		}
+		else
+			append_not_present(tmp_obj);
+
+		append_object_object(ret, "%{support}s", tmp_obj);
+	}
+
+	foreach(cell, node->options)
+	{
+		DefElem    *defel = (DefElem *) lfirst(cell);
+
+		if (strcmp(defel->defname, "set") == 0)
+		{
+			VariableSetStmt *sstmt = (VariableSetStmt *) defel->arg;
+			char	   *value = ExtractSetVariableArgs(sstmt);
+
+			tmp_obj = deparse_FunctionSet(sstmt->kind, sstmt->name, value);
+			sets = lappend(sets, new_object_object(tmp_obj));
+		}
+	}
+	append_array_object(ret, "%{set_options: }s", sets);
+
+	/* Add the function definition */
+	(void) SysCacheGetAttr(PROCOID, procTup, Anum_pg_proc_prosqlbody, &isnull);
+	if (procForm->prolang == SQLlanguageId && !isnull)
+	{
+		StringInfoData buf;
+
+		initStringInfo(&buf);
+		print_function_sqlbody(&buf, procTup);
+
+		append_string_object(ret, "%{definition}s", "definition",
+							 buf.data);
+	}
+	else if (probin == NULL)
+		append_string_object(ret, "AS %{definition}L", "definition", source);
+	else
+	{
+		append_string_object(ret, "AS %{objfile}L", "objfile", probin);
+		append_string_object(ret, ", %{symbol}L", "symbol", source);
+	}
+
+	ReleaseSysCache(langTup);
+	ReleaseSysCache(procTup);
+
+	return ret;
+}
+
+/*
+ * Deparse a CREATE OPERATOR CLASS command.
+ *
+ * Verbose syntax
+ * CREATE OPERATOR CLASS %{identity}D %{default}s FOR TYPE %{type}T USING
+ * %{amname}I %{opfamily}s AS %{items:, }s
+ */
+static ObjTree *
+deparse_CreateOpClassStmt(CollectedCommand *cmd)
+{
+	Oid			opcoid = cmd->d.createopc.address.objectId;
+	HeapTuple	opcTup;
+	HeapTuple	opfTup;
+	Form_pg_opfamily opfForm;
+	Form_pg_opclass opcForm;
+	ObjTree    *ret;
+	ObjTree    *tmp_obj;
+	List	   *list;
+	ListCell   *cell;
+
+	/* Don't deparse SQL commands generated while creating extension */
+	if (cmd->in_extension)
+		return NULL;
+
+	opcTup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opcoid));
+	if (!HeapTupleIsValid(opcTup))
+		elog(ERROR, "cache lookup failed for opclass with OID %u", opcoid);
+	opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
+
+	opfTup = SearchSysCache1(OPFAMILYOID, opcForm->opcfamily);
+	if (!HeapTupleIsValid(opfTup))
+		elog(ERROR, "cache lookup failed for operator family with OID %u", opcForm->opcfamily);
+	opfForm = (Form_pg_opfamily) GETSTRUCT(opfTup);
+
+	ret = new_objtree_VA("CREATE OPERATOR CLASS %{identity}D %{default}s FOR TYPE %{type}T USING %{amname}I", 4,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(opcForm->opcnamespace,
+												  NameStr(opcForm->opcname)),
+						 "default", ObjTypeString,
+						 opcForm->opcdefault ? "DEFAULT" : "",
+						 "type", ObjTypeObject,
+						 new_objtree_for_type(opcForm->opcintype, -1),
+						 "amname", ObjTypeString, get_am_name(opcForm->opcmethod));
+
+	/*
+	 * Add the FAMILY clause, but if it has the same name and namespace as the
+	 * opclass, then have it expand to empty because it would cause a failure
+	 * if the opfamily was created internally.
+	 */
+	tmp_obj = new_objtree_VA("FAMILY %{opfamily}D", 1,
+							"opfamily", ObjTypeObject,
+							new_objtree_for_qualname(opfForm->opfnamespace,
+													 NameStr(opfForm->opfname)));
+
+	if (strcmp(NameStr(opfForm->opfname), NameStr(opcForm->opcname)) == 0 &&
+		opfForm->opfnamespace == opcForm->opcnamespace)
+		append_not_present(tmp_obj);
+
+	append_object_object(ret, "%{opfamily}s", tmp_obj);
+
+	/*
+	 * Add the initial item list.  Note we always add the STORAGE clause, even
+	 * when it is implicit in the original command.
+	 */
+	tmp_obj = new_objtree("STORAGE");
+	append_object_object(tmp_obj, "%{type}T",
+						 new_objtree_for_type(OidIsValid(opcForm->opckeytype) ?
+											  opcForm->opckeytype : opcForm->opcintype,
+											  -1));
+	list = list_make1(new_object_object(tmp_obj));
+
+	/* Add the declared operators */
+	foreach(cell, cmd->d.createopc.operators)
+	{
+		OpFamilyMember *oper = lfirst(cell);
+
+		tmp_obj = new_objtree_VA("OPERATOR %{num}n %{operator}O(%{ltype}T, %{rtype}T)", 4,
+								"num", ObjTypeInteger, oper->number,
+								"operator", ObjTypeObject,
+								new_objtree_for_qualname_id(OperatorRelationId,
+															oper->object),
+								"ltype", ObjTypeObject,
+								new_objtree_for_type(oper->lefttype, -1),
+								"rtype", ObjTypeObject,
+								new_objtree_for_type(oper->righttype, -1));
+
+		/* Add the FOR SEARCH / FOR ORDER BY clause */
+		if (oper->sortfamily == InvalidOid)
+			append_string_object(tmp_obj, "%{purpose}s", "purpose",
+								 "FOR SEARCH");
+		else
+		{
+			ObjTree    *tmp_obj2;
+
+			tmp_obj2 = new_objtree("FOR ORDER BY %{opfamily}D");
+			append_object_object(tmp_obj2, "opfamily",
+								 new_objtree_for_qualname_id(OperatorFamilyRelationId,
+															 oper->sortfamily));
+			append_object_object(tmp_obj, "%{purpose}s", tmp_obj2);
+		}
+
+		list = lappend(list, new_object_object(tmp_obj));
+	}
+
+	/* Add the declared support functions */
+	foreach(cell, cmd->d.createopc.procedures)
+	{
+		OpFamilyMember *proc = lfirst(cell);
+		HeapTuple	procTup;
+		Form_pg_proc procForm;
+		Oid		   *proargtypes;
+		List	   *arglist = NIL;
+		int			i;
+
+		procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(proc->object));
+		if (!HeapTupleIsValid(procTup))
+			elog(ERROR, "cache lookup failed for procedure with OID %u",
+				 proc->object);
+		procForm = (Form_pg_proc) GETSTRUCT(procTup);
+
+		tmp_obj = new_objtree_VA("FUNCTION %{num}n (%{ltype}T, %{rtype}T) %{function}D", 4,
+								"num", ObjTypeInteger, proc->number,
+								"ltype", ObjTypeObject,
+								new_objtree_for_type(proc->lefttype, -1),
+								"rtype", ObjTypeObject,
+								new_objtree_for_type(proc->righttype, -1),
+								"function", ObjTypeObject,
+								new_objtree_for_qualname(procForm->pronamespace,
+														 NameStr(procForm->proname)));
+
+		proargtypes = procForm->proargtypes.values;
+		for (i = 0; i < procForm->pronargs; i++)
+		{
+			ObjTree    *arg;
+
+			arg = new_objtree_for_type(proargtypes[i], -1);
+			arglist = lappend(arglist, new_object_object(arg));
+		}
+
+		append_format_string(tmp_obj, "(");
+		append_array_object(tmp_obj, "%{argtypes:, }T", arglist);
+		append_format_string(tmp_obj, ")");
+
+		ReleaseSysCache(procTup);
+
+		list = lappend(list, new_object_object(tmp_obj));
+	}
+
+	append_array_object(ret, "AS %{items:, }s", list);
+
+	ReleaseSysCache(opfTup);
+	ReleaseSysCache(opcTup);
+
+	return ret;
+}
+
+/*
+ * Deparse a CreateOpFamilyStmt (CREATE OPERATOR FAMILY)
+ *
+ * Given a operator family OID and the parse tree that created it, return an
+ * ObjTree representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE OPERATOR FAMILY %{identity}D USING %{amname}I
+ */
+static ObjTree *
+deparse_CreateOpFamily(Oid objectId, Node *parsetree)
+{
+	HeapTuple	opfTup;
+	HeapTuple	amTup;
+	Form_pg_opfamily opfForm;
+	Form_pg_am	amForm;
+	ObjTree    *ret;
+
+	opfTup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(opfTup))
+		elog(ERROR, "cache lookup failed for operator family with OID %u", objectId);
+	opfForm = (Form_pg_opfamily) GETSTRUCT(opfTup);
+
+	amTup = SearchSysCache1(AMOID, ObjectIdGetDatum(opfForm->opfmethod));
+	if (!HeapTupleIsValid(amTup))
+		elog(ERROR, "cache lookup failed for access method with OID %u",
+			 opfForm->opfmethod);
+	amForm = (Form_pg_am) GETSTRUCT(amTup);
+
+	ret = new_objtree_VA("CREATE OPERATOR FAMILY %{identity}D USING %{amname}I", 2,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(opfForm->opfnamespace,
+												  NameStr(opfForm->opfname)),
+						 "amname", ObjTypeString, NameStr(amForm->amname));
+
+	ReleaseSysCache(amTup);
+	ReleaseSysCache(opfTup);
+
+	return ret;
+}
+
+/*
+ * Add common clauses to CreatePolicy or AlterPolicy deparse objects.
+ */
+static void
+add_policy_clauses(ObjTree *ret, Oid policyOid, List *roles, bool do_qual,
+				   bool do_with_check)
+{
+	Relation	polRel = table_open(PolicyRelationId, AccessShareLock);
+	HeapTuple	polTup = get_catalog_object_by_oid(polRel, Anum_pg_policy_oid, policyOid);
+	Form_pg_policy polForm;
+
+	if (!HeapTupleIsValid(polTup))
+		elog(ERROR, "cache lookup failed for policy with OID %u", policyOid);
+
+	polForm = (Form_pg_policy) GETSTRUCT(polTup);
+
+	/* Add the "ON table" clause */
+	append_object_object(ret, "ON %{table}D",
+						 new_objtree_for_qualname_id(RelationRelationId,
+													 polForm->polrelid));
+
+	/*
+	 * Add the "TO role" clause, if any.  In the CREATE case, it always
+	 * contains at least PUBLIC, but in the ALTER case it might be empty.
+	 */
+	if (roles)
+	{
+		List	   *list = NIL;
+		ListCell   *cell;
+
+		foreach(cell, roles)
+		{
+			RoleSpec   *spec = (RoleSpec *) lfirst(cell);
+
+			list = lappend(list,
+						   new_object_object(new_objtree_for_rolespec(spec)));
+		}
+		append_array_object(ret, "TO %{role:, }R", list);
+	}
+	else
+		append_not_present(ret);
+
+	/* Add the USING clause, if any */
+	if (do_qual)
+	{
+		Datum		deparsed;
+		Datum		storedexpr;
+		bool		isnull;
+
+		storedexpr = heap_getattr(polTup, Anum_pg_policy_polqual,
+								  RelationGetDescr(polRel), &isnull);
+		if (isnull)
+			elog(ERROR, "null polqual expression in policy %u", policyOid);
+		deparsed = DirectFunctionCall2(pg_get_expr, storedexpr, polForm->polrelid);
+		append_string_object(ret, "USING (%{expression}s)", "expression",
+							 TextDatumGetCString(deparsed));
+	}
+	else
+		append_not_present(ret);
+
+	/* Add the WITH CHECK clause, if any */
+	if (do_with_check)
+	{
+		Datum		deparsed;
+		Datum		storedexpr;
+		bool		isnull;
+
+		storedexpr = heap_getattr(polTup, Anum_pg_policy_polwithcheck,
+								  RelationGetDescr(polRel), &isnull);
+		if (isnull)
+			elog(ERROR, "null polwithcheck expression in policy %u", policyOid);
+		deparsed = DirectFunctionCall2(pg_get_expr, storedexpr, polForm->polrelid);
+		append_string_object(ret, "WITH CHECK (%{expression}s)",
+							 "expression", TextDatumGetCString(deparsed));
+	}
+	else
+		append_not_present(ret);
+
+	relation_close(polRel, AccessShareLock);
+}
+
+/*
+ * Deparse a CreatePolicyStmt (CREATE POLICY)
+ *
+ * Given a policy OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE POLICY %{identity}I
+ */
+static ObjTree *
+deparse_CreatePolicyStmt(Oid objectId, Node *parsetree)
+{
+	CreatePolicyStmt *node = (CreatePolicyStmt *) parsetree;
+	ObjTree    *ret;
+
+	ret = new_objtree_VA("CREATE POLICY %{identity}I", 1,
+						 "identity", ObjTypeString, node->policy_name);
+
+	/* Add the rest of the stuff */
+	add_policy_clauses(ret, objectId, node->roles, node->qual != NULL,
+					   node->with_check != NULL);
+
+	return ret;
+}
+
+/*
+ * Deparse a AlterPolicyStmt (ALTER POLICY)
+ *
+ * Given a policy OID and the parse tree of the ALTER POLICY command, return
+ * an ObjTree representing the alter command.
+ *
+ * Verbose syntax
+ * ALTER POLICY %{identity}I
+ */
+static ObjTree *
+deparse_AlterPolicyStmt(Oid objectId, Node *parsetree)
+{
+	AlterPolicyStmt *node = (AlterPolicyStmt *) parsetree;
+	ObjTree    *ret;
+
+	ret = new_objtree_VA("ALTER POLICY %{identity}I", 1,
+						 "identity", ObjTypeString, node->policy_name);
+
+	/* Add the rest of the stuff */
+	add_policy_clauses(ret, objectId, node->roles, node->qual != NULL,
+					   node->with_check != NULL);
+
+	return ret;
+}
+
+/*
+ * Deparse a CreateSchemaStmt.
+ *
+ * Given a schema OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE SCHEMA %{if_not_exists}s %{name}I %{authorization}s
+*/
+static ObjTree *
+deparse_CreateSchemaStmt(Oid objectId, Node *parsetree)
+{
+	CreateSchemaStmt *node = (CreateSchemaStmt *) parsetree;
+	ObjTree    *ret;
+	ObjTree    *auth;
+
+	ret = new_objtree_VA("CREATE SCHEMA %{if_not_exists}s %{name}I", 2,
+						 "if_not_exists", ObjTypeString,
+						 node->if_not_exists ? "IF NOT EXISTS" : "",
+						 "name", ObjTypeString,
+						 node->schemaname ? node->schemaname : "");
+
+	auth = new_objtree("AUTHORIZATION");
+	if (node->authrole)
+		append_string_object(auth, "%{authorization_role}I",
+							 "authorization_role",
+							 get_rolespec_name(node->authrole));
+	else
+	{
+		append_null_object(auth, "%{authorization_role}I");
+		append_not_present(auth);
+	}
+	append_object_object(ret, "%{authorization}s", auth);
+
+	return ret;
+}
+
+/*
+ * Return the default value of a domain.
+ */
+static char *
+DomainGetDefault(HeapTuple domTup, bool missing_ok)
+{
+	Datum		def;
+	Node	   *defval;
+	char	   *defstr;
+	bool		isnull;
+
+	def = SysCacheGetAttr(TYPEOID, domTup, Anum_pg_type_typdefaultbin,
+						  &isnull);
+	if (isnull)
+	{
+		if (!missing_ok)
+			elog(ERROR, "domain \"%s\" does not have a default value",
+				NameStr(((Form_pg_type) GETSTRUCT(domTup))->typname));
+		else
+			return NULL;
+	}
+
+	defval = stringToNode(TextDatumGetCString(def));
+	defstr = deparse_expression(defval, NULL /* dpcontext? */ ,
+								false, false);
+
+	return defstr;
+}
+
+/*
+ * Deparse a AlterDomainStmt.
+ *
+ * Verbose syntax
+ * ALTER DOMAIN %{identity}D DROP DEFAULT
+ * OR
+ * ALTER DOMAIN %{identity}D SET DEFAULT %{default}s
+ * OR
+ * ALTER DOMAIN %{identity}D DROP NOT NULL
+ * OR
+ * ALTER DOMAIN %{identity}D SET NOT NULL
+ * OR
+ * ALTER DOMAIN %{identity}D ADD CONSTRAINT %{constraint_name}s %{definition}s
+ * OR
+ * ALTER DOMAIN %{identity}D DROP CONSTRAINT IF EXISTS %{constraint_name}s %{cascade}s
+ * OR
+ * ALTER DOMAIN %{identity}D VALIDATE CONSTRAINT %{constraint_name}s
+ */
+static ObjTree *
+deparse_AlterDomainStmt(Oid objectId, Node *parsetree,
+						ObjectAddress constraintAddr)
+{
+	AlterDomainStmt *node = (AlterDomainStmt *) parsetree;
+	HeapTuple	domTup;
+	Form_pg_type domForm;
+	ObjTree    *ret;
+
+	domTup = SearchSysCache1(TYPEOID, objectId);
+	if (!HeapTupleIsValid(domTup))
+		elog(ERROR, "cache lookup failed for domain with OID %u", objectId);
+	domForm = (Form_pg_type) GETSTRUCT(domTup);
+
+	switch (node->subtype)
+	{
+		case 'T':
+			/* SET DEFAULT / DROP DEFAULT */
+			if (node->def == NULL)
+				ret = new_objtree_VA("ALTER DOMAIN %{identity}D DROP DEFAULT", 2,
+									 "type", ObjTypeString, "drop default",
+									 "identity", ObjTypeObject,
+									 new_objtree_for_qualname(domForm->typnamespace,
+															  NameStr(domForm->typname)));
+			else
+				ret = new_objtree_VA("ALTER DOMAIN %{identity}D SET DEFAULT %{default}s", 3,
+									 "type", ObjTypeString, "set default",
+									 "identity", ObjTypeObject,
+									 new_objtree_for_qualname(domForm->typnamespace,
+															  NameStr(domForm->typname)),
+									 "default", ObjTypeString,
+									 DomainGetDefault(domTup, false));
+			break;
+		case 'N':
+			/* DROP NOT NULL */
+			ret = new_objtree_VA("ALTER DOMAIN %{identity}D DROP NOT NULL", 2,
+									  "type", ObjTypeString, "drop not null",
+									  "identity", ObjTypeObject,
+									  new_objtree_for_qualname(domForm->typnamespace,
+															   NameStr(domForm->typname)));
+			break;
+		case 'O':
+			/* SET NOT NULL */
+			ret = new_objtree_VA("ALTER DOMAIN %{identity}D SET NOT NULL", 2,
+								 "type", ObjTypeString, "set not null",
+								 "identity", ObjTypeObject,
+								 new_objtree_for_qualname(domForm->typnamespace,
+														  NameStr(domForm->typname)));
+			break;
+		case 'C':
+			/*
+			 * ADD CONSTRAINT.  Only CHECK constraints are supported by
+			 * domains
+			 */
+			ret = new_objtree_VA("ALTER DOMAIN %{identity}D ADD CONSTRAINT %{constraint_name}s %{definition}s", 4,
+								 "type", ObjTypeString, "add constraint",
+								 "identity", ObjTypeObject,
+								 new_objtree_for_qualname(domForm->typnamespace,
+														  NameStr(domForm->typname)),
+								 "constraint_name", ObjTypeString,
+								 get_constraint_name(constraintAddr.objectId),
+								 "definition", ObjTypeString,
+								 pg_get_constraintdef_string(constraintAddr.objectId));
+			break;
+		case 'V':
+			/* VALIDATE CONSTRAINT */
+			/*
+			 * Process subtype=specific options. Validation a constraint
+			 * requires its name.
+			 */
+			ret = new_objtree_VA("ALTER DOMAIN %{identity}D VALIDATE CONSTRAINT %{constraint_name}s", 3,
+								 "type", ObjTypeString, "validate constraint",
+								 "identity", ObjTypeObject,
+								 new_objtree_for_qualname(domForm->typnamespace,
+														  NameStr(domForm->typname)),
+								 "constraint_name", ObjTypeString, node->name);
+			break;
+		case 'X':
+			{
+				ObjTree    *tmp_obj;
+
+				/* DROP CONSTRAINT */
+				ret = new_objtree_VA("ALTER DOMAIN %{identity}D DROP CONSTRAINT IF EXISTS %{constraint_name}s", 3,
+										"type", ObjTypeString, "drop constraint",
+										"identity", ObjTypeObject,
+										new_objtree_for_qualname(domForm->typnamespace,
+																NameStr(domForm->typname)),
+										"constraint_name", ObjTypeString, node->name);
+
+				tmp_obj = new_objtree_VA("CASCADE", 1,
+										"present", ObjTypeBool, node->behavior == DROP_CASCADE);
+
+				append_object_object(ret, "%{cascade}s", tmp_obj);
+			}
+			break;
+		default:
+			elog(ERROR, "invalid subtype %c", node->subtype);
+	}
+
+	/* Done */
+	ReleaseSysCache(domTup);
+
+	return ret;
+}
+
+/*
+ * Deparse a CreateStatsStmt.
+ *
+ * Given a statistics OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE STATISTICS %{if_not_exists}s %{identity}D ON %{expr:, }s FROM %{stat_table_identity}D
+ */
+static ObjTree *
+deparse_CreateStatisticsStmt(Oid objectId, Node *parsetree)
+{
+	CreateStatsStmt *node = (CreateStatsStmt *) parsetree;
+	Form_pg_statistic_ext statform;
+	ObjTree    *ret;
+	HeapTuple	tup;
+	Datum		datum;
+	bool		isnull;
+	List	   *statexprs = NIL;
+
+	tup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(tup))
+		elog(ERROR, "cache lookup failed for statistic with OID %u", objectId);
+
+	statform = (Form_pg_statistic_ext) GETSTRUCT(tup);
+
+	ret = new_objtree_VA("CREATE STATISTICS %{if_not_exists}s %{identity}D", 2,
+						 "if_not_exists", ObjTypeString,
+						 node->if_not_exists ? "IF NOT EXISTS" : "",
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(statform->stxnamespace,
+												  NameStr(statform->stxname)));
+
+	datum = SysCacheGetAttr(STATEXTOID, tup, Anum_pg_statistic_ext_stxexprs,
+							&isnull);
+	if (!isnull)
+	{
+		ListCell   *lc;
+		Relation	statsrel;
+		List	   *context;
+		List	   *exprs = NIL;
+		char	   *exprsString;
+
+		statsrel = relation_open(statform->stxrelid, AccessShareLock);
+		context = deparse_context_for(RelationGetRelationName(statsrel),
+									  RelationGetRelid(statsrel));
+
+		exprsString = TextDatumGetCString(datum);
+		exprs = (List *) stringToNode(exprsString);
+
+		foreach(lc, exprs)
+		{
+			Node	   *expr = (Node *) lfirst(lc);
+			char	   *statexpr;
+
+			statexpr = deparse_expression(expr, context, false, false);
+			statexprs = lappend(statexprs, new_string_object(statexpr));
+		}
+
+		append_array_object(ret, "ON %{expr:, }s", statexprs);
+		pfree(exprsString);
+		relation_close(statsrel, AccessShareLock);
+	}
+
+	datum = SysCacheGetAttr(STATEXTOID, tup, Anum_pg_statistic_ext_stxkeys,
+							&isnull);
+	if (!isnull)
+	{
+		int			keyno;
+		char	   *attname;
+		List	   *statcols = NIL;
+		int2vector *indoption;
+
+		indoption = (int2vector *) DatumGetPointer(datum);
+
+		for (keyno = 0; keyno < indoption->dim1; keyno++)
+		{
+			attname = get_attname(statform->stxrelid, indoption->values[keyno],
+								  false);
+			statcols = lappend(statcols, new_string_object(attname));
+		}
+
+		if (indoption->dim1)
+		{
+			/* Append a ',' if statexprs is present else append 'ON' */
+			append_string_object(ret, "%{comma}s", "comma",
+								 statexprs ? "," : "ON");
+			append_array_object(ret, "%{cols:, }s", statcols);
+		}
+	}
+
+	append_object_object(ret, "FROM %{stat_table_identity}D",
+						 new_objtree_for_qualname(get_rel_namespace(statform->stxrelid),
+												  get_rel_name(statform->stxrelid)));
+
+	ReleaseSysCache(tup);
+
+	return ret;
+}
+
+/*
+ * Deparse an CreateForeignServerStmt (CREATE SERVER)
+ *
+ * Given a server OID and the parse tree that created it, return an ObjTree
+ * representing the alter command.
+ *
+ * Verbose syntax
+ * CREATE SERVER %{identity}I %{type}s %{version}s FOREIGN DATA WRAPPER %{fdw}I
+ * %{generic_options}s
+ */
+static ObjTree *
+deparse_CreateForeignServerStmt(Oid objectId, Node *parsetree)
+{
+	CreateForeignServerStmt *node = (CreateForeignServerStmt *) parsetree;
+	ObjTree    *ret;
+	ObjTree    *tmp;
+
+	ret = new_objtree_VA("CREATE SERVER %{identity}I", 1,
+						 "identity", ObjTypeString, node->servername);
+
+	/* Add a TYPE clause, if any */
+	tmp = new_objtree("TYPE");
+	if (node->servertype)
+		append_string_object(tmp, "%{type}L", "type", node->servertype);
+	else
+		append_not_present(tmp);
+	append_object_object(ret, "%{type}s", tmp);
+
+	/* Add a VERSION clause, if any */
+	tmp = new_objtree("VERSION");
+	if (node->version)
+		append_string_object(tmp, "%{version}L", "version", node->version);
+	else
+		append_not_present(tmp);
+	append_object_object(ret, "%{version}s", tmp);
+
+	append_string_object(ret, "FOREIGN DATA WRAPPER %{fdw}I", "fdw",
+						 node->fdwname);
+
+	/* Add an OPTIONS clause, if any */
+	append_object_object(ret, "%{generic_options}s",
+						 deparse_FdwOptions(node->options, NULL, false));
+
+	return ret;
+}
+
+/*
+ * Deparse an AlterForeignServerStmt (ALTER SERVER)
+ *
+ * Given a server OID and the parse tree that created it, return an ObjTree
+ * representing the alter command.
+ *
+ * Verbose syntax
+ * ALTER SERVER %{identity}I %{version}s %{generic_options}s
+ */
+static ObjTree *
+deparse_AlterForeignServerStmt(Oid objectId, Node *parsetree)
+{
+	AlterForeignServerStmt *node = (AlterForeignServerStmt *) parsetree;
+	ObjTree    *tmp;
+
+	/* Add a VERSION clause, if any */
+	tmp = new_objtree("VERSION");
+	if (node->has_version && node->version)
+		append_string_object(tmp, "%{version}L", "version", node->version);
+	else if (node->has_version)
+		append_string_object(tmp, "version", "version", "NULL");
+	else
+		append_not_present(tmp);
+
+	return new_objtree_VA("ALTER SERVER %{identity}I %{version}s %{generic_options}s", 3,
+						  "identity", ObjTypeString, node->servername,
+						  "version", ObjTypeObject, tmp,
+						  "generic_options", ObjTypeObject,
+						  deparse_FdwOptions(node->options, NULL, false));
+}
+
+/*
+ * Deparse a CreatePLangStmt.
+ *
+ * Given a language OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE %{or_replace}s %{trusted}s LANGUAGE %{identity}s HANDLER %{handler}D
+ * %{inline}s %{validator}s
+ */
+static ObjTree *
+deparse_CreateLangStmt(Oid objectId, Node *parsetree)
+{
+	CreatePLangStmt *node = (CreatePLangStmt *) parsetree;
+	ObjTree    *ret;
+	ObjTree    *tmp;
+	HeapTuple	langTup;
+	Form_pg_language langForm;
+
+	langTup = SearchSysCache1(LANGOID,
+							  ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(langTup))
+		elog(ERROR, "cache lookup failed for language with OID %u", objectId);
+	langForm = (Form_pg_language) GETSTRUCT(langTup);
+
+	ret = new_objtree_VA("CREATE %{or_replace}s %{trusted}s LANGUAGE %{identity}s", 3,
+						 "or_replace", ObjTypeString,
+						 node->replace ? "OR REPLACE" : "",
+						 "trusted", ObjTypeString,
+						 langForm->lanpltrusted ? "TRUSTED" : "",
+						 "identity", ObjTypeString, node->plname);
+
+	if (node->plhandler != NIL)
+	{
+		/* Add the HANDLER clause */
+		append_object_object(ret, "HANDLER %{handler}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 langForm->lanplcallfoid));
+
+		/* Add the INLINE clause, if any */
+		tmp = new_objtree("INLINE");
+		if (OidIsValid(langForm->laninline))
+		{
+			append_object_object(tmp, "%{handler_name}D",
+								 new_objtree_for_qualname_id(ProcedureRelationId,
+															 langForm->laninline));
+		}
+		else
+			append_not_present(tmp);
+		append_object_object(ret, "%{inline}s", tmp);
+
+		/* Add the VALIDATOR clause, if any */
+		tmp = new_objtree("VALIDATOR");
+		if (OidIsValid(langForm->lanvalidator))
+		{
+			append_object_object(tmp, "%{handler_name}D",
+								 new_objtree_for_qualname_id(ProcedureRelationId,
+															 langForm->lanvalidator));
+		}
+		else
+			append_not_present(tmp);
+		append_object_object(ret, "%{validator}s", tmp);
+	}
+
+	ReleaseSysCache(langTup);
+
+	return ret;
+}
+
+/*
+ * Deparse a CreateForeignTableStmt (CREATE FOREIGN TABLE).
+ *
+ * Given a table OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * CREATE FOREIGN TABLE %{if_not_exists}s %{identity}D
+ * [(%{table_elements:, }s) %{inherits}s
+ *  | PARTITION OF %{parent_identity}D (%{typed_table_elements:, }s) %{partition_bound}s]
+ * SERVER %{server}I %{generic_options}s
+ */
+static ObjTree *
+deparse_CreateForeignTableStmt(Oid objectId, Node *parsetree)
+{
+	CreateForeignTableStmt *stmt = (CreateForeignTableStmt *) parsetree;
+	Relation	relation = relation_open(objectId, AccessShareLock);
+	List	   *dpcontext;
+	ObjTree    *createStmt;
+	ObjTree    *tmpobj;
+	List	   *tableelts = NIL;
+
+	createStmt = new_objtree("CREATE FOREIGN TABLE");
+
+	append_string_object(createStmt, "%{if_not_exists}s", "if_not_exists",
+						 stmt->base.if_not_exists ? "IF NOT EXISTS" : "");
+
+	tmpobj = new_objtree_for_qualname(relation->rd_rel->relnamespace,
+								   RelationGetRelationName(relation));
+	append_object_object(createStmt, "%{identity}D", tmpobj);
+
+	dpcontext = deparse_context_for(RelationGetRelationName(relation),
+									objectId);
+	if (stmt->base.partbound)
+	{
+		/* Partitioned table */
+		List	   *parents;
+		ObjElem    *elem;
+
+		parents = deparse_InhRelations(objectId);
+		elem = (ObjElem *) linitial(parents);
+
+		Assert(list_length(parents) == 1);
+
+		append_format_string(createStmt, "PARTITION OF");
+
+		append_object_object(createStmt, "%{parent_identity}D",
+										 elem->value.object);
+
+		tableelts = deparse_TableElements(relation, stmt->base.tableElts, dpcontext,
+										  true, /* typed table */
+										  false);	/* not composite */
+		tableelts = obtainConstraints(tableelts, objectId, InvalidOid);
+
+		tmpobj = new_objtree("");
+		if (tableelts)
+			append_array_object(tmpobj, "(%{elements:, }s)", tableelts);
+		else
+			append_not_present(tmpobj);
+
+		append_object_object(createStmt, "%{typed_table_elements}s", tmpobj);
+
+		/*
+		 * Add the partition_bound_spec, i.e. the FOR VALUES clause.
+		 * Get pg_class.relpartbound. We cannot use partbound in the parsetree
+		 * directly as it's the original partbound expression which haven't
+		 * been transformed.
+		 */
+		append_string_object(createStmt, "%{partition_bound}s", "partition_bound",
+							 RelationGetPartitionBound(objectId));
+
+		/* No PARTITION BY clause for CREATE FOREIGN TABLE */
+	}
+	else
+	{
+		tableelts = deparse_TableElements(relation, stmt->base.tableElts, dpcontext,
+										  false,		/* not typed table */
+										  false);	/* not composite */
+		tableelts = obtainConstraints(tableelts, objectId, InvalidOid);
+
+		if (tableelts)
+			append_array_object(createStmt, "(%{table_elements:, }s)", tableelts);
+		else
+			append_format_string(createStmt, "()");
+
+		/*
+		* Add inheritance specification.  We cannot simply scan the list of
+		* parents from the parser node, because that may lack the actual
+		* qualified names of the parent relations.  Rather than trying to
+		* re-resolve them from the information in the parse node, it seems
+		* more accurate and convenient to grab it from pg_inherits.
+		*/
+		tmpobj = new_objtree("INHERITS");
+		if (stmt->base.inhRelations != NIL)
+			append_array_object(tmpobj, "(%{parents:, }D)", deparse_InhRelations(objectId));
+		else
+		{
+			append_null_object(tmpobj, "(%{parents:, }D)");
+			append_not_present(tmpobj);
+		}
+		append_object_object(createStmt, "%{inherits}s", tmpobj);
+	}
+
+	append_string_object(createStmt, "SERVER %{server}I", "server", stmt->servername);
+
+	/* add an OPTIONS clause, if any */
+	append_object_object(createStmt, "%{generic_options}s",
+						 deparse_FdwOptions(stmt->options, NULL, false));
+
+	relation_close(relation, AccessShareLock);
+
+	return createStmt;
+}
+
+/*
+ * Deparse a DefineStmt.
+ */
+static ObjTree *
+deparse_DefineStmt(Oid objectId, Node *parsetree, ObjectAddress secondaryObj)
+{
+	DefineStmt *define = (DefineStmt *) parsetree;
+
+	switch (define->kind)
+	{
+		case OBJECT_AGGREGATE:
+			return deparse_DefineStmt_Aggregate(objectId, define);
+
+		case OBJECT_COLLATION:
+			return deparse_DefineStmt_Collation(objectId, define, secondaryObj);
+
+		case OBJECT_OPERATOR:
+			return deparse_DefineStmt_Operator(objectId, define);
+
+		case OBJECT_TSCONFIGURATION:
+			return deparse_DefineStmt_TSConfig(objectId, define, secondaryObj);
+
+		case OBJECT_TSDICTIONARY:
+			return deparse_DefineStmt_TSDictionary(objectId, define);
+
+		case OBJECT_TSPARSER:
+			return deparse_DefineStmt_TSParser(objectId, define);
+
+		case OBJECT_TSTEMPLATE:
+			return deparse_DefineStmt_TSTemplate(objectId, define);
+
+		case OBJECT_TYPE:
+			return deparse_DefineStmt_Type(objectId, define);
+
+		default:
+			elog(ERROR, "unsupported object kind: %d", define->kind);
+	}
+
+	return NULL;
+}
+
+/*
+ * Form an ObjElem to be used as a single argument in an aggregate argument
+ * list
+ */
+static ObjElem *
+form_agg_argument(int idx, char *modes, char **names, Oid *types)
+{
+	ObjTree	   *arg;
+
+	arg = new_objtree("");
+
+	append_string_object(arg, "%{mode}s", "mode",
+						 (modes && modes[idx] == 'v') ? "VARIADIC" : "");
+	append_string_object(arg, "%{name}s", "name", names ? names[idx] : "");
+	append_object_object(arg, "%{type}T",
+						 new_objtree_for_type(types[idx], -1));
+
+	return new_object_object(arg);
+}
+
+/*
+ * Deparse a DefineStmt (CREATE AGGREGATE)
+ *
+ * Given a aggregate OID, return an ObjTree representing the CREATE command.
+ *
+ * Verbose syntax
+ * CREATE AGGREGATE %{identity}D(%{types}s) (%{elems:, }s)
+ */
+static ObjTree *
+deparse_DefineStmt_Aggregate(Oid objectId, DefineStmt *define)
+{
+	HeapTuple   aggTup;
+	HeapTuple   procTup;
+	ObjTree	   *stmt;
+	ObjTree	   *tmp;
+	List	   *list;
+	Datum		initval;
+	bool		isnull;
+	Form_pg_aggregate agg;
+	Form_pg_proc proc;
+	Form_pg_operator op;
+	HeapTuple	tup;
+
+	aggTup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(aggTup))
+		elog(ERROR, "cache lookup failed for aggregate with OID %u", objectId);
+	agg = (Form_pg_aggregate) GETSTRUCT(aggTup);
+
+	procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(agg->aggfnoid));
+	if (!HeapTupleIsValid(procTup))
+		elog(ERROR, "cache lookup failed for procedure with OID %u",
+			 agg->aggfnoid);
+	proc = (Form_pg_proc) GETSTRUCT(procTup);
+
+	stmt = new_objtree("CREATE AGGREGATE");
+
+	append_object_object(stmt, "%{identity}D",
+						 new_objtree_for_qualname(proc->pronamespace,
+												  NameStr(proc->proname)));
+
+	/*
+	 * Add the argument list.  There are three cases to consider:
+	 *
+	 * 1. no arguments, in which case the signature is (*).
+	 *
+	 * 2. Not an ordered-set aggregate.  In this case there's one or more
+	 * arguments.
+	 *
+	 * 3. Ordered-set aggregates. These have zero or more direct arguments, and
+	 * one or more ordered arguments.
+	 *
+	 * We don't need to consider default values or table parameters, and the
+	 * only mode that we need to consider is VARIADIC.
+	 */
+
+	if (proc->pronargs == 0)
+		append_string_object(stmt, "(%{types}s)", "types", "*");
+	else if (!AGGKIND_IS_ORDERED_SET(agg->aggkind))
+	{
+		int			i;
+		int			nargs;
+		Oid		   *types;
+		char	   *modes;
+		char	  **names;
+
+		nargs = get_func_arg_info(procTup, &types, &names, &modes);
+
+		/* only direct arguments in this case */
+		list = NIL;
+		for (i = 0; i < nargs; i++)
+		{
+			list = lappend(list, form_agg_argument(i, modes, names, types));
+		}
+
+		tmp = new_objtree_VA("%{direct:, }s", 1,
+							 "direct", ObjTypeArray, list);
+		append_object_object(stmt, "(%{types}s)", tmp);
+	}
+	else
+	{
+		int			i;
+		int			nargs;
+		Oid		   *types;
+		char	   *modes;
+		char	  **names;
+
+		nargs = get_func_arg_info(procTup, &types, &names, &modes);
+
+		/* direct arguments ... */
+		list = NIL;
+		for (i = 0; i < agg->aggnumdirectargs; i++)
+		{
+			list = lappend(list, form_agg_argument(i, modes, names, types));
+		}
+		tmp = new_objtree_VA("%{direct:, }s", 1,
+							 "direct", ObjTypeArray, list);
+
+		/*
+		 * ... and aggregated arguments.  If the last direct argument is
+		 * VARIADIC, we need to repeat it here rather than searching for more
+		 * arguments.  (See aggr_args production in gram.y for an explanation.)
+		 */
+		if (modes && modes[agg->aggnumdirectargs - 1] == 'v')
+		{
+			list = list_make1(form_agg_argument(agg->aggnumdirectargs - 1,
+												modes, names, types));
+		}
+		else
+		{
+			list = NIL;
+			for (i = agg->aggnumdirectargs; i < nargs; i++)
+			{
+				list = lappend(list, form_agg_argument(i, modes, names, types));
+			}
+		}
+		append_array_object(tmp, "ORDER BY %{aggregated:, }s", list);
+
+		append_object_object(stmt, "(%{types}s)", tmp);
+	}
+
+	/* Add the definition clause */
+	list = NIL;
+
+	/* SFUNC */
+	tmp = new_objtree_VA("SFUNC=%{procedure}D", 1,
+						 "procedure", ObjTypeObject,
+						 new_objtree_for_qualname_id(ProcedureRelationId, agg->aggtransfn));
+	list = lappend(list, new_object_object(tmp));
+
+	/* STYPE */
+	tmp = new_objtree_VA("STYPE=%{type}T", 1,
+						 "type", ObjTypeObject,
+						 new_objtree_for_type(agg->aggtranstype, -1));
+	list = lappend(list, new_object_object(tmp));
+
+	/* SSPACE */
+	tmp = new_objtree("SSPACE=");
+	if (agg->aggtransspace != 0)
+		append_int_object(tmp,"%{space}n", agg->aggtransspace);
+	else
+		append_not_present(tmp);
+
+	list = lappend(list, new_object_object(tmp));
+
+	/* FINALFUNC */
+	tmp = new_objtree("FINALFUNC=");
+	if (OidIsValid(agg->aggfinalfn))
+		append_object_object(tmp, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 agg->aggfinalfn));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* FINALFUNC_EXTRA */
+	tmp = new_objtree("FINALFUNC_EXTRA=");
+	if (agg->aggfinalextra)
+		append_string_object(tmp, "%{value}s", "value", "true");
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* INITCOND */
+	initval = SysCacheGetAttr(AGGFNOID, aggTup,
+							  Anum_pg_aggregate_agginitval,
+							  &isnull);
+	tmp = new_objtree("INITCOND=");
+	if (!isnull)
+		append_string_object(tmp,"%{initval}L", "initval", TextDatumGetCString(initval));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* MSFUNC */
+	tmp = new_objtree("MSFUNC=");
+	if (OidIsValid(agg->aggmtransfn))
+		append_object_object(tmp, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId, agg->aggmtransfn));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* MSTYPE */
+	tmp = new_objtree("MSTYPE=");
+	if (OidIsValid(agg->aggmtranstype))
+		append_object_object(tmp, "%{type}T", new_objtree_for_type(agg->aggmtranstype, -1));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* MSSPACE */
+	tmp = new_objtree("MSSPACE=");
+	if (agg->aggmtransspace != 0)
+		append_int_object(tmp, "%{space}n", agg->aggmtransspace);
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* MINVFUNC */
+	tmp = new_objtree("MINVFUNC=");
+	if (OidIsValid(agg->aggminvtransfn))
+		append_object_object(tmp, "%{type}T", new_objtree_for_qualname_id(ProcedureRelationId,
+															agg->aggminvtransfn));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* MFINALFUNC */
+	tmp = new_objtree("MFINALFUNC=");
+	if (OidIsValid(agg->aggmfinalfn))
+		append_object_object(tmp, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 agg->aggmfinalfn));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* MFINALFUNC_EXTRA */
+	tmp = new_objtree("MFINALFUNC_EXTRA=");
+	if (agg->aggmfinalextra)
+		append_string_object(tmp, "%{value}s", "value", "true");
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* MINITCOND */
+	initval = SysCacheGetAttr(AGGFNOID, aggTup,
+							  Anum_pg_aggregate_aggminitval,
+							  &isnull);
+	tmp = new_objtree("MINITCOND=");
+	if (!isnull)
+		append_string_object(tmp, "%{initval}L", "initval", TextDatumGetCString(initval));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* HYPOTHETICAL */
+	tmp = new_objtree("HYPOTHETICAL=");
+	if (agg->aggkind == AGGKIND_HYPOTHETICAL)
+		append_string_object(tmp, "%{value}s", "value", "true");
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* SORTOP */
+	tmp = new_objtree("SORTOP=");
+	if (OidIsValid(agg->aggsortop))
+	{
+		tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(agg->aggsortop));
+		if (!HeapTupleIsValid(tup))
+			elog(ERROR, "cache lookup failed for operator with OID %u", agg->aggsortop);
+		op = (Form_pg_operator) GETSTRUCT(tup);
+		append_object_object(tmp, "%{operator}D",
+							 new_objtree_for_qualname(op->oprnamespace,
+													  NameStr(op->oprname)));
+
+		ReleaseSysCache(tup);
+	}
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* Done with the definition clause */
+	append_array_object(stmt, "(%{elems:, }s)", list);
+
+	ReleaseSysCache(procTup);
+	ReleaseSysCache(aggTup);
+
+	return stmt;
+}
+
+/*
+ * Deparse a DefineStmt (CREATE COLLATION)
+ *
+ * Given a collation OID, return an ObjTree representing the CREATE command.
+ *
+ * Verbose syntax
+ * CREATE COLLATION %{identity}D FROM %{from_identity}D (%{elems:, }s)
+ */
+static ObjTree *
+deparse_DefineStmt_Collation(Oid objectId, DefineStmt *define,
+							 ObjectAddress fromCollid)
+{
+	ObjTree    *ret;
+	HeapTuple	colTup;
+	Form_pg_collation colForm;
+	Datum		datum;
+	bool		isnull;
+	ObjTree    *tmp;
+	List	   *list = NIL;
+
+	colTup = SearchSysCache1(COLLOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(colTup))
+		elog(ERROR, "cache lookup failed for collation with OID %u", objectId);
+	colForm = (Form_pg_collation) GETSTRUCT(colTup);
+
+	ret = new_objtree_VA("CREATE COLLATION %{identity}D", 1,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(colForm->collnamespace,
+												  NameStr(colForm->collname)));
+
+	if (OidIsValid(fromCollid.objectId))
+	{
+		Oid			collid = fromCollid.objectId;
+		HeapTuple	tp;
+		Form_pg_collation fromColForm;
+
+		/*
+		 * CREATE COLLATION %{identity}D FROM existing_collation;
+		 */
+		tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
+		if (!HeapTupleIsValid(tp))
+			elog(ERROR, "cache lookup failed for collation with OID %u", collid);
+
+		fromColForm = (Form_pg_collation) GETSTRUCT(tp);
+
+		append_object_object(ret, "FROM %{from_identity}D",
+							 new_objtree_for_qualname(fromColForm->collnamespace,
+													  NameStr(fromColForm->collname)));
+
+		ReleaseSysCache(tp);
+		ReleaseSysCache(colTup);
+		return ret;
+	}
+
+	/* LOCALE */
+	datum = SysCacheGetAttr(COLLOID, colTup, Anum_pg_collation_colliculocale, &isnull);
+	if (!isnull)
+	{
+		tmp = new_objtree_VA("LOCALE=%{locale}L", 2,
+							 "clause", ObjTypeString, "locale",
+							 "locale", ObjTypeString,
+							 psprintf("%s", TextDatumGetCString(datum)));
+		list = lappend(list, new_object_object(tmp));
+	}
+
+	/* LC_COLLATE */
+	datum = SysCacheGetAttr(COLLOID, colTup, Anum_pg_collation_collcollate, &isnull);
+	if (!isnull)
+	{
+		tmp = new_objtree_VA("LC_COLLATE=%{collate}L", 2,
+							 "clause", ObjTypeString, "collate",
+							 "collate", ObjTypeString,
+							 psprintf("%s", TextDatumGetCString(datum)));
+		list = lappend(list, new_object_object(tmp));
+	}
+
+	/* LC_CTYPE */
+	datum = SysCacheGetAttr(COLLOID, colTup, Anum_pg_collation_collctype, &isnull);
+	if (!isnull)
+	{
+		tmp = new_objtree_VA("LC_CTYPE=%{ctype}L", 2,
+							 "clause", ObjTypeString, "ctype",
+							 "ctype", ObjTypeString,
+							 psprintf("%s", TextDatumGetCString(datum)));
+		list = lappend(list, new_object_object(tmp));
+	}
+
+	/* PROVIDER */
+	if (colForm->collprovider == COLLPROVIDER_ICU)
+	{
+		tmp = new_objtree_VA("PROVIDER=%{provider}L", 2,
+							 "clause", ObjTypeString, "provider",
+							 "provider", ObjTypeString,
+							 psprintf("%s", "icu"));
+		list = lappend(list, new_object_object(tmp));
+	}
+	else if (colForm->collprovider == COLLPROVIDER_LIBC)
+	{
+		tmp = new_objtree_VA("PROVIDER=%{provider}L", 2,
+							 "clause", ObjTypeString, "provider",
+							 "provider", ObjTypeString,
+							 psprintf("%s", "libc"));
+		list = lappend(list, new_object_object(tmp));
+	}
+
+	/* DETERMINISTIC */
+	if (colForm->collisdeterministic)
+	{
+		tmp = new_objtree_VA("DETERMINISTIC=%{deterministic}L", 2,
+							 "clause", ObjTypeString, "deterministic",
+							 "deterministic", ObjTypeString,
+							 psprintf("%s", "true"));
+		list = lappend(list, new_object_object(tmp));
+	}
+
+	/* VERSION */
+	datum = SysCacheGetAttr(COLLOID, colTup, Anum_pg_collation_collversion, &isnull);
+	if (!isnull)
+	{
+		tmp = new_objtree_VA("VERSION=%{version}L", 2,
+							 "clause", ObjTypeString, "version",
+							 "version", ObjTypeString,
+							 psprintf("%s", TextDatumGetCString(datum)));
+		list = lappend(list, new_object_object(tmp));
+	}
+
+	append_array_object(ret, "(%{elems:, }s)", list);
+	ReleaseSysCache(colTup);
+
+	return ret;
+}
+
+/*
+ * Deparse a DefineStmt (CREATE OPERATOR)
+ *
+ * Given a operator OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE OPERATOR %{identity}O (%{elems:, }s)
+ */
+static ObjTree *
+deparse_DefineStmt_Operator(Oid objectId, DefineStmt *define)
+{
+	HeapTuple	oprTup;
+	ObjTree    *ret;
+	ObjTree    *tmp_obj;
+	List	   *list = NIL;
+	Form_pg_operator oprForm;
+
+	oprTup = SearchSysCache1(OPEROID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(oprTup))
+		elog(ERROR, "cache lookup failed for operator with OID %u", objectId);
+	oprForm = (Form_pg_operator) GETSTRUCT(oprTup);
+
+	ret = new_objtree_VA("CREATE OPERATOR %{identity}O", 1,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(oprForm->oprnamespace,
+												  NameStr(oprForm->oprname)));
+
+	/* PROCEDURE */
+	tmp_obj = new_objtree_VA("PROCEDURE=%{procedure}D", 2,
+							"clause", ObjTypeString, "procedure",
+							"procedure", ObjTypeObject,
+							new_objtree_for_qualname_id(ProcedureRelationId,
+														oprForm->oprcode));
+	list = lappend(list, new_object_object(tmp_obj));
+
+	/* LEFTARG */
+	tmp_obj = new_objtree_VA("LEFTARG=", 1,
+							"clause", ObjTypeString, "leftarg");
+	if (OidIsValid(oprForm->oprleft))
+		append_object_object(tmp_obj, "%{type}T",
+							 new_objtree_for_type(oprForm->oprleft, -1));
+	else
+		append_not_present(tmp_obj);
+	list = lappend(list, new_object_object(tmp_obj));
+
+	/* RIGHTARG */
+	tmp_obj = new_objtree_VA("RIGHTARG=", 1,
+							"clause", ObjTypeString, "rightarg");
+	if (OidIsValid(oprForm->oprright))
+		append_object_object(tmp_obj, "%{type}T",
+							 new_objtree_for_type(oprForm->oprright, -1));
+	else
+		append_not_present(tmp_obj);
+	list = lappend(list, new_object_object(tmp_obj));
+
+	/* COMMUTATOR */
+	tmp_obj = new_objtree_VA("COMMUTATOR=", 1,
+							"clause", ObjTypeString, "commutator");
+	if (OidIsValid(oprForm->oprcom))
+		append_object_object(tmp_obj, "%{oper}D",
+							 new_objtree_for_qualname_id(OperatorRelationId,
+														 oprForm->oprcom));
+	else
+		append_not_present(tmp_obj);
+	list = lappend(list, new_object_object(tmp_obj));
+
+	/* NEGATOR */
+	tmp_obj = new_objtree_VA("NEGATOR=", 1,
+							"clause", ObjTypeString, "negator");
+	if (OidIsValid(oprForm->oprnegate))
+		append_object_object(tmp_obj, "%{oper}D",
+							 new_objtree_for_qualname_id(OperatorRelationId,
+														 oprForm->oprnegate));
+	else
+		append_not_present(tmp_obj);
+	list = lappend(list, new_object_object(tmp_obj));
+
+	/* RESTRICT */
+	tmp_obj = new_objtree_VA("RESTRICT=", 1,
+							"clause", ObjTypeString, "restrict");
+	if (OidIsValid(oprForm->oprrest))
+		append_object_object(tmp_obj, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 oprForm->oprrest));
+	else
+		append_not_present(tmp_obj);
+	list = lappend(list, new_object_object(tmp_obj));
+
+	/* JOIN */
+	tmp_obj = new_objtree_VA("JOIN=", 1,
+							"clause", ObjTypeString, "join");
+	if (OidIsValid(oprForm->oprjoin))
+		append_object_object(tmp_obj, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 oprForm->oprjoin));
+	else
+		append_not_present(tmp_obj);
+	list = lappend(list, new_object_object(tmp_obj));
+
+	/* HASHES */
+	tmp_obj = new_objtree_VA("HASHES", 1,
+							"clause", ObjTypeString, "hashes");
+	if (!oprForm->oprcanhash)
+		append_not_present(tmp_obj);
+	list = lappend(list, new_object_object(tmp_obj));
+
+	/* MERGES */
+	tmp_obj = new_objtree_VA("MERGES", 1,
+							"clause", ObjTypeString, "merges");
+	if (!oprForm->oprcanmerge)
+		append_not_present(tmp_obj);
+	list = lappend(list, new_object_object(tmp_obj));
+
+	append_array_object(ret, "(%{elems:, }s)", list);
+
+	ReleaseSysCache(oprTup);
+
+	return ret;
+}
+
+/*
+ * Deparse a CREATE TYPE statement.
+ *
+ * Verbose syntax
+ * CREATE TYPE %{identity}D %{elems:, }s)
+ */
+static ObjTree *
+deparse_DefineStmt_Type(Oid objectId, DefineStmt *define)
+{
+	HeapTuple	typTup;
+	ObjTree    *ret;
+	ObjTree    *tmp;
+	List	   *list = NIL;
+	char	   *str;
+	Datum		dflt;
+	bool		isnull;
+	Form_pg_type typForm;
+
+	typTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(typTup))
+		elog(ERROR, "cache lookup failed for type with OID %u", objectId);
+	typForm = (Form_pg_type) GETSTRUCT(typTup);
+
+	ret = new_objtree_VA("CREATE TYPE %{identity}D", 1,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(typForm->typnamespace,
+												  NameStr(typForm->typname)));
+
+	/* Shell types. */
+	if (!typForm->typisdefined)
+	{
+		ReleaseSysCache(typTup);
+		return ret;
+	}
+
+	/* Add the definition clause */
+	/* INPUT */
+	tmp = new_objtree_VA("(INPUT=%{procedure}D", 2,
+						 "clause", ObjTypeString, "input",
+						 "procedure", ObjTypeObject,
+						 new_objtree_for_qualname_id(ProcedureRelationId,
+													 typForm->typinput));
+	list = lappend(list, new_object_object(tmp));
+
+	/* OUTPUT */
+	tmp = new_objtree_VA("OUTPUT=%{procedure}D", 2,
+						 "clause", ObjTypeString, "output",
+						 "procedure", ObjTypeObject,
+						 new_objtree_for_qualname_id(ProcedureRelationId,
+													 typForm->typoutput));
+	list = lappend(list, new_object_object(tmp));
+
+	/* RECEIVE */
+	tmp = new_objtree_VA("RECEIVE=", 1,
+						 "clause", ObjTypeString, "receive");
+	if (OidIsValid(typForm->typreceive))
+		append_object_object(tmp, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 typForm->typreceive));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* SEND */
+	tmp = new_objtree_VA("SEND=", 1,
+						 "clause", ObjTypeString, "send");
+	if (OidIsValid(typForm->typsend))
+		append_object_object(tmp, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 typForm->typsend));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* TYPMOD_IN */
+	tmp = new_objtree_VA("TYPMOD_IN=", 1,
+						 "clause", ObjTypeString, "typmod_in");
+	if (OidIsValid(typForm->typmodin))
+		append_object_object(tmp, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 typForm->typmodin));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* TYPMOD_OUT */
+	tmp = new_objtree_VA("TYPMOD_OUT=", 1,
+						 "clause", ObjTypeString, "typmod_out");
+	if (OidIsValid(typForm->typmodout))
+		append_object_object(tmp, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 typForm->typmodout));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* ANALYZE */
+	tmp = new_objtree_VA("ANALYZE=", 1,
+						 "clause", ObjTypeString, "analyze");
+	if (OidIsValid(typForm->typanalyze))
+		append_object_object(tmp, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 typForm->typanalyze));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* INTERNALLENGTH */
+	if (typForm->typlen == -1)
+		tmp = new_objtree("INTERNALLENGTH=VARIABLE");
+	else
+		tmp = new_objtree_VA("INTERNALLENGTH=%{typlen}n", 1,
+							 "typlen", ObjTypeInteger, typForm->typlen);
+
+	list = lappend(list, new_object_object(tmp));
+
+	/* PASSEDBYVALUE */
+	tmp = new_objtree_VA("PASSEDBYVALUE", 1,
+						 "clause", ObjTypeString, "passedbyvalue");
+	if (!typForm->typbyval)
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* XXX it's odd to represent alignment with schema-qualified type names */
+	switch (typForm->typalign)
+	{
+		case 'd':
+			str = "pg_catalog.float8";
+			break;
+		case 'i':
+			str = "pg_catalog.int4";
+			break;
+		case 's':
+			str = "pg_catalog.int2";
+			break;
+		case 'c':
+			str = "pg_catalog.bpchar";
+			break;
+		default:
+			elog(ERROR, "invalid alignment %c", typForm->typalign);
+	}
+
+	/* ALIGNMENT */
+	tmp = new_objtree_VA("ALIGNMENT=%{align}s", 2,
+						 "clause", ObjTypeString, "alignment",
+						 "align", ObjTypeString, str);
+	list = lappend(list, new_object_object(tmp));
+
+	/* STORAGE */
+	tmp = new_objtree_VA("STORAGE=%{storage}s", 2,
+						 "clause", ObjTypeString, "storage",
+						 "storage", ObjTypeString,
+						 get_type_storage(typForm->typstorage));
+	list = lappend(list, new_object_object(tmp));
+
+	/* CATEGORY */
+	tmp = new_objtree_VA("CATEGORY=%{category}s", 2,
+						 "clause", ObjTypeString, "category",
+						 "category", ObjTypeString,
+						 psprintf("%c", typForm->typcategory));
+	list = lappend(list, new_object_object(tmp));
+
+	/* PREFERRED */
+	tmp = new_objtree_VA("PREFERRED=%{preferred}s", 1,
+						 "preferred", ObjTypeString,
+						 typForm->typispreferred ? "TRUE" : "FALSE");
+	if (!typForm->typispreferred)
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* DEFAULT */
+	dflt = SysCacheGetAttr(TYPEOID, typTup,
+						   Anum_pg_type_typdefault,
+						   &isnull);
+	tmp = new_objtree_VA("DEFAULT=", 1,
+						 "clause", ObjTypeString, "default");
+	if (!isnull)
+		append_string_object(tmp, "%{default}s", "default",
+							 TextDatumGetCString(dflt));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* ELEMENT */
+	tmp = new_objtree_VA("ELEMENT=", 1,
+						 "clause", ObjTypeString, "element");
+	if (OidIsValid(typForm->typelem))
+		append_object_object(tmp, "%{elem}T",
+							 new_objtree_for_type(typForm->typelem, -1));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* DELIMITER */
+	tmp = new_objtree_VA("DELIMITER=", 1,
+						 "clause", ObjTypeString, "delimiter");
+	append_string_object(tmp, "%{delim}L", "delim",
+						 psprintf("%c", typForm->typdelim));
+	list = lappend(list, new_object_object(tmp));
+
+	/* COLLATABLE */
+	tmp = new_objtree_VA("COLLATABLE=", 1,
+						 "clause", ObjTypeString, "collatable");
+	if (!OidIsValid(typForm->typcollation))
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	append_array_object(ret, "%{elems:, }s)", list);
+
+	ReleaseSysCache(typTup);
+
+	return ret;
+}
+
+/*
+ * Deparse a CREATE TEXT SEARCH CONFIGURATION statement.
+ *
+ * Verbose syntax
+ * CREATE TEXT SEARCH CONFIGURATION %{identity}D (%{elems:, }s)
+ */
+static ObjTree *
+deparse_DefineStmt_TSConfig(Oid objectId, DefineStmt *define,
+							ObjectAddress copied)
+{
+	HeapTuple	tscTup;
+	HeapTuple	tspTup;
+	ObjTree    *ret;
+	ObjTree    *tmp;
+	Form_pg_ts_config tscForm;
+	Form_pg_ts_parser tspForm;
+	List	   *list = NIL;
+
+	tscTup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(tscTup))
+		elog(ERROR, "cache lookup failed for text search configuration with OID %u",
+			 objectId);
+	tscForm = (Form_pg_ts_config) GETSTRUCT(tscTup);
+
+	tspTup = SearchSysCache1(TSPARSEROID, ObjectIdGetDatum(tscForm->cfgparser));
+	if (!HeapTupleIsValid(tspTup))
+		elog(ERROR, "cache lookup failed for text search parser %u",
+			 tscForm->cfgparser);
+	tspForm = (Form_pg_ts_parser) GETSTRUCT(tspTup);
+
+	/*
+	 * Add the definition clause.  If we have COPY'ed an existing config, add
+	 * a COPY clause; otherwise add a PARSER clause.
+	 */
+	/* COPY */
+	tmp = new_objtree_VA("COPY=", 1,
+						 "clause", ObjTypeString, "copy");
+	if (OidIsValid(copied.objectId))
+		append_object_object(tmp, "%{tsconfig}D",
+							 new_objtree_for_qualname_id(TSConfigRelationId,
+														 copied.objectId));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* PARSER */
+	tmp = new_objtree_VA("PARSER=", 1,
+						 "clause", ObjTypeString, "parser");
+	if (copied.objectId == InvalidOid)
+		append_object_object(tmp, "%{parser}D",
+							 new_objtree_for_qualname(tspForm->prsnamespace,
+													  NameStr(tspForm->prsname)));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	ret = new_objtree_VA("CREATE TEXT SEARCH CONFIGURATION %{identity}D (%{elems:, }s)", 2,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(tscForm->cfgnamespace,
+												  NameStr(tscForm->cfgname)),
+						 "elems", ObjTypeArray, list);
+
+	ReleaseSysCache(tspTup);
+	ReleaseSysCache(tscTup);
+	return ret;
+}
+
+/*
+ * Deparse a CREATE TEXT SEARCH PARSER statement.
+ *
+ * Verbose syntax
+ * CREATE TEXT SEARCH PARSER %{identity}D (%{elems:, }s)
+ */
+static ObjTree *
+deparse_DefineStmt_TSParser(Oid objectId, DefineStmt *define)
+{
+	HeapTuple	tspTup;
+	ObjTree    *ret;
+	ObjTree    *tmp;
+	List	   *list = NIL;
+	Form_pg_ts_parser tspForm;
+
+	tspTup = SearchSysCache1(TSPARSEROID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(tspTup))
+		elog(ERROR, "cache lookup failed for text search parser with OID %u",
+			 objectId);
+	tspForm = (Form_pg_ts_parser) GETSTRUCT(tspTup);
+
+	/* Add the definition clause */
+	/* START */
+	tmp = new_objtree_VA("START=%{procedure}D", 2,
+						 "clause", ObjTypeString, "start",
+						 "procedure", ObjTypeObject,
+						 new_objtree_for_qualname_id(ProcedureRelationId,
+													 tspForm->prsstart));
+	list = lappend(list, new_object_object(tmp));
+
+	/* GETTOKEN */
+	tmp = new_objtree_VA("GETTOKEN=%{procedure}D", 2,
+						 "clause", ObjTypeString, "gettoken",
+						 "procedure", ObjTypeObject,
+						 new_objtree_for_qualname_id(ProcedureRelationId,
+													 tspForm->prstoken));
+	list = lappend(list, new_object_object(tmp));
+
+	/* END */
+	tmp = new_objtree_VA("END=%{procedure}D", 2,
+						 "clause", ObjTypeString, "end",
+						 "procedure", ObjTypeObject,
+						 new_objtree_for_qualname_id(ProcedureRelationId,
+													 tspForm->prsend));
+	list = lappend(list, new_object_object(tmp));
+
+	/* LEXTYPES */
+	tmp = new_objtree_VA("LEXTYPES=%{procedure}D", 2,
+						 "clause", ObjTypeString, "lextypes",
+						 "procedure", ObjTypeObject,
+						 new_objtree_for_qualname_id(ProcedureRelationId,
+													 tspForm->prslextype));
+	list = lappend(list, new_object_object(tmp));
+
+	/* HEADLINE */
+	tmp = new_objtree_VA("HEADLINE=", 1,
+						 "clause", ObjTypeString, "headline");
+	if (OidIsValid(tspForm->prsheadline))
+		append_object_object(tmp, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 tspForm->prsheadline));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	ret = new_objtree_VA("CREATE TEXT SEARCH PARSER %{identity}D (%{elems:, }s)", 2,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(tspForm->prsnamespace,
+												  NameStr(tspForm->prsname)),
+						 "elems", ObjTypeArray, list);
+
+	ReleaseSysCache(tspTup);
+	return ret;
+}
+
+/*
+ * Deparse a CREATE TEXT SEARCH DICTIONARY statement.
+ *
+ * Verbose syntax
+ * CREATE TEXT SEARCH DICTIONARY %{identity}D (%{elems:, }s)
+ */
+static ObjTree *
+deparse_DefineStmt_TSDictionary(Oid objectId, DefineStmt *define)
+{
+	HeapTuple	tsdTup;
+	ObjTree    *ret;
+	ObjTree    *tmp;
+	List	   *list = NIL;
+	Datum		options;
+	bool		isnull;
+	Form_pg_ts_dict tsdForm;
+
+	tsdTup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(tsdTup))
+		elog(ERROR, "cache lookup failed for text search dictionary with OID %u",
+			 objectId);
+	tsdForm = (Form_pg_ts_dict) GETSTRUCT(tsdTup);
+
+
+
+	/* Add the definition clause */
+	/* TEMPLATE */
+	tmp = new_objtree_VA("TEMPLATE=", 1,
+						 "clause", ObjTypeString, "template");
+	append_object_object(tmp, "%{template}D",
+						 new_objtree_for_qualname_id(TSTemplateRelationId,
+													 tsdForm->dicttemplate));
+	list = lappend(list, new_object_object(tmp));
+
+	/*
+	 * options.  XXX this is a pretty useless representation, but we can't do
+	 * better without more ts_cache.c cooperation ...
+	 */
+	options = SysCacheGetAttr(TSDICTOID, tsdTup,
+							  Anum_pg_ts_dict_dictinitoption,
+							  &isnull);
+	tmp = new_objtree("");
+	if (!isnull)
+		append_string_object(tmp, "%{options}s", "options",
+							 TextDatumGetCString(options));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	ret = new_objtree_VA("CREATE TEXT SEARCH DICTIONARY %{identity}D (%{elems:, }s)", 2,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(tsdForm->dictnamespace,
+												  NameStr(tsdForm->dictname)),
+						 "elems", ObjTypeArray, list);
+
+	ReleaseSysCache(tsdTup);
+	return ret;
+}
+
+/*
+ * Deparse a CREATE TEXT SEARCH TEMPLATE statement.
+ *
+ * Verbose syntax
+ * CREATE TEXT SEARCH TEMPLATE %{identity}D (%{elems:, }s)
+ */
+static ObjTree *
+deparse_DefineStmt_TSTemplate(Oid objectId, DefineStmt *define)
+{
+	HeapTuple	tstTup;
+	ObjTree    *ret;
+	ObjTree    *tmp;
+	List	   *list = NIL;
+	Form_pg_ts_template tstForm;
+
+	tstTup = SearchSysCache1(TSTEMPLATEOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(tstTup))
+		elog(ERROR, "cache lookup failed for text search template with OID %u",
+			 objectId);
+	tstForm = (Form_pg_ts_template) GETSTRUCT(tstTup);
+
+	/* Add the definition clause */
+	/* INIT */
+	tmp = new_objtree_VA("INIT=", 1,
+						 "clause", ObjTypeString, "init");
+	if (OidIsValid(tstForm->tmplinit))
+		append_object_object(tmp, "%{procedure}D",
+							 new_objtree_for_qualname_id(ProcedureRelationId,
+														 tstForm->tmplinit));
+	else
+		append_not_present(tmp);
+	list = lappend(list, new_object_object(tmp));
+
+	/* LEXIZE */
+	tmp = new_objtree_VA("LEXIZE=%{procedure}D", 2,
+						 "clause", ObjTypeString, "lexize",
+						 "procedure", ObjTypeObject,
+						 new_objtree_for_qualname_id(ProcedureRelationId,
+													 tstForm->tmpllexize));
+	list = lappend(list, new_object_object(tmp));
+
+	ret = new_objtree_VA("CREATE TEXT SEARCH TEMPLATE %{identity}D (%{elems:, }s)", 2,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(tstForm->tmplnamespace,
+												  NameStr(tstForm->tmplname)),
+						 "elems", ObjTypeArray, list);
+
+	ReleaseSysCache(tstTup);
+	return ret;
+}
+
+/*
+ * Deparse an ALTER TEXT SEARCH CONFIGURATION statement.
+ *
+ * Verbose syntax
+ * ALTER TEXT SEARCH CONFIGURATION %{identity}D ADD MAPPING
+ * FOR %{tokentype:, }I WITH %{dictionaries:, }D
+ *	OR
+ * ALTER TEXT SEARCH CONFIGURATION %{identity}D DROP MAPPING %{if_exists}s
+ * FOR %{tokentype}I
+ *	OR
+ * ALTER TEXT SEARCH CONFIGURATION %{identity}D ALTER MAPPING
+ * FOR %{tokentype:, }I WITH %{dictionaries:, }D
+ *	OR
+ * ALTER TEXT SEARCH CONFIGURATION %{identity}D ALTER MAPPING
+ * REPLACE %{old_dictionary}D WITH %{new_dictionary}D
+ *	OR
+ * ALTER TEXT SEARCH CONFIGURATION %{identity}D ALTER MAPPING
+ * FOR %{tokentype:, }I REPLACE %{old_dictionary}D WITH %{new_dictionary}D
+ */
+static ObjTree *
+deparse_AlterTSConfigurationStmt(CollectedCommand *cmd)
+{
+	AlterTSConfigurationStmt *node = (AlterTSConfigurationStmt *) cmd->parsetree;
+	ObjTree    *ret;
+	ObjTree    *tmp;
+	List	   *list = NIL;
+	ListCell   *cell;
+	int			i;
+
+	ret = new_objtree("ALTER TEXT SEARCH CONFIGURATION");
+
+	/* Determine the format string appropriate to each subcommand */
+	switch (node->kind)
+	{
+		case ALTER_TSCONFIG_ADD_MAPPING:
+			append_object_object(ret, "%{identity}D ADD MAPPING",
+								 new_objtree_for_qualname_id(cmd->d.atscfg.address.classId,
+															 cmd->d.atscfg.address.objectId));
+			break;
+
+		case ALTER_TSCONFIG_DROP_MAPPING:
+			append_object_object(ret, "%{identity}D DROP MAPPING",
+								 new_objtree_for_qualname_id(cmd->d.atscfg.address.classId,
+															 cmd->d.atscfg.address.objectId));
+			tmp = new_objtree("IF EXISTS");
+			append_bool_object(tmp, "present", node->missing_ok);
+			append_object_object(ret, "%{if_exists}s", tmp);
+			break;
+
+		case ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN:
+		case ALTER_TSCONFIG_REPLACE_DICT:
+		case ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN:
+			append_object_object(ret, "%{identity}D ALTER MAPPING",
+								 new_objtree_for_qualname_id(cmd->d.atscfg.address.classId,
+															 cmd->d.atscfg.address.objectId));
+			break;
+	}
+
+	/* Add the affected token list, for subcommands that have one */
+	if (node->kind == ALTER_TSCONFIG_ADD_MAPPING ||
+		node->kind == ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN ||
+		node->kind == ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN ||
+		node->kind == ALTER_TSCONFIG_DROP_MAPPING)
+	{
+		foreach(cell, node->tokentype)
+			list = lappend(list, new_string_object(strVal(lfirst(cell))));
+		append_array_object(ret, "FOR %{tokentype:, }I", list);
+	}
+
+	/* Add further subcommand-specific elements */
+	if (node->kind == ALTER_TSCONFIG_ADD_MAPPING ||
+		node->kind == ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN)
+	{
+		/* ADD MAPPING and ALTER MAPPING FOR need a list of dictionaries */
+		list = NIL;
+		for (i = 0; i < cmd->d.atscfg.ndicts; i++)
+		{
+			ObjTree    *dict_obj;
+
+			dict_obj = new_objtree_for_qualname_id(TSDictionaryRelationId,
+												  cmd->d.atscfg.dictIds[i]);
+			list = lappend(list,
+						   new_object_object(dict_obj));
+		}
+		append_array_object(ret, "WITH %{dictionaries:, }D", list);
+	}
+	else if (node->kind == ALTER_TSCONFIG_REPLACE_DICT ||
+			 node->kind == ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN)
+	{
+		/* The REPLACE forms want old and new dictionaries */
+		Assert(cmd->d.atscfg.ndicts == 2);
+		append_object_object(ret, "REPLACE %{old_dictionary}D",
+							 new_objtree_for_qualname_id(TSDictionaryRelationId,
+														 cmd->d.atscfg.dictIds[0]));
+		append_object_object(ret, "WITH %{new_dictionary}D",
+							 new_objtree_for_qualname_id(TSDictionaryRelationId,
+														 cmd->d.atscfg.dictIds[1]));
+	}
+
+	return ret;
+}
+
+/*
+ * Deparse an ALTER TEXT SEARCH DICTIONARY statement.
+ *
+ * Verbose syntax
+ * ALTER TEXT SEARCH DICTIONARY %{identity}D (%{definition:, }s)
+ */
+static ObjTree *
+deparse_AlterTSDictionaryStmt(Oid objectId, Node *parsetree)
+{
+	ObjTree    *ret;
+	ObjTree    *tmp;
+	Datum		options;
+	List	   *definition = NIL;
+	bool		isnull;
+	HeapTuple	tsdTup;
+	Form_pg_ts_dict tsdForm;
+
+	tsdTup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(tsdTup))
+		elog(ERROR, "cache lookup failed for text search dictionary with OID %u",
+			 objectId);
+	tsdForm = (Form_pg_ts_dict) GETSTRUCT(tsdTup);
+
+	/*
+	 * Add the definition list according to the pg_ts_dict dictinitoption
+	 * column
+	 */
+	options = SysCacheGetAttr(TSDICTOID, tsdTup,
+							  Anum_pg_ts_dict_dictinitoption,
+							  &isnull);
+	tmp = new_objtree("");
+	if (!isnull)
+		append_string_object(tmp, "%{options}s", "options",
+							 TextDatumGetCString(options));
+	else
+		append_not_present(tmp);
+
+	definition = lappend(definition, new_object_object(tmp));
+
+	ret = new_objtree_VA("ALTER TEXT SEARCH DICTIONARY %{identity}D (%{definition:, }s)", 2,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(tsdForm->dictnamespace,
+												  NameStr(tsdForm->dictname)),
+						 "definition", ObjTypeArray, definition);
+
+	ReleaseSysCache(tsdTup);
+	return ret;
+}
+
+/*
+ * deparse_ViewStmt
+ *		deparse a ViewStmt
+ *
+ * Given a view OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE %{or_replace}s %{persistence}s VIEW %{identity}D AS %{query}s
+ */
+static ObjTree *
+deparse_ViewStmt(Oid objectId, Node *parsetree)
+{
+	ViewStmt   *node = (ViewStmt *) parsetree;
+	ObjTree    *ret;
+	Relation	relation;
+
+	relation = relation_open(objectId, AccessShareLock);
+
+	ret = new_objtree_VA("CREATE %{or_replace}s %{persistence}s VIEW %{identity}D AS %{query}s", 4,
+						 "or_replace", ObjTypeString,
+						 node->replace ? "OR REPLACE" : "",
+						 "persistence", ObjTypeString,
+						 get_persistence_str(relation->rd_rel->relpersistence),
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(relation->rd_rel->relnamespace,
+												  RelationGetRelationName(relation)),
+						 "query", ObjTypeString,
+						 pg_get_viewdef_string(objectId));
+
+	relation_close(relation, AccessShareLock);
+	return ret;
+}
+
+/*
+ * Deparse CREATE Materialized View statement, it is a variant of
+ * CreateTableAsStmt
+ *
+ * Note that CREATE TABLE AS SELECT INTO can also be deparsed by
+ * deparse_CreateTableAsStmt to remove the SELECT INTO clause.
+ *
+ * Verbose syntax
+ * CREATE %{persistence}s [MATERIALIZED VIEW | TABLE] %{if_not_exists}s
+ * 		%{identity}D %{columns}s [%{on_commit}s] %{tablespace}s
+ *  		AS %{query}s %{with_no_data}s"
+ */
+static ObjTree *
+deparse_CreateTableAsStmt_vanilla(Oid objectId, Node *parsetree)
+{
+	CreateTableAsStmt *node = (CreateTableAsStmt *) parsetree;
+	Relation	relation = relation_open(objectId, AccessShareLock);
+	ObjTree    *ret;
+	ObjTree    *tmp;
+	ObjTree    *tmp2;
+	char	   *fmt;
+	List	   *list = NIL;
+	ListCell   *cell;
+
+	/* Reject unsupported case right away. */
+	if (((Query *) (node->query))->commandType == CMD_UTILITY)
+		elog(ERROR, "unimplemented deparse of CREATE TABLE AS EXECUTE");
+
+	/*
+	 * Note that INSERT INTO is deparsed as CREATE TABLE AS.  They are
+	 * functionally equivalent synonyms so there is no harm from this.
+	 */
+	if (node->objtype == OBJECT_MATVIEW)
+		fmt = "CREATE %{persistence}s MATERIALIZED VIEW %{if_not_exists}s %{identity}D";
+	else
+		fmt = "CREATE %{persistence}s TABLE %{if_not_exists}s %{identity}D";
+
+	ret = new_objtree_VA(fmt, 3,
+						 "persistence", ObjTypeString,
+						 get_persistence_str(node->into->rel->relpersistence),
+						 "if_not_exists", ObjTypeString,
+						 node->if_not_exists ? "IF NOT EXISTS" : "",
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname_id(RelationRelationId,
+													 objectId));
+
+	/* COLUMNS clause */
+	if (node->into->colNames)
+	{
+		foreach(cell, node->into->colNames)
+			list = lappend(list, new_string_object(strVal(lfirst(cell))));
+
+		tmp = new_objtree_VA("(%{columns:, }I)", 1,
+							 "columns", ObjTypeArray, list);
+	}
+	else
+		tmp = new_objtree_VA("", 1,
+							 "present", ObjTypeBool, false);
+
+	append_object_object(ret, "%{columns}s", tmp);
+
+	/* USING clause */
+	tmp = new_objtree("USING");
+	if (node->into->accessMethod)
+		append_string_object(tmp, "%{access_method}I", "access_method",
+							 node->into->accessMethod);
+	else
+	{
+		append_null_object(tmp, "%{access_method}I");
+		append_not_present(tmp);
+	}
+	append_object_object(ret, "%{access_method}s", tmp);
+
+	/* WITH clause */
+	tmp = new_objtree("WITH");
+	list = NIL;
+
+	foreach(cell, node->into->options)
+	{
+		DefElem    *opt = (DefElem *) lfirst(cell);
+
+		tmp2 = deparse_DefElem(opt, false);
+		list = lappend(list, new_object_object(tmp2));
+	}
+
+	if (list)
+		append_array_object(tmp, "(%{with:, }s)", list);
+	else
+		append_not_present(tmp);
+
+	append_object_object(ret, "%{with_clause}s", tmp);
+
+	/* ON COMMIT clause.  CREATE MATERIALIZED VIEW doesn't have one */
+	if (node->objtype == OBJECT_TABLE)
+		append_object_object(ret, "%{on_commit}s",
+							 deparse_OnCommitClause(node->into->onCommit));
+
+	/* TABLESPACE clause */
+	tmp = new_objtree("TABLESPACE %{tablespace}I");
+	if (node->into->tableSpaceName)
+		append_string_object(tmp, "%{tablespace}s", "tablespace",
+							 node->into->tableSpaceName);
+	else
+	{
+		append_null_object(tmp, "%{tablespace}I");
+		append_not_present(tmp);
+	}
+	append_object_object(ret, "%{tablespace}s", tmp);
+
+	/* Add the query */
+	Assert(IsA(node->query, Query));
+	append_string_object(ret, "AS %{query}s", "query",
+						 pg_get_querydef((Query *) node->query, false));
+
+	/* Add a WITH NO DATA clause */
+	tmp = new_objtree_VA("WITH NO DATA", 1,
+						 "present", ObjTypeBool,
+						 node->into->skipData ? true : false);
+	append_object_object(ret, "%{with_no_data}s", tmp);
+
+	relation_close(relation, AccessShareLock);
+
+	return ret;
+}
+
+/*
+ * Deparse a CreateTrigStmt (CREATE TRIGGER)
+ *
+ * Given a trigger OID and the parse tree that created it, return an ObjTree
+ * representing the creation command.
+ *
+ * Verbose syntax
+ * CREATE %{constraint}s TRIGGER %{name}I %{time}s %{events: OR }s ON
+ * %{relation}D %{from_table}s %{constraint_attrs: }s %{referencing: }s
+ * FOR EACH %{for_each}s %{when}s EXECUTE PROCEDURE %{function}s
+ */
+static ObjTree *
+deparse_CreateTrigStmt(Oid objectId, Node *parsetree)
+{
+	CreateTrigStmt *node = (CreateTrigStmt *) parsetree;
+	Relation	pg_trigger;
+	HeapTuple	trigTup;
+	Form_pg_trigger trigForm;
+	ObjTree    *ret;
+	ObjTree    *tmp_obj;
+	int			tgnargs;
+	List	   *list = NIL;
+	List	   *events;
+	char	   *trigtiming;
+	char	   *tgoldtable;
+	char	   *tgnewtable;
+	Datum		value;
+	bool		isnull;
+
+	pg_trigger = table_open(TriggerRelationId, AccessShareLock);
+
+	trigTup = get_catalog_object_by_oid(pg_trigger, Anum_pg_trigger_oid, objectId);
+	trigForm = (Form_pg_trigger) GETSTRUCT(trigTup);
+
+	trigtiming = node->timing == TRIGGER_TYPE_BEFORE ? "BEFORE" :
+		node->timing == TRIGGER_TYPE_AFTER ? "AFTER" :
+		node->timing == TRIGGER_TYPE_INSTEAD ? "INSTEAD OF" :
+		NULL;
+	if (!trigtiming)
+		elog(ERROR, "unrecognized trigger timing type %d", node->timing);
+
+	ret = new_objtree_VA("CREATE %{constraint}s TRIGGER %{name}I %{time}s", 3,
+						 "constraint", ObjTypeString, node->isconstraint ? "CONSTRAINT" : "",
+						 "name", ObjTypeString, node->trigname,
+						 "time", ObjTypeString, trigtiming);
+
+	/*
+	 * Decode the events that the trigger fires for.  The output is a list; in
+	 * most cases it will just be a string with the event name, but when
+	 * there's an UPDATE with a list of columns, we return a JSON object.
+	 */
+	events = NIL;
+	if (node->events & TRIGGER_TYPE_INSERT)
+		events = lappend(events, new_string_object("INSERT"));
+	if (node->events & TRIGGER_TYPE_DELETE)
+		events = lappend(events, new_string_object("DELETE"));
+	if (node->events & TRIGGER_TYPE_TRUNCATE)
+		events = lappend(events, new_string_object("TRUNCATE"));
+	if (node->events & TRIGGER_TYPE_UPDATE)
+	{
+		if (node->columns == NIL)
+		{
+			events = lappend(events, new_string_object("UPDATE"));
+		}
+		else
+		{
+			ObjTree    *update;
+			ListCell   *cell;
+			List	   *cols = NIL;
+
+			/*
+			 * Currently only UPDATE OF can be objects in the output JSON, but
+			 * we add a "kind" element so that user code can distinguish
+			 * possible future new event types.
+			 */
+			update = new_objtree_VA("UPDATE OF", 1,
+									"kind", ObjTypeString, "update_of");
+
+			foreach(cell, node->columns)
+			{
+				char	   *colname = strVal(lfirst(cell));
+
+				cols = lappend(cols, new_string_object(colname));
+			}
+
+			append_array_object(update, "%{columns:, }I", cols);
+
+			events = lappend(events, new_object_object(update));
+		}
+	}
+	append_array_object(ret, "%{events: OR }s", events);
+
+	tmp_obj = new_objtree_for_qualname_id(RelationRelationId,
+										 trigForm->tgrelid);
+	append_object_object(ret, "ON %{relation}D", tmp_obj);
+
+	tmp_obj = new_objtree("FROM");
+	if (trigForm->tgconstrrelid)
+	{
+		ObjTree    *rel;
+
+		rel = new_objtree_for_qualname_id(RelationRelationId,
+										  trigForm->tgconstrrelid);
+		append_object_object(tmp_obj, "%{relation}D", rel);
+	}
+	else
+		append_not_present(tmp_obj);
+	append_object_object(ret, "%{from_table}s", tmp_obj);
+
+	if (node->isconstraint)
+	{
+		if (!node->deferrable)
+			list = lappend(list, new_string_object("NOT"));
+		list = lappend(list, new_string_object("DEFERRABLE INITIALLY"));
+		if (node->initdeferred)
+			list = lappend(list, new_string_object("DEFERRED"));
+		else
+			list = lappend(list, new_string_object("IMMEDIATE"));
+	}
+	append_array_object(ret, "%{constraint_attrs: }s", list);
+
+	list = NIL;
+	value = fastgetattr(trigTup, Anum_pg_trigger_tgoldtable,
+						RelationGetDescr(pg_trigger), &isnull);
+	if (!isnull)
+		tgoldtable = NameStr(*DatumGetName(value));
+	else
+		tgoldtable = NULL;
+	value = fastgetattr(trigTup, Anum_pg_trigger_tgnewtable,
+						RelationGetDescr(pg_trigger), &isnull);
+	if (!isnull)
+		tgnewtable = NameStr(*DatumGetName(value));
+	else
+		tgnewtable = NULL;
+	if (tgoldtable != NULL || tgnewtable != NULL)
+	{
+		list = lappend(list, new_string_object("REFERENCING"));
+
+		if (tgoldtable != NULL)
+		{
+			list = lappend(list, new_string_object("OLD TABLE AS"));
+			list = lappend(list, new_string_object(tgoldtable));
+		}
+		if (tgnewtable != NULL)
+		{
+			list = lappend(list, new_string_object("NEW TABLE AS"));
+			list = lappend(list, new_string_object(tgnewtable));
+		}
+	}
+	append_array_object(ret, "%{referencing: }s", list);
+
+	append_string_object(ret, "FOR EACH %{for_each}s", "for_each",
+						 node->row ? "ROW" : "STATEMENT");
+
+	tmp_obj = new_objtree("WHEN");
+	if (node->whenClause)
+	{
+		Node	   *whenClause;
+
+		value = fastgetattr(trigTup, Anum_pg_trigger_tgqual,
+							RelationGetDescr(pg_trigger), &isnull);
+		if (isnull)
+			elog(ERROR, "null tgqual for trigger \"%s\"",
+				 NameStr(trigForm->tgname));
+
+		whenClause = stringToNode(TextDatumGetCString(value));
+		append_string_object(tmp_obj, "(%{clause}s)", "clause",
+							 pg_get_trigger_whenclause(trigForm,
+													   whenClause,
+													   false));
+	}
+	else
+		append_not_present(tmp_obj);
+	append_object_object(ret, "%{when}s", tmp_obj);
+
+	tmp_obj = new_objtree_VA("%{funcname}D", 1,
+							"funcname", ObjTypeObject,
+							new_objtree_for_qualname_id(ProcedureRelationId,
+														trigForm->tgfoid));
+	list = NIL;
+	tgnargs = trigForm->tgnargs;
+	if (tgnargs > 0)
+	{
+		char	   *p;
+		int			i;
+
+		value = fastgetattr(trigTup, Anum_pg_trigger_tgargs,
+							RelationGetDescr(pg_trigger), &isnull);
+		if (isnull)
+			elog(ERROR, "null tgargs for trigger \"%s\"",
+				 NameStr(trigForm->tgname));
+		p = (char *) VARDATA_ANY(DatumGetByteaPP(value));
+		for (i = 0; i < tgnargs; i++)
+		{
+			list = lappend(list, new_string_object(p));
+			/* advance p to next string embedded in tgargs */
+			while (*p)
+				p++;
+			p++;
+		}
+	}
+
+	append_format_string(tmp_obj, "(");
+	append_array_object(tmp_obj, "%{args:, }L", list);	/* might be NIL */
+	append_format_string(tmp_obj, ")");
+
+	append_object_object(ret, "EXECUTE FUNCTION %{function}s", tmp_obj);
+
+	table_close(pg_trigger, AccessShareLock);
+
+	return ret;
+}
+
+/*
+ * Deparse a CreateUserMappingStmt (CREATE USER MAPPING)
+ *
+ * Given a User Mapping OID and the parse tree that created it,
+ * return an ObjTree representing the CREATE USER MAPPING command.
+ *
+ * Verbose syntax
+ * CREATE USER MAPPING FOR %{role}R SERVER %{server}I
+ */
+static ObjTree *
+deparse_CreateUserMappingStmt(Oid objectId, Node *parsetree)
+{
+	CreateUserMappingStmt *node = (CreateUserMappingStmt *) parsetree;
+	ObjTree    *ret;
+	Relation	rel;
+	HeapTuple	tp;
+	Form_pg_user_mapping form;
+	ForeignServer *server;
+
+	rel = table_open(UserMappingRelationId, RowExclusiveLock);
+
+	/*
+	 * Lookup object in the catalog, so we don't have to deal with
+	 * current_user and such.
+	 */
+	tp = SearchSysCache1(USERMAPPINGOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(tp))
+		elog(ERROR, "cache lookup failed for user mapping with OID %u",
+			 objectId);
+
+	form = (Form_pg_user_mapping) GETSTRUCT(tp);
+
+	server = GetForeignServer(form->umserver);
+
+	ret = new_objtree_VA("CREATE USER MAPPING FOR %{role}R SERVER %{server}I %{generic_options}s", 3,
+						 "role", ObjTypeObject,
+						 new_objtree_for_role_id(form->umuser),
+						 "server", ObjTypeString, server->servername,
+						 "generic_options", ObjTypeObject,
+						 deparse_FdwOptions(node->options, NULL, false));
+
+	ReleaseSysCache(tp);
+	table_close(rel, RowExclusiveLock);
+	return ret;
+}
+
+/*
+ * deparse_AlterUserMapping
+ *
+ * Given a User Mapping OID and the parse tree that created it, return an
+ * ObjTree representing the alter command.
+ *
+ * Verbose syntax
+ * ALTER USER MAPPING FOR %{role}R SERVER %{server}I
+ */
+static ObjTree *
+deparse_AlterUserMappingStmt(Oid objectId, Node *parsetree)
+{
+	AlterUserMappingStmt *node = (AlterUserMappingStmt *) parsetree;
+	ObjTree    *ret;
+	Relation	rel;
+	HeapTuple	tp;
+	Form_pg_user_mapping form;
+	ForeignServer *server;
+
+	rel = table_open(UserMappingRelationId, RowExclusiveLock);
+
+	/*
+	 * Lookup object in the catalog, so we don't have to deal with
+	 * current_user and such.
+	 */
+	tp = SearchSysCache1(USERMAPPINGOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(tp))
+		elog(ERROR, "cache lookup failed for user mapping with OID %u",
+			 objectId);
+
+	form = (Form_pg_user_mapping) GETSTRUCT(tp);
+
+	server = GetForeignServer(form->umserver);
+
+	ret = new_objtree_VA("ALTER USER MAPPING FOR %{role}R SERVER %{server}I %{generic_options}s", 3,
+						 "role", ObjTypeObject,
+						 new_objtree_for_role_id(form->umuser),
+						 "server", ObjTypeString, server->servername,
+						 "generic_options", ObjTypeObject,
+						 deparse_FdwOptions(node->options, NULL, false));
+
+	ReleaseSysCache(tp);
+	table_close(rel, RowExclusiveLock);
+	return ret;
+}
+
+/*
+ * Deparse an AlterStatsStmt (ALTER STATISTICS)
+ *
+ * Given a alter statistics OID and the parse tree that created it, return an
+ * ObjTree representing the alter command.
+ *
+ * Verbose syntax
+ * ALTER STATISTICS %{identity}D SET STATISTICS %{target}n
+ */
+static ObjTree *
+deparse_AlterStatsStmt(Oid objectId, Node *parsetree)
+{
+	AlterStatsStmt *node = (AlterStatsStmt *) parsetree;
+	ObjTree    *ret;
+	HeapTuple	tp;
+	Form_pg_statistic_ext statform;
+
+	if (!node->stxstattarget)
+		return NULL;
+
+	/* Lookup object in the catalog */
+	tp = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(tp))
+		elog(ERROR, "cache lookup failed for statistic with OID %u", objectId);
+
+	statform = (Form_pg_statistic_ext) GETSTRUCT(tp);
+	ret = new_objtree_VA("ALTER STATISTICS %{identity}D SET STATISTICS %{target}n", 2,
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname(statform->stxnamespace,
+												  NameStr(statform->stxname)),
+						 "target", ObjTypeInteger, node->stxstattarget);
+
+	ReleaseSysCache(tp);
+	return ret;
+}
+
+/*
+ * Deparse a RefreshMatViewStmt (REFRESH MATERIALIZED VIEW)
+ *
+ * Given a materialized view OID and the parse tree that created it, return an
+ * ObjTree representing the refresh command.
+ *
+ * Verbose syntax
+ * REFRESH MATERIALIZED VIEW %{concurrently}s %{identity}D %{with_no_data}s
+ */
+static ObjTree *
+deparse_RefreshMatViewStmt(Oid objectId, Node *parsetree)
+{
+	RefreshMatViewStmt *node = (RefreshMatViewStmt *) parsetree;
+	ObjTree    *ret;
+	ObjTree    *tmp;
+
+	ret = new_objtree_VA("REFRESH MATERIALIZED VIEW %{concurrently}s %{identity}D", 2,
+						 "concurrently", ObjTypeString,
+						 node->concurrent ? "CONCURRENTLY" : "",
+						 "identity", ObjTypeObject,
+						 new_objtree_for_qualname_id(RelationRelationId,
+													 objectId));
+
+	/* Add a WITH NO DATA clause */
+	tmp = new_objtree_VA("WITH NO DATA", 1,
+						 "present", ObjTypeBool,
+						 node->skipData ? true : false);
+	append_object_object(ret, "%{with_no_data}s", tmp);
+
+	return ret;
+}
+
+/*
+ * Deparse a RenameStmt.
+ *
+ * Verbose syntax
+ * ALTER %s %{if_exists}s %{identity}D RENAME TO %{newname}I
+ * OR
+ * ALTER POLICY %{if_exists}s %{policyname}I ON %{identity}D RENAME TO %{newname}I
+ * OR
+ * ALTER DOMAIN %{identity}D RENAME CONSTRAINT %{oldname}I TO %{newname}I
+ * OR
+ * ALTER TABLE %{identity}D RENAME CONSTRAINT %{oldname}I TO %{newname}I
+ * OR
+ * ALTER objtype %{identity}D RENAME ATTRIBUTE %{colname}I TO %{newname}I %{cascade}s
+ * OR
+ * ALTER objtype %{if_exists}s %%{identity}D RENAME COLUMN %{colname}I TO %{newname}I
+ * OR
+ * ALTER %s %%{identity}s RENAME TO %%{newname}I
+ * OR
+ * ALTER %s %%{identity}D USING %%{index_method}s RENAME TO %%{newname}I
+ * OR
+ * ALTER SCHEMA %{identity}I RENAME TO %{newname}I
+ * OR
+ * ALTER RULE %{rulename}I ON %{identity}D RENAME TO %{newname}I
+ * OR
+ * ALTER TRIGGER %{triggername}I ON %{identity}D RENAME TO %{newname}I
+ * OR
+ * ALTER %s %%{identity}D RENAME TO %%{newname}I
+ */
+static ObjTree *
+deparse_RenameStmt(ObjectAddress address, Node *parsetree)
+{
+	RenameStmt *node = (RenameStmt *) parsetree;
+	ObjTree    *ret;
+	Relation	relation;
+	Oid			schemaId;
+
+	/*
+	 * In an ALTER .. RENAME command, we don't have the original name of the
+	 * object in system catalogs: since we inspect them after the command has
+	 * executed, the old name is already gone.  Therefore, we extract it from
+	 * the parse node.  Note we still extract the schema name from the catalog
+	 * (it might not be present in the parse node); it cannot possibly have
+	 * changed anyway.
+	 */
+	switch (node->renameType)
+	{
+		case OBJECT_TABLE:
+		case OBJECT_INDEX:
+		case OBJECT_SEQUENCE:
+		case OBJECT_VIEW:
+		case OBJECT_MATVIEW:
+		case OBJECT_FOREIGN_TABLE:
+			relation = relation_open(address.objectId, AccessShareLock);
+			schemaId = RelationGetNamespace(relation);
+			ret = new_objtree_VA("ALTER %{objtype}s %{if_exists}s %{identity}D RENAME TO %{newname}I", 4,
+								 "objtype", ObjTypeString,
+								 stringify_objtype(node->renameType, false),
+								 "if_exists", ObjTypeString,
+								 node->missing_ok ? "IF EXISTS" : "",
+								 "identity", ObjTypeObject,
+								 new_objtree_for_qualname(schemaId,
+														  node->relation->relname),
+								 "newname", ObjTypeString,
+								 node->newname);
+			relation_close(relation, AccessShareLock);
+			break;
+
+		case OBJECT_POLICY:
+			{
+				HeapTuple	polTup;
+				Form_pg_policy polForm;
+				Relation	pg_policy;
+				ScanKeyData key;
+				SysScanDesc scan;
+
+				pg_policy = relation_open(PolicyRelationId, AccessShareLock);
+				ScanKeyInit(&key, Anum_pg_policy_oid,
+							BTEqualStrategyNumber, F_OIDEQ,
+							ObjectIdGetDatum(address.objectId));
+				scan = systable_beginscan(pg_policy, PolicyOidIndexId, true,
+										  NULL, 1, &key);
+				polTup = systable_getnext(scan);
+				if (!HeapTupleIsValid(polTup))
+					elog(ERROR, "cache lookup failed for policy with OID %u",
+						 address.objectId);
+				polForm = (Form_pg_policy) GETSTRUCT(polTup);
+
+				ret = new_objtree_VA("ALTER POLICY %{if_exists}s %{policyname}I ON %{identity}D RENAME TO %{newname}I", 4,
+									 "if_exists", ObjTypeString,
+									 node->missing_ok ? "IF EXISTS" : "",
+									 "policyname", ObjTypeString,
+									 node->subname,
+									 "identity", ObjTypeObject,
+									 new_objtree_for_qualname_id(RelationRelationId,
+																 polForm->polrelid),
+									 "newname", ObjTypeString,
+									 node->newname);
+				systable_endscan(scan);
+				relation_close(pg_policy, AccessShareLock);
+			}
+			break;
+
+		case OBJECT_DOMCONSTRAINT:
+			{
+				HeapTuple	domtup;
+				HeapTuple	consttup;
+				Form_pg_constraint constform;
+				Form_pg_type domform;
+
+				/* Get domain id from the constraint */
+				consttup = SearchSysCache1(CONSTROID,
+										   ObjectIdGetDatum(address.objectId));
+				if (!HeapTupleIsValid(consttup))
+					elog(ERROR, "cache lookup failed for constraint with OID %u",
+						 address.objectId);
+				constform = (Form_pg_constraint) GETSTRUCT(consttup);
+
+				domtup = SearchSysCache1(TYPEOID,
+										 ObjectIdGetDatum(constform->contypid));
+				if (!HeapTupleIsValid(domtup))
+					elog(ERROR, "cache lookup failed for domain with OID %u",
+						 constform->contypid);
+				ReleaseSysCache(consttup);
+
+				domform = (Form_pg_type) GETSTRUCT(domtup);
+				ret = new_objtree_VA("ALTER DOMAIN %{identity}D RENAME CONSTRAINT %{oldname}I TO %{newname}I", 3,
+						"identity", ObjTypeObject,
+						new_objtree_for_qualname(domform->typnamespace,
+												 NameStr(domform->typname)),
+						"oldname", ObjTypeString, node->subname,
+						"newname", ObjTypeString, node->newname);
+				ReleaseSysCache(domtup);
+			}
+			break;
+
+		case OBJECT_TABCONSTRAINT:
+			{
+				HeapTuple	constrtup;
+				Form_pg_constraint constform;
+
+				constrtup = SearchSysCache1(CONSTROID,
+											ObjectIdGetDatum(address.objectId));
+				if (!HeapTupleIsValid(constrtup))
+					elog(ERROR, "cache lookup failed for constraint with OID %u",
+						 address.objectId);
+				constform = (Form_pg_constraint) GETSTRUCT(constrtup);
+
+				ret = new_objtree_VA("ALTER TABLE %{identity}D RENAME CONSTRAINT %{oldname}I TO %{newname}I", 3,
+									"identity", ObjTypeObject,
+									new_objtree_for_qualname_id(RelationRelationId,
+																constform->conrelid),
+									"oldname", ObjTypeString, node->subname,
+									"newname", ObjTypeString, node->newname);
+				ReleaseSysCache(constrtup);
+			}
+			break;
+
+		case OBJECT_ATTRIBUTE:
+		case OBJECT_COLUMN:
+			relation = relation_open(address.objectId, AccessShareLock);
+			schemaId = RelationGetNamespace(relation);
+
+			if (node->renameType == OBJECT_ATTRIBUTE)
+				ret = new_objtree_VA("ALTER TYPE %{identity}D RENAME ATTRIBUTE %{colname}I", 2,
+									 "identity", ObjTypeObject,
+									 new_objtree_for_qualname(schemaId,
+															  node->relation->relname),
+									 "colname", ObjTypeString, node->subname);
+			else
+			{
+				ret = new_objtree_VA("ALTER %{objtype}s", 1,
+									 "objtype", ObjTypeString,
+									 stringify_objtype(node->relationType, false));
+
+				/* Composite types do not support IF EXISTS */
+				if (node->renameType == OBJECT_COLUMN)
+					append_string_object(ret, "%{if_exists}s",
+										 "if_exists",
+										 node->missing_ok ? "IF EXISTS" : "");
+
+				append_object_object(ret, "%{identity}D",
+									 new_objtree_for_qualname(schemaId,
+															  node->relation->relname));
+				append_string_object(ret, "RENAME COLUMN %{colname}I",
+									 "colname", node->subname);
+			}
+
+			append_string_object(ret, "TO %{newname}I", "newname",
+								 node->newname);
+
+			if (node->renameType == OBJECT_ATTRIBUTE)
+				append_object_object(ret, "%{cascade}s",
+									 new_objtree_VA("CASCADE", 1,
+													"present", ObjTypeBool,
+													node->behavior == DROP_CASCADE));
+
+			relation_close(relation, AccessShareLock);
+			break;
+
+		case OBJECT_AGGREGATE:
+		case OBJECT_FUNCTION:
+		case OBJECT_ROUTINE:
+			{
+				char	   *ident;
+				HeapTuple	proctup;
+				Form_pg_proc procform;
+				List	   *identity;
+
+				Assert(IsA(node->object, ObjectWithArgs));
+				identity = ((ObjectWithArgs *) node->object)->objname;
+
+				proctup = SearchSysCache1(PROCOID,
+										  ObjectIdGetDatum(address.objectId));
+				if (!HeapTupleIsValid(proctup))
+					elog(ERROR, "cache lookup failed for procedure with OID %u",
+						 address.objectId);
+				procform = (Form_pg_proc) GETSTRUCT(proctup);
+
+				/* XXX does this work for ordered-set aggregates? */
+				ident = psprintf("%s%s",
+								 quote_qualified_identifier(get_namespace_name(procform->pronamespace),
+															strVal(llast(identity))),
+								 format_procedure_args(address.objectId, true));
+
+				ret = new_objtree_VA("ALTER %{objtype}s %{identity}s RENAME TO %{newname}I", 3,
+									 "objtype", ObjTypeString,
+									 stringify_objtype(node->renameType, false),
+									 "identity", ObjTypeString, ident,
+									 "newname", ObjTypeString, node->newname);
+
+				ReleaseSysCache(proctup);
+			}
+			break;
+
+		case OBJECT_OPCLASS:
+			{
+				HeapTuple	opcTup;
+				Form_pg_opclass opcForm;
+				List	   *oldnames;
+				char	   *schemaname;
+				char	   *opcname;
+
+				opcTup = SearchSysCache1(CLAOID, ObjectIdGetDatum(address.objectId));
+				if (!HeapTupleIsValid(opcTup))
+					elog(ERROR, "cache lookup failed for opclass with OID %u",
+						 address.objectId);
+
+				opcForm = (Form_pg_opclass) GETSTRUCT(opcTup);
+
+				oldnames = list_copy_tail((List *) node->object, 1);
+
+				/* Deconstruct the name list */
+				DeconstructQualifiedName(oldnames, &schemaname, &opcname);
+
+				ret = new_objtree_VA("ALTER %{objtype}s %{identity}D USING %{index_method}s RENAME TO %{newname}I", 4,
+									 "objtype", ObjTypeString,
+									 stringify_objtype(node->renameType, false),
+									 "identity", ObjTypeObject,
+									 new_objtree_for_qualname(opcForm->opcnamespace,
+															  opcname),
+									 "index_method", ObjTypeString,
+									 get_am_name(opcForm->opcmethod),
+									 "newname", ObjTypeString, node->newname);
+
+				ReleaseSysCache(opcTup);
+			}
+			break;
+
+		case OBJECT_OPFAMILY:
+			{
+				HeapTuple	opfTup;
+				HeapTuple	amTup;
+				Form_pg_opfamily opfForm;
+				Form_pg_am	amForm;
+				List	   *oldnames;
+				char	   *schemaname;
+				char	   *opfname;
+
+				opfTup = SearchSysCache1(OPFAMILYOID, address.objectId);
+				if (!HeapTupleIsValid(opfTup))
+					elog(ERROR, "cache lookup failed for operator family with OID %u",
+						 address.objectId);
+				opfForm = (Form_pg_opfamily) GETSTRUCT(opfTup);
+
+				amTup = SearchSysCache1(AMOID, ObjectIdGetDatum(opfForm->opfmethod));
+				if (!HeapTupleIsValid(amTup))
+					elog(ERROR, "cache lookup failed for access method with OID %u",
+						 opfForm->opfmethod);
+
+				amForm = (Form_pg_am) GETSTRUCT(amTup);
+
+				oldnames = list_copy_tail((List *) node->object, 1);
+
+				/* Deconstruct the name list */
+				DeconstructQualifiedName(oldnames, &schemaname, &opfname);
+
+				ret = new_objtree_VA("ALTER %{objtype}s %{identity}D USING %{index_method}s RENAME TO %{newname}I", 4,
+									 "objtype", ObjTypeString,
+									 stringify_objtype(node->renameType, false),
+									 "identity", ObjTypeObject,
+									 new_objtree_for_qualname(opfForm->opfnamespace,
+															  opfname),
+									 "index_method", ObjTypeString,
+									 NameStr(amForm->amname),
+									 "newname", ObjTypeString, node->newname);
+
+				ReleaseSysCache(amTup);
+				ReleaseSysCache(opfTup);
+			}
+			break;
+
+		case OBJECT_SCHEMA:
+			ret = new_objtree_VA("ALTER SCHEMA %{identity}I RENAME TO %{newname}I", 2,
+								 "identity", ObjTypeString, node->subname,
+								 "newname", ObjTypeString, node->newname);
+			break;
+
+		case OBJECT_FDW:
+		case OBJECT_LANGUAGE:
+		case OBJECT_FOREIGN_SERVER:
+		case OBJECT_PUBLICATION:
+			ret = new_objtree_VA("ALTER %{objtype}s %{identity}s RENAME TO %{newname}I", 3,
+								 "objtype", ObjTypeString,
+								 stringify_objtype(node->renameType, false),
+								 "identity", ObjTypeString,
+								 strVal(castNode(String, node->object)),
+								 "newname", ObjTypeString, node->newname);
+			break;
+
+		case OBJECT_RULE:
+			{
+				HeapTuple	rewrTup;
+				Form_pg_rewrite rewrForm;
+				Relation	pg_rewrite;
+
+				pg_rewrite = relation_open(RewriteRelationId, AccessShareLock);
+				rewrTup = get_catalog_object_by_oid(pg_rewrite, Anum_pg_rewrite_oid, address.objectId);
+				rewrForm = (Form_pg_rewrite) GETSTRUCT(rewrTup);
+
+				ret = new_objtree_VA("ALTER RULE %{rulename}I ON %{identity}D RENAME TO %{newname}I", 3,
+									 "rulename", ObjTypeString, node->subname,
+									 "identity", ObjTypeObject,
+									 new_objtree_for_qualname_id(RelationRelationId,
+																 rewrForm->ev_class),
+									 "newname", ObjTypeString, node->newname);
+				relation_close(pg_rewrite, AccessShareLock);
+			}
+			break;
+
+		case OBJECT_TRIGGER:
+			{
+				HeapTuple	trigTup;
+				Form_pg_trigger trigForm;
+				Relation	pg_trigger;
+
+				pg_trigger = relation_open(TriggerRelationId, AccessShareLock);
+				trigTup = get_catalog_object_by_oid(pg_trigger, get_object_attnum_oid(address.classId), address.objectId);
+				trigForm = (Form_pg_trigger) GETSTRUCT(trigTup);
+
+				ret = new_objtree_VA("ALTER TRIGGER %{triggername}I ON %{identity}D RENAME TO %{newname}I", 3,
+									 "triggername", ObjTypeString, node->subname,
+									 "identity", ObjTypeObject,
+									 new_objtree_for_qualname_id(RelationRelationId,
+																 trigForm->tgrelid),
+									 "newname", ObjTypeString, node->newname);
+
+				relation_close(pg_trigger, AccessShareLock);
+			}
+			break;
+
+		case OBJECT_COLLATION:
+		case OBJECT_STATISTIC_EXT:
+		case OBJECT_TYPE:
+		case OBJECT_CONVERSION:
+		case OBJECT_DOMAIN:
+		case OBJECT_TSDICTIONARY:
+		case OBJECT_TSPARSER:
+		case OBJECT_TSTEMPLATE:
+		case OBJECT_TSCONFIGURATION:
+			{
+				HeapTuple	objTup;
+				Relation	catalog;
+				Datum		objnsp;
+				bool		isnull;
+				AttrNumber	Anum_namespace;
+				List	   *identity = castNode(List, node->object);
+
+				/* Obtain object tuple */
+				catalog = relation_open(address.classId, AccessShareLock);
+				objTup = get_catalog_object_by_oid(catalog, get_object_attnum_oid(address.classId), address.objectId);
+
+				/* Obtain namespace */
+				Anum_namespace = get_object_attnum_namespace(address.classId);
+				objnsp = heap_getattr(objTup, Anum_namespace,
+									  RelationGetDescr(catalog), &isnull);
+				if (isnull)
+					elog(ERROR, "invalid NULL namespace");
+
+				ret = new_objtree_VA("ALTER %{objtype}s %{identity}D RENAME TO %{newname}I", 3,
+									 "objtype", ObjTypeString,
+									 stringify_objtype(node->renameType, false),
+									 "identity", ObjTypeObject,
+									 new_objtree_for_qualname(DatumGetObjectId(objnsp),
+															  strVal(llast(identity))),
+									 "newname", ObjTypeString, node->newname);
+				relation_close(catalog, AccessShareLock);
+			}
+			break;
+
+		default:
+			elog(ERROR, "unsupported object type %d", node->renameType);
+	}
+
+	return ret;
+}
+
+/*
+ * Deparse a AlterObjectDependsStmt (ALTER ... DEPENDS ON ...).
+ *
+ * Verbose syntax
+ * ALTER INDEX %{identity}D %{no}s DEPENDS ON EXTENSION %{newname}I
+ */
+static ObjTree *
+deparse_AlterDependStmt(Oid objectId, Node *parsetree)
+{
+	AlterObjectDependsStmt *node = (AlterObjectDependsStmt *) parsetree;
+	ObjTree    *ret = NULL;
+
+	if (node->objectType == OBJECT_INDEX)
+	{
+		ObjTree    *qualified;
+		Relation	relation = relation_open(objectId, AccessShareLock);
+
+		qualified = new_objtree_for_qualname(relation->rd_rel->relnamespace,
+											 node->relation->relname);
+		relation_close(relation, AccessShareLock);
+
+		ret = new_objtree_VA("ALTER INDEX %{identity}D %{no}s DEPENDS ON EXTENSION %{newname}I", 3,
+							 "identity", ObjTypeObject, qualified,
+							 "no", ObjTypeString,
+							 node->remove ? "NO" : "",
+							 "newname", ObjTypeString, strVal(node->extname));
+	}
+	else
+		elog(LOG, "unrecognized node type in deparse command: %d",
+			 (int) nodeTag(parsetree));
+
+	return ret;
+}
+
+/*
+ * Deparse a RuleStmt (CREATE RULE).
+ *
+ * Given a rule OID and the parse tree that created it, return an ObjTree
+ * representing the rule command.
+ *
+ * Verbose syntax
+ * CREATE RULE %{or_replace}s %{identity}I AS ON %{event}s TO %{table}D
+ * %{where_clause}s DO %{instead}s %{actions:, }s
+ */
+static ObjTree *
+deparse_RuleStmt(Oid objectId, Node *parsetree)
+{
+	RuleStmt   *node = (RuleStmt *) parsetree;
+	ObjTree    *ret;
+	ObjTree    *tmp;
+	Relation	pg_rewrite;
+	Form_pg_rewrite rewrForm;
+	HeapTuple	rewrTup;
+	SysScanDesc scan;
+	ScanKeyData key;
+	Datum		ev_qual;
+	Datum		ev_actions;
+	bool		isnull;
+	char	   *qual;
+	List	   *actions;
+	List	   *list = NIL;
+	ListCell   *cell;
+	char	   *event_str;
+
+	pg_rewrite = table_open(RewriteRelationId, AccessShareLock);
+	ScanKeyInit(&key,
+				Anum_pg_rewrite_oid,
+				BTEqualStrategyNumber,
+				F_OIDEQ, ObjectIdGetDatum(objectId));
+
+	scan = systable_beginscan(pg_rewrite, RewriteOidIndexId, true,
+							  NULL, 1, &key);
+	rewrTup = systable_getnext(scan);
+	if (!HeapTupleIsValid(rewrTup))
+		elog(ERROR, "cache lookup failed for rewrite rule with OID %u",
+			 objectId);
+
+	rewrForm = (Form_pg_rewrite) GETSTRUCT(rewrTup);
+
+	event_str = node->event == CMD_SELECT ? "SELECT" :
+		node->event == CMD_UPDATE ? "UPDATE" :
+		node->event == CMD_DELETE ? "DELETE" :
+		node->event == CMD_INSERT ? "INSERT" : NULL;
+	Assert(event_str != NULL);
+
+	ev_qual = heap_getattr(rewrTup, Anum_pg_rewrite_ev_qual,
+						   RelationGetDescr(pg_rewrite), &isnull);
+	ev_actions = heap_getattr(rewrTup, Anum_pg_rewrite_ev_action,
+							  RelationGetDescr(pg_rewrite), &isnull);
+
+	pg_get_ruledef_detailed(ev_qual, ev_actions, &qual, &actions);
+
+	tmp = new_objtree("");
+	if (qual)
+		append_string_object(tmp, "WHERE %{clause}s", "clause", qual);
+	else
+	{
+		append_null_object(tmp, "WHERE %{clause}s");
+		append_not_present(tmp);
+	}
+
+	if (actions == NIL)
+		list = lappend(list, new_string_object("NOTHING"));
+	else
+	{
+		foreach(cell, actions)
+			list = lappend(list, new_string_object(lfirst(cell)));
+	}
+
+	ret = new_objtree_VA("CREATE RULE %{or_replace}s %{identity}I AS ON %{event}s TO %{table}D %{where_clause}s DO %{instead}s", 6,
+						 "or_replace", ObjTypeString,
+						 node->replace ? "OR REPLACE" : "",
+						 "identity", ObjTypeString, node->rulename,
+						 "event", ObjTypeString, event_str,
+						 "table", ObjTypeObject,
+						 new_objtree_for_qualname_id(RelationRelationId,
+													 rewrForm->ev_class),
+						 "where_clause", ObjTypeObject, tmp,
+						 "instead", ObjTypeString,
+						 node->instead ? "INSTEAD" : "ALSO");
+
+	if (list_length(list) > 1)
+		append_array_object(ret, "(%{actions:; }s)", list);
+	else
+		append_array_object(ret, "%{actions:; }s", list);
+
+	systable_endscan(scan);
+	table_close(pg_rewrite, AccessShareLock);
+
+	return ret;
+}
+
+/*
+ * Deparse a CreateTransformStmt (CREATE TRANSFORM).
+ *
+ * Given a transform OID and the parse tree that created it, return an ObjTree
+ * representing the CREATE TRANSFORM command.
+ *
+ * Verbose syntax
+ * CREATE %{or_replace}s TRANSFORM FOR %{typename}D LANGUAGE %{language}I
+ * ( FROM SQL WITH FUNCTION %{signature}s, TO SQL WITH FUNCTION
+ * %{signature_tof}s )
+ */
+static ObjTree *
+deparse_CreateTransformStmt(Oid objectId, Node *parsetree)
+{
+	CreateTransformStmt *node = (CreateTransformStmt *) parsetree;
+	ObjTree    *ret;
+	ObjTree    *signature;
+	HeapTuple	trfTup;
+	HeapTuple	langTup;
+	HeapTuple	procTup;
+	Form_pg_transform trfForm;
+	Form_pg_language langForm;
+	Form_pg_proc procForm;
+	int			i;
+
+	/* Get the pg_transform tuple */
+	trfTup = SearchSysCache1(TRFOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(trfTup))
+		elog(ERROR, "cache lookup failed for transform with OID %u",
+			 objectId);
+	trfForm = (Form_pg_transform) GETSTRUCT(trfTup);
+
+	/* Get the corresponding pg_language tuple */
+	langTup = SearchSysCache1(LANGOID, trfForm->trflang);
+	if (!HeapTupleIsValid(langTup))
+		elog(ERROR, "cache lookup failed for language with OID %u",
+			 trfForm->trflang);
+	langForm = (Form_pg_language) GETSTRUCT(langTup);
+
+	ret = new_objtree_VA("CREATE %{or_replace}s TRANSFORM FOR %{typename}D LANGUAGE %{language}I", 3,
+						 "or_replace", ObjTypeString,
+						 node->replace ? "OR REPLACE" : "",
+						 "typename", ObjTypeObject,
+						 new_objtree_for_qualname_id(TypeRelationId,
+													 trfForm->trftype),
+						 "language", ObjTypeString,
+						 NameStr(langForm->lanname));
+
+	/* Deparse the transform_element_list */
+	if (OidIsValid(trfForm->trffromsql))
+	{
+		List	   *params = NIL;
+
+		/* Get the pg_proc tuple for the FROM FUNCTION */
+		procTup = SearchSysCache1(PROCOID, trfForm->trffromsql);
+		if (!HeapTupleIsValid(procTup))
+			elog(ERROR, "cache lookup failed for function with OID %u",
+				 trfForm->trffromsql);
+		procForm = (Form_pg_proc) GETSTRUCT(procTup);
+
+		/*
+		 * CREATE TRANSFORM does not change function signature so we can use
+		 * catalog to get input type Oids.
+		 */
+		for (i = 0; i < procForm->pronargs; i++)
+		{
+			ObjTree    *param_obj;
+
+			param_obj = new_objtree_VA("%{type}T", 1,
+									  "type", ObjTypeObject,
+								 new_objtree_for_type(procForm->proargtypes.values[i], -1));
+			params = lappend(params, new_object_object(param_obj));
+		}
+
+		signature = new_objtree_VA("%{identity}D (%{arguments:, }s)", 2,
+								   "identity", ObjTypeObject,
+								   new_objtree_for_qualname(procForm->pronamespace,
+															NameStr(procForm->proname)),
+								   "arguments", ObjTypeArray, params);
+
+		append_object_object(ret, "(FROM SQL WITH FUNCTION %{signature}s",
+							 signature);
+		ReleaseSysCache(procTup);
+	}
+	if (OidIsValid(trfForm->trftosql))
+	{
+		List	   *params = NIL;
+
+		/* Append a ',' if trffromsql is present, else append '(' */
+		append_format_string(ret, OidIsValid(trfForm->trffromsql) ? "," : "(");
+
+		/* Get the pg_proc tuple for the TO FUNCTION */
+		procTup = SearchSysCache1(PROCOID, trfForm->trftosql);
+		if (!HeapTupleIsValid(procTup))
+			elog(ERROR, "cache lookup failed for function with OID %u",
+				 trfForm->trftosql);
+		procForm = (Form_pg_proc) GETSTRUCT(procTup);
+
+		/*
+		 * CREATE TRANSFORM does not change function signature so we can use
+		 * catalog to get input type Oids.
+		 */
+		for (i = 0; i < procForm->pronargs; i++)
+		{
+			ObjTree    *param_obj = new_objtree("");
+
+			param_obj = new_objtree_VA("%{type}T", 1,
+									  "type", ObjTypeObject,
+									  new_objtree_for_type(procForm->proargtypes.values[i], -1));
+			params = lappend(params, new_object_object(param_obj));
+		}
+
+		signature = new_objtree_VA("%{identity}D (%{arguments:, }s)", 2,
+								   "identity", ObjTypeObject,
+								   new_objtree_for_qualname(procForm->pronamespace,
+															NameStr(procForm->proname)),
+								   "arguments", ObjTypeArray, params);
+
+		append_object_object(ret, "TO SQL WITH FUNCTION %{signature_tof}s",
+							 signature);
+		ReleaseSysCache(procTup);
+	}
+
+	append_format_string(ret, ")");
+
+	ReleaseSysCache(langTup);
+	ReleaseSysCache(trfTup);
+	return ret;
+}
+
+/*
+ * Deparse a CommentStmt when it pertains to a constraint.
+ *
+ * Verbose syntax
+ * COMMENT ON CONSTRAINT %{identity}s ON [DOMAIN] %{parentobj}s IS %{comment}s
+ */
+static ObjTree *
+deparse_CommentOnConstraintSmt(Oid objectId, Node *parsetree)
+{
+	CommentStmt *node = (CommentStmt *) parsetree;
+	ObjTree    *ret;
+	HeapTuple	constrTup;
+	Form_pg_constraint constrForm;
+	ObjectAddress addr;
+
+	Assert(node->objtype == OBJECT_TABCONSTRAINT || node->objtype == OBJECT_DOMCONSTRAINT);
+
+	constrTup = SearchSysCache1(CONSTROID, objectId);
+	if (!HeapTupleIsValid(constrTup))
+		elog(ERROR, "cache lookup failed for constraint with OID %u", objectId);
+	constrForm = (Form_pg_constraint) GETSTRUCT(constrTup);
+
+	if (OidIsValid(constrForm->conrelid))
+		ObjectAddressSet(addr, RelationRelationId, constrForm->conrelid);
+	else
+		ObjectAddressSet(addr, TypeRelationId, constrForm->contypid);
+
+	ret = new_objtree_VA("COMMENT ON CONSTRAINT %{identity}s ON %{domain}s %{parentobj}s", 3,
+						 "identity", ObjTypeString, pstrdup(NameStr(constrForm->conname)),
+						 "domain", ObjTypeString,
+						 (node->objtype == OBJECT_DOMCONSTRAINT) ? "DOMAIN" : "",
+						 "parentobj", ObjTypeString,
+						 getObjectIdentity(&addr, false));
+
+	/* Add the comment clause */
+	append_literal_or_null(ret, "IS %{comment}s", node->comment);
+
+	ReleaseSysCache(constrTup);
+	return ret;
+}
+
+/*
+ * Deparse an CommentStmt (COMMENT ON ...).
+ *
+ * Given the object address and the parse tree that created it, return an
+ * ObjTree representing the comment command.
+ *
+ * Verbose syntax
+ * COMMENT ON %{objtype}s %{identity}s IS %{comment}s
+ */
+static ObjTree *
+deparse_CommentStmt(ObjectAddress address, Node *parsetree)
+{
+	CommentStmt *node = (CommentStmt *) parsetree;
+	ObjTree    *ret;
+	char	   *identity;
+
+	/* Comment on subscription is not supported */
+	if (node->objtype == OBJECT_SUBSCRIPTION)
+		return NULL;
+
+	/*
+	 * Constraints are sufficiently different that it is easier to handle them
+	 * separately.
+	 */
+	if (node->objtype == OBJECT_DOMCONSTRAINT ||
+		node->objtype == OBJECT_TABCONSTRAINT)
+	{
+		Assert(address.classId == ConstraintRelationId);
+		return deparse_CommentOnConstraintSmt(address.objectId, parsetree);
+	}
+
+	ret = new_objtree_VA("COMMENT ON %{objtype}s", 1,
+						 "objtype", ObjTypeString,
+						 (char *) stringify_objtype(node->objtype, false));
+
+	/*
+	 * Add the object identity clause.  For zero argument aggregates we need
+	 * to add the (*) bit; in all other cases we can just use
+	 * getObjectIdentity.
+	 *
+	 * XXX shouldn't we instead fix the object identities for zero-argument
+	 * aggregates?
+	 */
+	if (node->objtype == OBJECT_AGGREGATE)
+	{
+		HeapTuple	procTup;
+		Form_pg_proc procForm;
+
+		procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(address.objectId));
+		if (!HeapTupleIsValid(procTup))
+			elog(ERROR, "cache lookup failed for procedure with OID %u",
+				 address.objectId);
+		procForm = (Form_pg_proc) GETSTRUCT(procTup);
+		if (procForm->pronargs == 0)
+			identity = psprintf("%s(*)",
+								quote_qualified_identifier(get_namespace_name(procForm->pronamespace),
+														   NameStr(procForm->proname)));
+		else
+			identity = getObjectIdentity(&address, false);
+		ReleaseSysCache(procTup);
+	}
+	else
+		identity = getObjectIdentity(&address, false);
+
+	append_string_object(ret, "%{identity}s", "identity", identity);
+
+	/* Add the comment clause; can be either NULL or a quoted literal. */
+	append_literal_or_null(ret, "IS %{comment}s", node->comment);
+
+	return ret;
+}
+
+/*
+ * Deparse a SECURITY LABEL command.
+ *
+ * Verbose syntax
+ * SECURITY LABEL FOR %{provider}s ON %{object_type_name}s %{identity}s IS %{label}s
+ */
+static ObjTree *
+deparse_SecLabelStmt(CollectedCommand *cmd)
+{
+	ObjTree	   *ret;
+	SecLabelStmt *node = (SecLabelStmt *) cmd->parsetree;
+
+	/* Don't deparse sql commands generated while creating extension */
+	if (cmd->in_extension)
+		return NULL;
+
+	Assert(cmd->d.seclabel.provider);
+
+	ret = new_objtree_VA("SECURITY LABEL FOR %{provider}s ON %{objtype}s %{identity}s", 3,
+						 "provider", ObjTypeString, cmd->d.seclabel.provider,
+						 "objtype", ObjTypeString, stringify_objtype(node->objtype, false),
+						 "identity", ObjTypeString, getObjectIdentity(&(cmd->d.seclabel.address), false));
+
+	/* Add the label clause; can be either NULL or a quoted literal. */
+	append_literal_or_null(ret, "IS %{label}s", node->label);
+
+	return ret;
+}
+
+/*
+ * Deparse a CreateAmStmt (CREATE ACCESS METHOD).
+ *
+ * Given an access method OID and the parse tree that created it, return an
+ * ObjTree representing the CREATE ACCESS METHOD command.
+ *
+ * Verbose syntax
+ * CREATE ACCESS METHOD %{identity}I TYPE %{am_type}s HANDLER %{handler}D
+ */
+static ObjTree *
+deparse_CreateAmStmt(Oid objectId, Node *parsetree)
+{
+	ObjTree    *ret;
+	HeapTuple	amTup;
+	Form_pg_am	amForm;
+	char	   *amtype;
+
+	amTup = SearchSysCache1(AMOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(amTup))
+		elog(ERROR, "cache lookup failed for access method with OID %u",
+			 objectId);
+	amForm = (Form_pg_am) GETSTRUCT(amTup);
+
+	switch (amForm->amtype)
+	{
+		case 'i':
+			amtype = "INDEX";
+			break;
+		case 't':
+			amtype = "TABLE";
+			break;
+		default:
+			elog(ERROR, "invalid type %c for access method", amForm->amtype);
+	}
+
+	ret = new_objtree_VA("CREATE ACCESS METHOD %{identity}I TYPE %{am_type}s HANDLER %{handler}D", 3,
+						 "identity", ObjTypeString,
+						 NameStr(amForm->amname),
+						 "am_type", ObjTypeString, amtype,
+						 "handler", ObjTypeObject,
+						 new_objtree_for_qualname_id(ProcedureRelationId,
+													 amForm->amhandler));
+
+	ReleaseSysCache(amTup);
+
+	return ret;
+}
+
+/*
+ * Deparse the publication column list.
+ *
+ * Given a tuple of pg_publication_rel, return an objTree that represent the
+ * column names.
+ */
+static ObjTree *
+deparse_PublicationRelationColumnList(HeapTuple pubreltup)
+{
+	bool		isnull;
+	List	   *collist = NIL;
+	ObjTree	   *columnlist;
+	Datum		attrsdatum;
+
+	attrsdatum = SysCacheGetAttr(PUBLICATIONRELMAP, pubreltup,
+								 Anum_pg_publication_rel_prattrs,
+								 &isnull);
+
+	columnlist = new_objtree("");
+	if (!isnull)
+	{
+		Form_pg_publication_rel pubrel;
+		ArrayType  *arr;
+		int			nelems;
+		int16	   *elems;
+
+		arr = DatumGetArrayTypeP(attrsdatum);
+		nelems = ARR_DIMS(arr)[0];
+		elems = (int16 *) ARR_DATA_PTR(arr);
+
+		pubrel = (Form_pg_publication_rel) GETSTRUCT(pubreltup);
+
+		for (int i = 0; i < nelems; i++)
+		{
+			char *colname = get_attname(pubrel->prrelid, elems[i], false);
+			collist = lappend(collist, new_string_object(colname));
+		}
+
+		append_array_object(columnlist, "(%{cols:, }s)", collist);
+	}
+	else
+		append_not_present(columnlist);
+
+	return columnlist;
+}
+
+/*
+ * Deparse the publication where clause.
+ *
+ * Given a tuple of pg_publication_rel, return a objTree that represent the
+ * publication where clause.
+ */
+static ObjTree *
+deparse_PublicationRelationWhereClause(HeapTuple pubreltup)
+{
+	Datum					qualdatum;
+	ObjTree				   *whereclause;
+	bool					isnull;
+
+	qualdatum = SysCacheGetAttr(PUBLICATIONRELMAP, pubreltup,
+								Anum_pg_publication_rel_prqual, &isnull);
+
+	whereclause = new_objtree("");
+	if (!isnull)
+	{
+		Form_pg_publication_rel pubrel;
+		Node				   *qualnode;
+		List				   *context;
+		char				   *qualstr;
+		Oid						relid;
+
+		pubrel = (Form_pg_publication_rel) GETSTRUCT(pubreltup);
+		relid = pubrel->prrelid;
+
+		context = deparse_context_for(get_rel_name(relid), relid);
+		qualnode = stringToNode(TextDatumGetCString(qualdatum));
+		qualstr = deparse_expression(qualnode, context, false, false);
+
+		append_string_object(whereclause, "WHERE %{where}s", "where", qualstr);
+	}
+	else
+		append_not_present(whereclause);
+
+	return whereclause;
+}
+
+/*
+ * Subroutine for CREATE PUBLICATION deparsing.
+ *
+ * Deal with all the publication table information including the where clause
+ * and column list.
+ */
+static List *
+deparse_PublicationRelationDefs(Oid puboid)
+{
+	Relation	pubrelsrel;
+	ScanKeyData scankey;
+	SysScanDesc scan;
+	HeapTuple	tup;
+	List	   *reldefs = NIL;
+
+	pubrelsrel = table_open(PublicationRelRelationId, AccessShareLock);
+
+	ScanKeyInit(&scankey,
+				Anum_pg_publication_rel_prpubid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(puboid));
+
+	scan = systable_beginscan(pubrelsrel, PublicationRelPrpubidIndexId,
+							  true, NULL, 1, &scankey);
+
+	while (HeapTupleIsValid(tup = systable_getnext(scan)))
+	{
+		Form_pg_publication_rel pubrel;
+		Oid						relid;
+		ObjTree				   *columnlist;
+		ObjTree				   *whereclause;
+		ObjTree				   *reldef;
+
+		pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
+		relid = pubrel->prrelid;
+
+		reldef = new_objtree_VA("%{tablename}D", 1,
+								"tablename", ObjTypeObject,
+								 new_objtree_for_qualname_id(RelationRelationId, relid));
+
+		columnlist = deparse_PublicationRelationColumnList(tup);
+		append_object_object(reldef, "%{column_list}s", columnlist);
+
+		whereclause = deparse_PublicationRelationWhereClause(tup);
+		append_object_object(reldef, "%{where_clause}s", whereclause);
+
+		reldefs = lappend(reldefs, new_object_object(reldef));
+	}
+
+	systable_endscan(scan);
+	table_close(pubrelsrel, AccessShareLock);
+
+	return reldefs;
+}
+
+/*
+ * Deparse a CreatePublicationStmt (CREATE PUBLICATION).
+ *
+ * Given an publication OID and the parse tree that created it, return an
+ * ObjTree representing the CREATE PUBLICATION command.
+ *
+ * Verbose syntax
+ * CREATE PUBLICATION %{identity}I %{for_tables}s %{for_schemas}s %{with_clause}s
+ * OR
+ * CREATE PUBLICATION %{identity}I FOR ALL TABLES %{with_clause}s
+ */
+static ObjTree *
+deparse_CreatePublicationStmt(Oid objectId, Node *parsetree)
+{
+	CreatePublicationStmt *node = (CreatePublicationStmt *) parsetree;
+	ObjTree    *createPub;
+	ObjTree    *tmp;
+	HeapTuple	pubTup;
+	Form_pg_publication	pubForm;
+	List	   *list = NIL;
+	ListCell   *cell;
+
+	pubTup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(objectId));
+	if (!HeapTupleIsValid(pubTup))
+		elog(ERROR, "cache lookup failed for access method with OID %u",
+			 objectId);
+	pubForm = (Form_pg_publication) GETSTRUCT(pubTup);
+
+	createPub = new_objtree_VA("CREATE PUBLICATION %{identity}s", 1,
+							   "identity", ObjTypeString,
+							   NameStr(pubForm->pubname));
+
+	if (node->for_all_tables)
+		append_format_string(createPub, "FOR ALL TABLES");
+	else
+	{
+		List	   *oldschemaids;
+		StringInfoData for_schemas;
+
+		/* FOR TABLES t1,t2,... */
+		tmp = new_objtree("FOR TABLE");
+
+		list = deparse_PublicationRelationDefs(objectId);
+		if (list != NIL)
+			append_array_object(tmp, "%{tables:, }s", list);
+		else
+			append_not_present(tmp);
+
+		append_object_object(createPub, "%{for_tables}s", tmp);
+
+		/* FOR TABLES IN SCHEMA s1,s2,... */
+		initStringInfo(&for_schemas);
+		if (list != NIL)
+			appendStringInfoString(&for_schemas, ", ");
+		else
+			appendStringInfoString(&for_schemas, "FOR ");
+		appendStringInfoString(&for_schemas, "TABLES IN SCHEMA");
+
+		tmp = new_objtree(for_schemas.data);
+		list = NIL;
+		oldschemaids = GetPublicationSchemas(pubForm->oid);
+		foreach(cell, oldschemaids)
+		{
+			Oid		schemaid = lfirst_oid(cell);
+			list = lappend(list, new_string_object(get_namespace_name(schemaid)));
+		}
+
+		if (list != NIL)
+			append_array_object(tmp, "%{schemas:, }I", list);
+		else
+			append_not_present(tmp);
+
+		append_object_object(createPub, "%{for_schemas}s", tmp);
+	}
+
+	/* WITH clause */
+	tmp = new_objtree("WITH");
+
+	list = NIL;
+	foreach(cell, node->options)
+	{
+		ObjTree    *tmp_obj;
+		DefElem    *opt = (DefElem *) lfirst(cell);
+
+		tmp_obj = deparse_DefElem(opt, false);
+		list = lappend(list, new_object_object(tmp_obj));
+	}
+
+	if (list != NIL)
+		append_array_object(tmp, "(%{with:, }s)", list);
+	else
+		append_not_present(tmp);
+
+	append_object_object(createPub, "%{with_clause}s", tmp);
+
+	ReleaseSysCache(pubTup);
+
+	return createPub;
+}
+
+/*
+ * Deparse a AlterPublicationStmt (ALTER PUBLICATION).
+ *
+ * Given an publication relation OID or publication schema OID and the parse
+ * tree that added it, return an ObjTree representing the ALTER PUBLICATION
+ * command.
+ *
+ * Note that only ALTER PUBLICATION ADD/SET should be deparsed here, ALTER
+ * PUBLICATION DROP is deparsed in different places.
+ *
+ * XXX ALTER PUBLICATION SET publication_object is converted to ALTER
+ * PUBLICATION ADD/DROP.
+ *
+ * Verbose syntax
+ * ALTER PUBLICATION %{identity}I %{add_object}s
+ * OR
+ * ALTER PUBLICATION %{identity}I %{set_options}s
+ */
+static ObjTree *
+deparse_AlterPublicationAddStmt(ObjectAddress object, Node *parsetree)
+{
+	char	   *pubname;
+	ObjTree	   *alterpub;
+	ObjTree	   *addobject = NULL;
+	ObjTree	   *setoption = NULL;
+	AlterPublicationStmt *node = (AlterPublicationStmt *) parsetree;
+
+	switch (object.classId)
+	{
+		/* ADD TABLE */
+		case PublicationRelRelationId:
+			{
+				ObjTree	   *whereclause;
+				ObjTree	   *columnlist;
+				Form_pg_publication_rel pubrelform;
+				Oid			relid;
+				HeapTuple	tup;
+
+				tup = SearchSysCache1(PUBLICATIONREL,
+									  ObjectIdGetDatum(object.objectId));
+
+				if (!HeapTupleIsValid(tup))
+					elog(ERROR, "cache lookup failed for publication table %u",
+						 object.objectId);
+
+				pubrelform = (Form_pg_publication_rel) GETSTRUCT(tup);
+				relid = pubrelform->prrelid;
+
+				addobject = new_objtree_VA("ADD TABLE %{tablename}D", 1,
+										   "tablename", ObjTypeObject,
+										   new_objtree_for_qualname_id(RelationRelationId, relid));
+
+				columnlist = deparse_PublicationRelationColumnList(tup);
+				append_object_object(addobject, "%{column_list}s", columnlist);
+
+				whereclause = deparse_PublicationRelationWhereClause(tup);
+				append_object_object(addobject, "%{where_clause}s", whereclause);
+
+				ReleaseSysCache(tup);
+			}
+			break;
+
+		/* ADD TABLES IN SCHEMA */
+		case PublicationNamespaceRelationId:
+			{
+				Form_pg_publication_namespace pubnspform;
+				HeapTuple	tup;
+
+				tup = SearchSysCache1(PUBLICATIONNAMESPACE,
+									  ObjectIdGetDatum(object.objectId));
+
+				if (!HeapTupleIsValid(tup))
+					elog(ERROR, "cache lookup failed for publication schema %u",
+						 object.objectId);
+
+				pubnspform = (Form_pg_publication_namespace) GETSTRUCT(tup);
+
+				addobject = new_objtree_VA("ADD TABLES IN SCHEMA %{schema}I", 1,
+										   "schema", ObjTypeString,
+										   get_namespace_name(pubnspform->pnnspid));
+
+				ReleaseSysCache(tup);
+			}
+			break;
+
+		/* SET option */
+		case PublicationRelationId:
+			{
+				List	   *optionlist = NIL;
+				ListCell   *cell;
+
+				Assert(node->options != NIL);
+
+				foreach(cell, node->options)
+				{
+					ObjTree    *tmp_obj;
+					DefElem    *opt = (DefElem *) lfirst(cell);
+
+					tmp_obj = deparse_DefElem(opt, false);
+					optionlist = lappend(optionlist, new_object_object(tmp_obj));
+				}
+
+				setoption = new_objtree_VA("SET (%{options:, }s)", 1,
+										   "options", ObjTypeArray,
+										   optionlist);
+			}
+			break;
+
+		default:
+			Assert(false);
+			break;
+	}
+
+	pubname = pstrdup(node->pubname);
+
+	alterpub = new_objtree_VA("ALTER PUBLICATION %{identity}s", 1,
+							  "identity", ObjTypeString, pubname);
+
+	Assert(addobject || setoption);
+
+	if (addobject)
+		append_object_object(alterpub, "%{add_object}s", addobject);
+	else
+		append_object_object(alterpub, "%{set_options}s", setoption);
+
+	return alterpub;
+}
+
+/*
+ * Handle deparsing of ALTER PUBLICATION DROP commands.
+ *
+ * Verbose syntax
+ * ALTER PUBLICATION %{identity}I %{drop_object}s
+ */
+char *
+deparse_AlterPublicationDropStmt(SQLDropObject *obj)
+{
+	ObjTree	   *alterpub;
+	ObjTree	   *drop_object = NULL;
+	char		objname[NAMEDATALEN];
+	char		pubname[NAMEDATALEN];
+	Jsonb	   *jsonb;
+	char	   *command;
+	StringInfoData str;
+
+	if (sscanf(obj->objidentity, "%s in publication %s", objname, pubname) != 2)
+		elog(ERROR, "could not parse ALTER PUBLICATION command \"%s\"",
+			 obj->objidentity);
+
+	switch (getObjectClass(&obj->address))
+	{
+		/* DROP TABLE */
+		case OCLASS_PUBLICATION_REL:
+			drop_object = new_objtree_VA("DROP TABLE %{tablename}s", 1,
+										 "tablename", ObjTypeString, objname);
+			break;
+
+		/* DROP TABLES IN SCHEMA */
+		case OCLASS_PUBLICATION_NAMESPACE:
+			drop_object = new_objtree_VA("DROP TABLES IN SCHEMA %{schemaname}s", 1,
+										 "schemaname", ObjTypeString, objname);
+			break;
+
+		default:
+			Assert(false);
+			break;
+	}
+
+	alterpub = new_objtree_VA("ALTER PUBLICATION %{identity}s", 1,
+							  "identity", ObjTypeString, pubname);
+
+	Assert(drop_object);
+
+	append_object_object(alterpub, "%{drop_object}s", drop_object);
+
+	initStringInfo(&str);
+	jsonb = objtree_to_jsonb(alterpub);
+	command = JsonbToCString(&str, &jsonb->root, JSONB_ESTIMATED_LEN);
+
+	return command;
+}
+
+/*
+ * Handle deparsing of simple commands.
+ *
+ * This function should cover all cases handled in ProcessUtilitySlow.
+ */
+static ObjTree *
+deparse_simple_command(CollectedCommand *cmd)
+{
+	Oid			objectId;
+	Node	   *parsetree;
+
+	Assert(cmd->type == SCT_Simple);
+
+	parsetree = cmd->parsetree;
+	objectId = cmd->d.simple.address.objectId;
+
+	if (cmd->in_extension && (nodeTag(parsetree) != T_CreateExtensionStmt))
+		return NULL;
+
+	/* This switch needs to handle everything that ProcessUtilitySlow does */
+	switch (nodeTag(parsetree))
+	{
+		case T_AlterCollationStmt:
+			return deparse_AlterCollation(objectId, parsetree);
+
+		case T_AlterDomainStmt:
+			return deparse_AlterDomainStmt(objectId, parsetree,
+										   cmd->d.simple.secondaryObject);
+
+		case T_AlterEnumStmt:
+			return deparse_AlterEnumStmt(objectId, parsetree);
+
+		case T_AlterExtensionContentsStmt:
+			return deparse_AlterExtensionContentsStmt(objectId, parsetree,
+													  cmd->d.simple.secondaryObject);
+
+		case T_AlterExtensionStmt:
+			return deparse_AlterExtensionStmt(objectId, parsetree);
+
+		case T_AlterFdwStmt:
+			return deparse_AlterFdwStmt(objectId, parsetree);
+
+		case T_AlterForeignServerStmt:
+			return deparse_AlterForeignServerStmt(objectId, parsetree);
+
+		case T_AlterFunctionStmt:
+			return deparse_AlterFunction(objectId, parsetree);
+
+		case T_AlterObjectDependsStmt:
+			return deparse_AlterDependStmt(objectId, parsetree);
+
+		case T_AlterObjectSchemaStmt:
+			return deparse_AlterObjectSchemaStmt(cmd->d.simple.address,
+												 parsetree,
+												 cmd->d.simple.secondaryObject);
+
+		case T_AlterOperatorStmt:
+			return deparse_AlterOperatorStmt(objectId, parsetree);
+
+		case T_AlterOwnerStmt:
+			return deparse_AlterOwnerStmt(cmd->d.simple.address, parsetree);
+
+		case T_AlterPolicyStmt:
+			return deparse_AlterPolicyStmt(objectId, parsetree);
+
+		case T_AlterSeqStmt:
+			return deparse_AlterSeqStmt(objectId, parsetree);
+
+		case T_AlterStatsStmt:
+			return deparse_AlterStatsStmt(objectId, parsetree);
+
+		case T_AlterTSDictionaryStmt:
+			return deparse_AlterTSDictionaryStmt(objectId, parsetree);
+
+		case T_AlterTypeStmt:
+			return deparse_AlterTypeSetStmt(objectId, parsetree);
+
+		case T_AlterUserMappingStmt:
+			return deparse_AlterUserMappingStmt(objectId, parsetree);
+
+		case T_CommentStmt:
+			return deparse_CommentStmt(cmd->d.simple.address, parsetree);
+
+		case T_CompositeTypeStmt:
+			return deparse_CompositeTypeStmt(objectId, parsetree);
+
+		case T_CreateAmStmt:
+			return deparse_CreateAmStmt(objectId, parsetree);
+
+		case T_CreateCastStmt:
+			return deparse_CreateCastStmt(objectId, parsetree);
+
+		case T_CreateConversionStmt:
+			return deparse_CreateConversion(objectId, parsetree);
+
+		case T_CreateDomainStmt:
+			return deparse_CreateDomain(objectId, parsetree);
+
+		case T_CreateEnumStmt:	/* CREATE TYPE AS ENUM */
+			return deparse_CreateEnumStmt(objectId, parsetree);
+
+		case T_CreateExtensionStmt:
+			return deparse_CreateExtensionStmt(objectId, parsetree);
+
+		case T_CreateFdwStmt:
+			return deparse_CreateFdwStmt(objectId, parsetree);
+
+		case T_CreateForeignServerStmt:
+			return deparse_CreateForeignServerStmt(objectId, parsetree);
+
+		case T_CreateFunctionStmt:
+			return deparse_CreateFunction(objectId, parsetree);
+
+		case T_CreateOpFamilyStmt:
+			return deparse_CreateOpFamily(objectId, parsetree);
+
+		case T_CreatePLangStmt:
+			return deparse_CreateLangStmt(objectId, parsetree);
+
+		case T_CreatePolicyStmt:
+			return deparse_CreatePolicyStmt(objectId, parsetree);
+
+		case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
+			return deparse_CreateRangeStmt(objectId, parsetree);
+
+		case T_CreateSchemaStmt:
+			return deparse_CreateSchemaStmt(objectId, parsetree);
+
+		case T_CreateSeqStmt:
+			return deparse_CreateSeqStmt(objectId, parsetree);
+
+		case T_CreateStatsStmt:
+			return deparse_CreateStatisticsStmt(objectId, parsetree);
+
+		case T_CreateStmt:
+			return deparse_CreateStmt(objectId, parsetree);
+
+		case T_CreateForeignTableStmt:
+			return deparse_CreateForeignTableStmt(objectId, parsetree);
+
+		case T_CreateTableAsStmt:	/* CREATE MATERIALIZED VIEW */
+			return deparse_CreateTableAsStmt_vanilla(objectId, parsetree);
+
+		case T_CreateTransformStmt:
+			return deparse_CreateTransformStmt(objectId, parsetree);
+
+		case T_CreateTrigStmt:
+			return deparse_CreateTrigStmt(objectId, parsetree);
+
+		case T_CreateUserMappingStmt:
+			return deparse_CreateUserMappingStmt(objectId, parsetree);
+
+		case T_DefineStmt:
+			return deparse_DefineStmt(objectId, parsetree,
+									  cmd->d.simple.secondaryObject);
+
+		case T_IndexStmt:
+			return deparse_IndexStmt(objectId, parsetree);
+
+		case T_RefreshMatViewStmt:
+			return deparse_RefreshMatViewStmt(objectId, parsetree);
+
+		case T_RenameStmt:
+			return deparse_RenameStmt(cmd->d.simple.address, parsetree);
+
+		case T_RuleStmt:
+			return deparse_RuleStmt(objectId, parsetree);
+
+		case T_ViewStmt:		/* CREATE VIEW */
+			return deparse_ViewStmt(objectId, parsetree);
+
+		case T_CreatePublicationStmt:
+			return deparse_CreatePublicationStmt(objectId, parsetree);
+
+		case T_AlterPublicationStmt:
+			return deparse_AlterPublicationAddStmt(cmd->d.simple.address, parsetree);
+
+		default:
+			elog(LOG, "unrecognized node type in deparse command: %d",
+				 (int) nodeTag(parsetree));
+	}
+
+	return NULL;
+}
+
+/*
+ * Workhorse to deparse a CollectedCommand.
+ */
+char *
+deparse_utility_command(CollectedCommand *cmd, bool verbose_mode)
+{
+	OverrideSearchPath *overridePath;
+	MemoryContext oldcxt;
+	MemoryContext tmpcxt;
+	ObjTree    *tree;
+	char	   *command = NULL;
+	StringInfoData str;
+
+	/*
+	 * Allocate everything done by the deparsing routines into a temp context,
+	 * to avoid having to sprinkle them with memory handling code, but
+	 * allocate the output StringInfo before switching.
+	 */
+	initStringInfo(&str);
+	tmpcxt = AllocSetContextCreate(CurrentMemoryContext,
+								   "deparse ctx",
+								   ALLOCSET_DEFAULT_MINSIZE,
+								   ALLOCSET_DEFAULT_INITSIZE,
+								   ALLOCSET_DEFAULT_MAXSIZE);
+	oldcxt = MemoryContextSwitchTo(tmpcxt);
+
+	/*
+	 * Many routines underlying this one will invoke ruleutils.c functionality
+	 * to obtain deparsed versions of expressions.  In such results, we want
+	 * all object names to be qualified, 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);
+
+	verbose = verbose_mode;
+
+	switch (cmd->type)
 	{
 		case SCT_Simple:
 			tree = deparse_simple_command(cmd);
@@ -3550,9 +10057,27 @@ deparse_utility_command(CollectedCommand *cmd, bool verbose_mode)
 		case SCT_AlterTable:
 			tree = deparse_AlterRelation(cmd);
 			break;
+		case SCT_Grant:
+			tree = deparse_GrantStmt(cmd);
+			break;
 		case SCT_CreateTableAs:
 			tree = deparse_CreateTableAsStmt(cmd);
 			break;
+		case SCT_AlterOpFamily:
+			tree = deparse_AlterOpFamily(cmd);
+			break;
+		case SCT_CreateOpClass:
+			tree = deparse_CreateOpClassStmt(cmd);
+			break;
+		case SCT_AlterDefaultPrivileges:
+			tree = deparse_AlterDefaultPrivilegesStmt(cmd);
+			break;
+		case SCT_AlterTSConfig:
+			tree = deparse_AlterTSConfigurationStmt(cmd);
+			break;
+		case SCT_SecurityLabel:
+			tree = deparse_SecLabelStmt(cmd);
+			break;
 		default:
 			elog(ERROR, "unexpected deparse node type %d", cmd->type);
 	}
diff --git a/src/include/tcop/ddl_deparse.h b/src/include/tcop/ddl_deparse.h
index 1a2702c..e261a3e 100644
--- a/src/include/tcop/ddl_deparse.h
+++ b/src/include/tcop/ddl_deparse.h
@@ -12,11 +12,13 @@
 #ifndef DDL_DEPARSE_H
 #define DDL_DEPARSE_H
 
+#include "commands/event_trigger.h"
 #include "tcop/deparse_utility.h"
 
 extern char *deparse_utility_command(CollectedCommand *cmd, bool verbose_mode);
 extern char *deparse_ddl_json_to_string(char *jsonb);
 extern char *deparse_drop_command(const char *objidentity, const char *objecttype,
 								  DropBehavior behavior);
+extern char * deparse_AlterPublicationDropStmt(SQLDropObject *obj);
 
 #endif							/* DDL_DEPARSE_H */
-- 
1.8.3.1



  [application/octet-stream] v80-0006-Support-DDL-replication.patch (200.3K, 7-v80-0006-Support-DDL-replication.patch)
  download | inline diff:
From a4a5ea289057d69f595080c077a1ff927d0ac419 Mon Sep 17 00:00:00 2001
From: Ajin Cherian <ajinc@fast.au.fujitsu.com>
Date: Mon, 13 Mar 2023 23:55:31 -0400
Subject: [PATCH v80 6/8] Support DDL replication.

To support DDL replication, we use event trigger and DDL deparsing
facilities. During CREATE PUBLICATION we register a command end trigger that
deparses the DDL (if the DDL is annotated as ddlreplok for DDL replication in
cmdtaglist.h) as a JSON blob, and WAL logs it. The event trigger is automatically
removed at the time of DROP PUBLICATION. The WALSender decodes the WAL and sends
it downstream similar to other DML commands. The subscriber then converts JSON
back to the DDL command string and executes it. In the subscriber, we also add
the newly added rel to pg_subscription_rel so that the DML changes on the new
table can be replicated without having to manually run
"ALTER SUBSCRIPTION ... REFRESH PUBLICATION".

- For non-rewrite ALTER object command and
-     CREATE object command:
we deparse the command at ddl_command_end event trigger and WAL log the
deparsed json string. The WALSender decodes the WAL and sends it to
subscriber if the created/altered table is published. It supports most of
ALTER TABLE command except some commands(DDL related to PARTITIONED TABLE
...) that introduced recently which haven't been supported by the current
ddl_deparser, we will support that later.

- For DROP object:
The 'command start' event handler logs a ddl message with the relids of
the tables that are dropped which the output plugin (pgoutput) stores in
its internal data structure after verifying that it is for a table that is
part of the publication. Later the 'command end' event handler sends the
actual drop message. Pgoutput on receiving the command end, only sends out
the drop command only if it is for one of the relids marked for deleting.

The reason we have to do this is because, once the logical decoder
receives the 'command end' message,  the relid of the table is no longer
valid as it has been deleted as part of invalidations received for the
drop table command. It is no longer possible to verify if the table is
part of the publication list or not. To make this possible, I have added
two more elements to the ddl xlog and ddl message, (relid and cmdtype).

We could have also handled all this on the subscriber side as well, but
that would mean sending spurious ddl messages for tables that are not part
of the publication.

- For table_rewrite ALTER TABLE command:
(ALTER COLUMN TYPE, ADD COLUMN DEFAULT, SET LOGGED, SET ACCESS METHOD)

we deparse the command and WAL log the deparsed json string at
table_rewrite event trigger. The WALSender decodes the WAL and sends it to
subscriber if the altered table is published. Then, the WALSender will
convert the upcoming rewrite INSERTs to UPDATEs and send them to
subscriber so that the data between publisher and subscriber can always be
consistent. Note that the tables that publish rewrite ddl must have a
replica identity configured in order to be able to replicate the upcoming
rewrite UPDATEs.

We do this way because of two reason:
(1) The data before the rewrite ddl could already be different among
publisher and subscriber. To make sure the extra data in subscriber which
doesn't exist in publisher also get rewritten, we need to let the
subscriber execute the original rewrite ddl to rewrite all the data at
first.

(2) the data after executing rewrite ddl could be different among
publisher and subscriber(due to different functions/operators used during
rewrite), so we need to replicate the rewrite UPDATEs to keep the data
consistent.

TO IMPROVE:
This approach could be improved by letting the subscriber try to update
the extra data itself instead of doing fully rewrite ddl and use the
upcoming rewrite UPDATEs to rewrite the rest data. To achieve this, we
could modify the deparsed json string to temporarily remove the rewrite
part and add some logic in subscriber to update the extra data.
Besides, we may not need to send rewrite changes for all type of rewrite
ddl, for example, it seems fine to skip sending rewrite changes for ALTER
TABLE SET LOGGED as the data in the table doesn't actually be changed. We
could use the deparser and event trigger to filter these ddls and skip
sending rewrite changes for them.
---
 src/backend/catalog/pg_publication.c            |   2 +
 src/backend/commands/createas.c                 |  10 +
 src/backend/commands/event_trigger.c            | 310 +++++++++++++++-
 src/backend/commands/publicationcmds.c          | 251 +++++++++++--
 src/backend/commands/tablecmds.c                |  10 +-
 src/backend/parser/parse_utilcmd.c              |   1 +
 src/backend/replication/logical/Makefile        |   1 +
 src/backend/replication/logical/ddltrigger.c    | 365 +++++++++++++++++++
 src/backend/replication/logical/logical.c       |  49 +++
 src/backend/replication/logical/meson.build     |   1 +
 src/backend/replication/logical/proto.c         |  43 +++
 src/backend/replication/logical/reorderbuffer.c |  20 +-
 src/backend/replication/logical/worker.c        | 240 ++++++++++++
 src/backend/replication/pgoutput/pgoutput.c     | 191 +++++++++-
 src/backend/tcop/cmdtag.c                       |  26 +-
 src/backend/tcop/utility.c                      |   9 +-
 src/backend/utils/cache/evtcache.c              |   2 +
 src/backend/utils/cache/relcache.c              |   2 +
 src/bin/pg_dump/pg_dump.c                       |  90 ++++-
 src/bin/pg_dump/pg_dump.h                       |   2 +
 src/bin/pg_dump/t/002_pg_dump.pl                |   2 +-
 src/bin/psql/describe.c                         |  44 ++-
 src/include/catalog/pg_proc.dat                 |  12 +
 src/include/catalog/pg_publication.h            |  17 +
 src/include/commands/event_trigger.h            |  14 +-
 src/include/replication/logicalproto.h          |   4 +
 src/include/replication/output_plugin.h         |  15 +-
 src/include/replication/pgoutput.h              |   1 +
 src/include/replication/reorderbuffer.h         |  12 +
 src/include/tcop/cmdtag.h                       |   4 +-
 src/include/tcop/cmdtaglist.h                   | 386 ++++++++++----------
 src/include/tcop/deparse_utility.h              |   1 +
 src/include/utils/evtcache.h                    |   3 +-
 src/test/regress/expected/psql.out              |   6 +-
 src/test/regress/expected/publication.out       | 420 ++++++++++-----------
 src/test/subscription/t/032_ddl_replication.pl  | 465 ++++++++++++++++++++++++
 src/tools/pgindent/typedefs.list                |   6 +
 37 files changed, 2550 insertions(+), 487 deletions(-)
 create mode 100644 src/backend/replication/logical/ddltrigger.c
 create mode 100644 src/test/subscription/t/032_ddl_replication.pl

diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index a98fcad..c505f24 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -1005,6 +1005,8 @@ GetPublication(Oid pubid)
 	pub->pubactions.pubupdate = pubform->pubupdate;
 	pub->pubactions.pubdelete = pubform->pubdelete;
 	pub->pubactions.pubtruncate = pubform->pubtruncate;
+	pub->pubactions.pubddl_all = pubform->pubddl_all;
+	pub->pubactions.pubddl_table = pubform->pubddl_table;
 	pub->pubviaroot = pubform->pubviaroot;
 
 	ReleaseSysCache(tup);
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index d6c6d51..77dcb9c9 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/event_trigger.c b/src/backend/commands/event_trigger.c
index 1928e59..b3f6849 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -36,9 +36,13 @@
 #include "lib/ilist.h"
 #include "miscadmin.h"
 #include "parser/parse_func.h"
+#include "parser/parser.h"
 #include "pgstat.h"
+#include "replication/ddlmessage.h"
+#include "replication/message.h"
 #include "tcop/deparse_utility.h"
 #include "tcop/utility.h"
+#include "tcop/ddl_deparse.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/evtcache.h"
@@ -92,7 +96,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\"",
@@ -118,7 +123,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
@@ -522,6 +528,7 @@ EventTriggerCommonSetup(Node *parsetree,
 	List	   *cachelist;
 	ListCell   *lc;
 	List	   *runlist = NIL;
+	int			pub_deparse_func_cnt = 0;
 
 	/*
 	 * We want the list of command tags for which this procedure is actually
@@ -544,7 +551,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));
@@ -571,6 +579,12 @@ EventTriggerCommonSetup(Node *parsetree,
 	 * once we do anything at all that touches the catalogs, an invalidation
 	 * might leave cachelist pointing at garbage, so we must do this before we
 	 * can do much else.
+	 *
+	 * Special handling for event triggers created as part of publications.
+	 * If there are multiple publications which publish ddls, only one set of the
+	 * event trigger functions need to be invoked. The ddl deparse event triggers
+	 * write to WAL, so no need to duplicate it as all walsenders will read the same
+	 * WAL.
 	 */
 	foreach(lc, cachelist)
 	{
@@ -578,8 +592,25 @@ EventTriggerCommonSetup(Node *parsetree,
 
 		if (filter_event_trigger(tag, item))
 		{
-			/* We must plan to fire this trigger. */
-			runlist = lappend_oid(runlist, item->fnoid);
+			static const char *trigger_func_prefix = "publication_deparse_%s";
+			char		trigger_func_name[NAMEDATALEN];
+			Oid			pub_funcoid;
+			List 		*pubfuncname;
+
+			/* Get function oid of the publication's ddl deparse event trigger */
+			snprintf(trigger_func_name, sizeof(trigger_func_name), trigger_func_prefix,
+					 eventstr);
+			pubfuncname = SystemFuncName(trigger_func_name);
+			pub_funcoid = LookupFuncName(pubfuncname, 0, NULL, true);
+
+			if (item->fnoid != pub_funcoid)
+				runlist = lappend_oid(runlist, item->fnoid);
+			else
+			{
+				/* Only the first ddl deparse event trigger needs to be invoked */
+				if (pub_deparse_func_cnt++ == 0)
+					runlist = lappend_oid(runlist, item->fnoid);
+			}
 		}
 	}
 
@@ -827,6 +858,141 @@ EventTriggerTableRewrite(Node *parsetree, Oid tableOid, int reason)
 	CommandCounterIncrement();
 }
 
+
+/*
+ * EventTriggerTableInitWriteStart
+ *     Prepare to receive data on an CREATE TABLE AS/SELET 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;
+
+	stmt =  (CreateTableAsStmt *)currentEventTriggerState->currentCommand->parsetree;
+
+	if (stmt->objtype == OBJECT_TABLE)
+	{
+		parent = currentEventTriggerState->currentCommand->parent;
+
+		pfree(currentEventTriggerState->currentCommand);
+
+		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;
+
+	/*
+	 * 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;
+
+	runlist = EventTriggerCommonSetup(command->parsetree,
+									  EVT_TableInitWrite,
+									  "table_init_write",
+									  &trigdata);
+	if (runlist == NIL)
+		return;
+
+	/* Set the real CreateTable statment and object address */
+	command->d.ctas.real_create = real_create;
+	command->d.ctas.address = address;
+
+	/* 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.
  */
@@ -1108,7 +1274,8 @@ trackDroppedObjectsNeeded(void)
 	 */
 	return (EventCacheLookup(EVT_SQLDrop) != NIL) ||
 		(EventCacheLookup(EVT_TableRewrite) != NIL) ||
-		(EventCacheLookup(EVT_DDLCommandEnd) != NIL);
+		(EventCacheLookup(EVT_DDLCommandEnd) != NIL) ||
+		(EventCacheLookup(EVT_TableInitWrite) != NIL);
 }
 
 /*
@@ -1499,6 +1666,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);
 
@@ -1532,7 +1700,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;
@@ -1552,6 +1720,83 @@ 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)
+	{
+		char	   *defexpr;
+
+		defexpr = nodeToString(def->cooked_default);
+		newsub->usingexpr = TextDatumGetCString(DirectFunctionCall2(pg_get_expr,
+																	CStringGetTextDatum(defexpr),
+																	RelationGetRelid(rel)));
+	}
+	else
+		newsub->usingexpr = NULL;
+
 	currentEventTriggerState->currentCommand->d.alterTable.subcmds =
 		lappend(currentEventTriggerState->currentCommand->d.alterTable.subcmds, newsub);
 
@@ -1559,6 +1804,57 @@ EventTriggerCollectAlterTableSubcmd(Node *subcmd, ObjectAddress address)
 }
 
 /*
+ * 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.
  *
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index f4ba572..23add32 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -38,10 +38,12 @@
 #include "commands/publicationcmds.h"
 #include "funcapi.h"
 #include "miscadmin.h"
+#include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
 #include "parser/parse_clause.h"
 #include "parser/parse_collate.h"
 #include "parser/parse_relation.h"
+#include "parser/parser.h"
 #include "storage/lmgr.h"
 #include "utils/acl.h"
 #include "utils/array.h"
@@ -82,21 +84,26 @@ static void PublicationDropSchemas(Oid pubid, List *schemas, bool missing_ok);
 static void
 parse_publication_options(ParseState *pstate,
 						  List *options,
+						  bool for_all_tables,
 						  bool *publish_given,
 						  PublicationActions *pubactions,
 						  bool *publish_via_partition_root_given,
-						  bool *publish_via_partition_root)
+						  bool *publish_via_partition_root,
+						  bool *ddl_type_given)
 {
 	ListCell   *lc;
 
 	*publish_given = false;
 	*publish_via_partition_root_given = false;
+	*ddl_type_given = false;
 
 	/* defaults */
 	pubactions->pubinsert = true;
 	pubactions->pubupdate = true;
 	pubactions->pubdelete = true;
 	pubactions->pubtruncate = true;
+	pubactions->pubddl_all = false;
+	pubactions->pubddl_table = false;
 	*publish_via_partition_root = false;
 
 	/* Parse options */
@@ -123,7 +130,7 @@ parse_publication_options(ParseState *pstate,
 			pubactions->pubtruncate = false;
 
 			*publish_given = true;
-			publish = defGetString(defel);
+			publish = pstrdup(defGetString(defel));
 
 			if (!SplitIdentifierString(publish, ',', &publish_list))
 				ereport(ERROR,
@@ -158,6 +165,52 @@ parse_publication_options(ParseState *pstate,
 			*publish_via_partition_root_given = true;
 			*publish_via_partition_root = defGetBoolean(defel);
 		}
+		else if (strcmp(defel->defname, "ddl") == 0)
+		{
+			char	   *ddl_level;
+			List	   *ddl_list;
+			ListCell   *lc3;
+
+			if (*ddl_type_given)
+				errorConflictingDefElem(defel, pstate);
+
+			if (!for_all_tables)
+				ereport(ERROR,
+						(errcode(ERRCODE_SYNTAX_ERROR),
+						 errmsg("DDL replication is only supported in FOR ALL TABLES publication")));
+			/*
+			 * If ddl option was given only the explicitly listed ddl types
+			 * should be published.
+			 */
+			pubactions->pubddl_all = false;
+			pubactions->pubddl_table = false;
+
+			*ddl_type_given = true;
+			ddl_level = defGetString(defel);
+
+			if (!SplitIdentifierString(ddl_level, ',', &ddl_list))
+				ereport(ERROR,
+						(errcode(ERRCODE_SYNTAX_ERROR),
+						 errmsg("invalid list syntax for \"ddl\" option")));
+
+			/* Process the option list. */
+			foreach(lc3, ddl_list)
+			{
+				char	   *publish_opt = (char *) lfirst(lc3);
+
+				if (strcmp(publish_opt, "all") == 0)
+				{
+					pubactions->pubddl_all = true;
+					pubactions->pubddl_table = true;
+				}
+				else if (strcmp(publish_opt, "table") == 0)
+					pubactions->pubddl_table = true;
+				else
+					ereport(ERROR,
+							(errcode(ERRCODE_SYNTAX_ERROR),
+							 errmsg("unrecognized \"ddl\" value: \"%s\"", publish_opt)));
+			}
+		}
 		else
 			ereport(ERROR,
 					(errcode(ERRCODE_SYNTAX_ERROR),
@@ -600,13 +653,56 @@ check_simple_rowfilter_expr(Node *node, ParseState *pstate)
 }
 
 /*
+ * Helper function to tranform a where clause.
+ *
+ * Also check the publication row filter expression and throw an error if
+ * anything not permitted or unexpected is encountered.
+ */
+static Node *
+GetTransformWhereClauses(const char *queryString, Relation relation,
+						 Node *whereClause, bool check_expr)
+{
+	Node	   *transformedWhereClause = NULL;
+	ParseNamespaceItem *nsitem;
+	ParseState *pstate;
+
+	/*
+	 * A fresh pstate is required so that we only have "this" table in its
+	 * rangetable
+	 */
+	pstate = make_parsestate(NULL);
+	pstate->p_sourcetext = queryString;
+	nsitem = addRangeTableEntryForRelation(pstate, relation,
+										   AccessShareLock, NULL,
+										   false, false);
+	addNSItemToQuery(pstate, nsitem, false, true, true);
+
+	transformedWhereClause = transformWhereClause(pstate,
+												  copyObject(whereClause),
+												  EXPR_KIND_WHERE,
+												  "PUBLICATION WHERE");
+
+	/* Fix up collation information */
+	assign_expr_collations(pstate, transformedWhereClause);
+
+	/*
+	 * We allow only simple expressions in row filters. See
+	 * check_simple_rowfilter_expr_walker.
+	 */
+	if (check_expr)
+		check_simple_rowfilter_expr(transformedWhereClause, pstate);
+
+	free_parsestate(pstate);
+
+	return transformedWhereClause;
+}
+
+/*
  * Transform the publication WHERE expression for all the relations in the list,
  * ensuring it is coerced to boolean and necessary collation information is
  * added if required, and add a new nsitem/RTE for the associated relation to
  * the ParseState's namespace list.
  *
- * Also check the publication row filter expression and throw an error if
- * anything not permitted or unexpected is encountered.
  */
 static void
 TransformPubWhereClauses(List *tables, const char *queryString,
@@ -616,9 +712,7 @@ TransformPubWhereClauses(List *tables, const char *queryString,
 
 	foreach(lc, tables)
 	{
-		ParseNamespaceItem *nsitem;
-		Node	   *whereclause = NULL;
-		ParseState *pstate;
+
 		PublicationRelInfo *pri = (PublicationRelInfo *) lfirst(lc);
 
 		if (pri->whereClause == NULL)
@@ -638,38 +732,11 @@ TransformPubWhereClauses(List *tables, const char *queryString,
 					 errdetail("WHERE clause cannot be used for a partitioned table when %s is false.",
 							   "publish_via_partition_root")));
 
-		/*
-		 * A fresh pstate is required so that we only have "this" table in its
-		 * rangetable
-		 */
-		pstate = make_parsestate(NULL);
-		pstate->p_sourcetext = queryString;
-		nsitem = addRangeTableEntryForRelation(pstate, pri->relation,
-											   AccessShareLock, NULL,
-											   false, false);
-		addNSItemToQuery(pstate, nsitem, false, true, true);
-
-		whereclause = transformWhereClause(pstate,
-										   copyObject(pri->whereClause),
-										   EXPR_KIND_WHERE,
-										   "PUBLICATION WHERE");
-
-		/* Fix up collation information */
-		assign_expr_collations(pstate, whereclause);
-
-		/*
-		 * We allow only simple expressions in row filters. See
-		 * check_simple_rowfilter_expr_walker.
-		 */
-		check_simple_rowfilter_expr(whereclause, pstate);
-
-		free_parsestate(pstate);
-
-		pri->whereClause = whereclause;
+		pri->whereClause = GetTransformWhereClauses(queryString, pri->relation,
+													pri->whereClause, true);
 	}
 }
 
-
 /*
  * Given a list of tables that are going to be added to a publication,
  * verify that they fulfill the necessary preconditions, namely: no tables
@@ -729,6 +796,52 @@ CheckPubRelationColumnList(char *pubname, List *tables,
 }
 
 /*
+ * Create event trigger which is used for DDL replication.
+ */
+static void
+CreateDDLReplicaEventTrigger(char *eventname, CommandTag *commands,
+							 int ncommands, ObjectAddress pubaddress,
+							 Oid puboid)
+{
+	int			i;
+	List	   *tags = NIL;
+	Oid			trigger_id;
+	ObjectAddress referenced;
+	CreateEventTrigStmt *ddl_trigger;
+	char		trigger_name[NAMEDATALEN];
+	char		trigger_func_name[NAMEDATALEN];
+	static const char *trigger_func_prefix = "publication_deparse_%s";
+
+	ddl_trigger = makeNode(CreateEventTrigStmt);
+
+	snprintf(trigger_name, sizeof(trigger_name), PUB_EVENT_TRIG_PREFIX,
+			 eventname, puboid);
+	snprintf(trigger_func_name, sizeof(trigger_func_name), trigger_func_prefix,
+			 eventname);
+
+	ddl_trigger->trigname = pstrdup(trigger_name);
+	ddl_trigger->eventname = eventname;
+	ddl_trigger->funcname = SystemFuncName(trigger_func_name);
+
+	for (i = 0; i < ncommands; i++)
+	{
+		String	   *tag = makeString(pstrdup(GetCommandTagName(commands[i])));
+
+		tags = lappend(tags, tag);
+	}
+
+	ddl_trigger->whenclause = list_make1(makeDefElem("tag", (Node *) tags, -1));
+
+	trigger_id = CreateEventTrigger(ddl_trigger);
+
+	/*
+	 * Register the event triggers as internally dependent on the publication.
+	 */
+	ObjectAddressSet(referenced, EventTriggerRelationId, trigger_id);
+	recordDependencyOn(&referenced, &pubaddress, DEPENDENCY_INTERNAL);
+}
+
+/*
  * Create new publication.
  */
 ObjectAddress
@@ -741,6 +854,7 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
 	Datum		values[Natts_pg_publication];
 	HeapTuple	tup;
 	bool		publish_given;
+	bool		ddl_type_given;
 	PublicationActions pubactions;
 	bool		publish_via_partition_root_given;
 	bool		publish_via_partition_root;
@@ -781,9 +895,11 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
 
 	parse_publication_options(pstate,
 							  stmt->options,
+							  stmt->for_all_tables,
 							  &publish_given, &pubactions,
 							  &publish_via_partition_root_given,
-							  &publish_via_partition_root);
+							  &publish_via_partition_root,
+							  &ddl_type_given);
 
 	puboid = GetNewOidWithIndex(rel, PublicationObjectIndexId,
 								Anum_pg_publication_oid);
@@ -798,6 +914,10 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
 		BoolGetDatum(pubactions.pubdelete);
 	values[Anum_pg_publication_pubtruncate - 1] =
 		BoolGetDatum(pubactions.pubtruncate);
+	values[Anum_pg_publication_pubddl_all - 1] =
+		BoolGetDatum(pubactions.pubddl_all);
+	values[Anum_pg_publication_pubddl_table - 1] =
+	BoolGetDatum(pubactions.pubddl_table);
 	values[Anum_pg_publication_pubviaroot - 1] =
 		BoolGetDatum(publish_via_partition_root);
 
@@ -858,6 +978,50 @@ CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
 		}
 	}
 
+	/*
+	 * Create an event trigger to allow logging of DDL statements.
+	 *
+	 */
+	if (pubactions.pubddl_table || pubactions.pubddl_all)
+	{
+		CommandTag	start_commands[] = {CMDTAG_DROP_TABLE};
+		CommandTag	rewrite_commands[] = {CMDTAG_ALTER_TABLE};
+		CommandTag	init_commands[] = {
+			CMDTAG_CREATE_TABLE_AS,
+			CMDTAG_SELECT_INTO
+		};
+		int ncommands = 0;
+		CommandTag *end_commands = NULL;
+
+		if (pubactions.pubddl_all)
+			end_commands = GetCommandTagsForDDLRepl(&ncommands);
+		else if (pubactions.pubddl_table)
+		{
+			ncommands = 3;
+			end_commands = palloc0(ncommands * sizeof(CommandTag));
+			end_commands[0] = CMDTAG_CREATE_TABLE;
+			end_commands[1] = CMDTAG_ALTER_TABLE;
+			end_commands[2] = CMDTAG_DROP_TABLE;
+		}
+
+		/* Create the ddl_command_end event trigger */
+		CreateDDLReplicaEventTrigger(PUB_TRIG_EVENT1, end_commands,
+									 ncommands, myself, puboid);
+		pfree(end_commands);
+
+		/* Create the ddl_command_start event trigger */
+		CreateDDLReplicaEventTrigger(PUB_TRIG_EVENT2, start_commands,
+									 lengthof(start_commands), myself, puboid);
+
+		/* Create the table_rewrite event trigger */
+		CreateDDLReplicaEventTrigger(PUB_TRIG_EVENT3, rewrite_commands,
+									 lengthof(rewrite_commands), myself, puboid);
+
+		/* Create the table_init_write event trigger */
+		CreateDDLReplicaEventTrigger(PUB_TRIG_EVENT4, init_commands,
+									 lengthof(init_commands), myself, puboid);
+	}
+
 	table_close(rel, RowExclusiveLock);
 
 	InvokeObjectPostCreateHook(PublicationRelationId, puboid, 0);
@@ -882,6 +1046,7 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
 	bool		replaces[Natts_pg_publication];
 	Datum		values[Natts_pg_publication];
 	bool		publish_given;
+	bool		ddl_type_given;
 	PublicationActions pubactions;
 	bool		publish_via_partition_root_given;
 	bool		publish_via_partition_root;
@@ -890,11 +1055,15 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
 	List	   *root_relids = NIL;
 	ListCell   *lc;
 
+	pubform = (Form_pg_publication) GETSTRUCT(tup);
+
 	parse_publication_options(pstate,
 							  stmt->options,
+							  pubform->puballtables,
 							  &publish_given, &pubactions,
 							  &publish_via_partition_root_given,
-							  &publish_via_partition_root);
+							  &publish_via_partition_root,
+							  &ddl_type_given);
 
 	pubform = (Form_pg_publication) GETSTRUCT(tup);
 
@@ -996,6 +1165,12 @@ AlterPublicationOptions(ParseState *pstate, AlterPublicationStmt *stmt,
 
 		values[Anum_pg_publication_pubtruncate - 1] = BoolGetDatum(pubactions.pubtruncate);
 		replaces[Anum_pg_publication_pubtruncate - 1] = true;
+
+		values[Anum_pg_publication_pubddl_all - 1] = BoolGetDatum(pubactions.pubddl_all);
+		replaces[Anum_pg_publication_pubddl_all - 1] = true;
+
+		values[Anum_pg_publication_pubddl_table - 1] = BoolGetDatum(pubactions.pubddl_table);
+		replaces[Anum_pg_publication_pubddl_table - 1] = true;
 	}
 
 	if (publish_via_partition_root_given)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 3e2c5f7..84a038b 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -4718,6 +4718,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);
@@ -4989,6 +4992,7 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
 {
 	ObjectAddress address = InvalidObjectAddress;
 	Relation	rel = tab->rel;
+	bool		commandCollected = false;
 
 	switch (cmd->subtype)
 	{
@@ -5112,6 +5116,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 =
@@ -5284,8 +5290,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/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index f9218f4..8b53b43 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -1392,6 +1392,7 @@ expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
 		atcmd->cmds = atsubcmds;
 		atcmd->objtype = OBJECT_TABLE;
 		atcmd->missing_ok = false;
+		atcmd->table_like = true;
 		result = lcons(atcmd, result);
 	}
 
diff --git a/src/backend/replication/logical/Makefile b/src/backend/replication/logical/Makefile
index d3680e9..b79ddd8 100644
--- a/src/backend/replication/logical/Makefile
+++ b/src/backend/replication/logical/Makefile
@@ -17,6 +17,7 @@ override CPPFLAGS := -I$(srcdir) $(CPPFLAGS)
 OBJS = \
 	applyparallelworker.o \
 	ddlmessage.o \
+	ddltrigger.o \
 	decode.o \
 	launcher.o \
 	logical.o \
diff --git a/src/backend/replication/logical/ddltrigger.c b/src/backend/replication/logical/ddltrigger.c
new file mode 100644
index 0000000..d68a507
--- /dev/null
+++ b/src/backend/replication/logical/ddltrigger.c
@@ -0,0 +1,365 @@
+/*-------------------------------------------------------------------------
+ *
+ * ddltrigger.c
+ *	  Logical DDL messages.
+ *
+ * Copyright (c) 2022, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/backend/replication/logical/ddltrigger.c
+ *
+ * NOTES
+ *
+ * Deparse the ddl command and log it.
+ *
+ * ---------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/table.h"
+#include "catalog/pg_class.h"
+#include "commands/event_trigger.h"
+#include "funcapi.h"
+#include "lib/ilist.h"
+#include "replication/ddlmessage.h"
+#include "tcop/ddl_deparse.h"
+#include "utils/fmgrprotos.h"
+#include "utils/lsyscache.h"
+
+extern EventTriggerQueryState *currentEventTriggerState;
+
+/*
+ * Deparse the ddl command and log it prior to
+ * execution. Currently only used for DROP TABLE command
+ * so that catalog can be accessed before being deleted.
+ * This is to check if the table is part of the publication
+ * or not.
+ */
+Datum
+publication_deparse_ddl_command_start(PG_FUNCTION_ARGS)
+{
+	EventTriggerData *trigdata;
+	char	   *command = psprintf("Drop table command start");
+	DropStmt   *stmt;
+	ListCell   *cell1;
+
+	if (!CALLED_AS_EVENT_TRIGGER(fcinfo))
+		elog(ERROR, "not fired by event trigger manager");
+
+	trigdata = (EventTriggerData *) fcinfo->context;
+	stmt = (DropStmt *) trigdata->parsetree;
+
+	/* Extract the relid from the parse tree */
+	foreach(cell1, stmt->objects)
+	{
+		char		relpersist;
+		Node	   *object = lfirst(cell1);
+		ObjectAddress address;
+		Relation	relation = NULL;
+
+		address = get_object_address(stmt->removeType,
+									 object,
+									 &relation,
+									 AccessExclusiveLock,
+									 true);
+
+		/* Object does not exist, nothing to do */
+		if (!relation)
+			continue;
+
+		relpersist = get_rel_persistence(address.objectId);
+
+		/*
+		 * Do not generate wal log for commands whose target table is a
+		 * temporary table.
+		 *
+		 * We will generate wal logs for unlogged tables so that unlogged
+		 * tables can also be created and altered on the subscriber side. This
+		 * makes it possible to directly replay the SET LOGGED command and the
+		 * incoming rewrite message without creating a new table.
+		 */
+		if (relpersist != RELPERSISTENCE_TEMP)
+			LogLogicalDDLMessage("deparse", address.objectId, DCT_TableDropStart,
+								 command, strlen(command) + 1);
+
+		if (relation)
+			table_close(relation, NoLock);
+	}
+	return PointerGetDatum(NULL);
+}
+
+/*
+ * publication_deparse_table_rewrite
+ *
+ * Deparse the ddl table rewrite command and log it.
+ */
+Datum
+publication_deparse_table_rewrite(PG_FUNCTION_ARGS)
+{
+	char		relpersist;
+	CollectedCommand *cmd;
+	char	   *json_string;
+
+	if (!CALLED_AS_EVENT_TRIGGER(fcinfo))
+		elog(ERROR, "not fired by event trigger manager");
+
+	cmd = currentEventTriggerState->currentCommand;
+
+	Assert(cmd && cmd->d.alterTable.rewrite);
+
+	relpersist = get_rel_persistence(cmd->d.alterTable.objectId);
+
+	/*
+	 * Do not generate wal log for commands whose target table is a temporary
+	 * table.
+	 *
+	 * We will generate wal logs for unlogged tables so that unlogged tables
+	 * can also be created and altered on the subscriber side. This makes it
+	 * possible to directly replay the SET LOGGED command and the incoming
+	 * rewrite message without creating a new table.
+	 */
+	if (relpersist != RELPERSISTENCE_TEMP)
+	{
+		/* Deparse the DDL command and WAL log it to allow decoding of the same. */
+		json_string = deparse_utility_command(cmd, false);
+
+		if (json_string != NULL)
+			LogLogicalDDLMessage("deparse", cmd->d.alterTable.objectId, DCT_TableAlter,
+								 json_string, strlen(json_string) + 1);
+	}
+
+	return PointerGetDatum(NULL);
+}
+
+/*
+ * Deparse the ddl command and log it. This function
+ * is called after the execution of the command but before the
+ * transaction commits.
+ */
+Datum
+publication_deparse_ddl_command_end(PG_FUNCTION_ARGS)
+{
+	ListCell   *lc;
+	slist_iter	iter;
+	DeparsedCommandType type;
+	Oid			relid;
+	char		relkind;
+
+	if (!CALLED_AS_EVENT_TRIGGER(fcinfo))
+		elog(ERROR, "not fired by event trigger manager");
+
+	foreach(lc, currentEventTriggerState->commandList)
+	{
+		char		relpersist = RELPERSISTENCE_PERMANENT;
+		CollectedCommand *cmd = lfirst(lc);
+		char	   *json_string;
+
+		/* Rewrite DDL has been handled in table_rewrite trigger */
+		if (cmd->d.alterTable.rewrite)
+		{
+			RenameStmt *renameStmt = (RenameStmt *) cmd->parsetree;
+
+			if (renameStmt && renameStmt->relationType != OBJECT_TYPE &&
+				renameStmt->relationType != OBJECT_TABLE)
+				continue;
+		}
+
+		if (cmd->type == SCT_Simple &&
+			!OidIsValid(cmd->d.simple.address.objectId))
+			continue;
+
+		if (cmd->type == SCT_AlterTable)
+		{
+			relid = cmd->d.alterTable.objectId;
+			type = DCT_TableAlter;
+		}
+		else
+		{
+			/* Only SCT_Simple for now */
+			relid = cmd->d.simple.address.objectId;
+			type = DCT_SimpleCmd;
+		}
+
+		relkind = get_rel_relkind(relid);
+		if (relkind)
+			relpersist = get_rel_persistence(relid);
+
+		/*
+		 * Do not generate wal log for commands whose target table is a
+		 * temporary table.
+		 *
+		 * We will generate wal logs for unlogged tables so that unlogged
+		 * tables can also be created and altered on the subscriber side. This
+		 * makes it possible to directly replay the SET LOGGED command and the
+		 * incoming rewrite message without creating a new table.
+		 */
+		if (relpersist != RELPERSISTENCE_TEMP)
+		{
+			/*
+			 * Deparse the DDL command and WAL log it to allow decoding of the
+			 * same.
+			 */
+			json_string = deparse_utility_command(cmd, false);
+
+			if (json_string != NULL)
+				LogLogicalDDLMessage("deparse", relid, type, json_string,
+									 strlen(json_string) + 1);
+		}
+	}
+
+	slist_foreach(iter, &(currentEventTriggerState->SQLDropList))
+	{
+		SQLDropObject *obj;
+		DropStmt   *stmt;
+		EventTriggerData *trigdata;
+		char	   *command;
+		DeparsedCommandType cmdtype;
+		const char *tmptype;
+		ObjectClass	objclass;
+		ObjectAddress objaddr;
+
+		trigdata = (EventTriggerData *) fcinfo->context;
+		stmt = (DropStmt *) trigdata->parsetree;
+
+		obj = slist_container(SQLDropObject, next, iter.cur);
+		objaddr = obj->address;
+		objclass = getObjectClass(&objaddr);
+
+		if (strcmp(obj->objecttype, "table") == 0)
+			cmdtype = DCT_TableDropEnd;
+		else if (objclass == OCLASS_SCHEMA ||
+				 objclass == OCLASS_OPERATOR ||
+				 objclass == OCLASS_OPCLASS ||
+				 objclass == OCLASS_OPFAMILY ||
+				 objclass == OCLASS_CAST ||
+				 objclass == OCLASS_TYPE ||
+				 objclass == OCLASS_TRIGGER ||
+				 objclass == OCLASS_CONVERSION ||
+				 objclass == OCLASS_POLICY ||
+				 objclass == OCLASS_REWRITE ||
+				 objclass == OCLASS_EXTENSION ||
+				 objclass == OCLASS_FDW ||
+				 objclass == OCLASS_TSCONFIG ||
+				 objclass == OCLASS_TSDICT ||
+				 objclass == OCLASS_TSTEMPLATE ||
+				 objclass == OCLASS_TSPARSER ||
+				 objclass == OCLASS_TRANSFORM ||
+				 objclass == OCLASS_FOREIGN_SERVER ||
+				 objclass == OCLASS_COLLATION ||
+				 objclass == OCLASS_USER_MAPPING ||
+				 objclass == OCLASS_LANGUAGE ||
+				 objclass == OCLASS_STATISTIC_EXT ||
+				 objclass == OCLASS_AM ||
+				 objclass == OCLASS_PUBLICATION ||
+				 objclass == OCLASS_PUBLICATION_REL ||
+				 objclass == OCLASS_PUBLICATION_NAMESPACE ||
+				 strcmp(obj->objecttype, "foreign table") == 0 ||
+				 strcmp(obj->objecttype, "index") == 0 ||
+				 strcmp(obj->objecttype, "sequence") == 0 ||
+				 strcmp(obj->objecttype, "view") == 0 ||
+				 strcmp(obj->objecttype, "function") == 0 ||
+				 strcmp(obj->objecttype, "materialized view") == 0 ||
+				 strcmp(obj->objecttype, "procedure") == 0 ||
+				 strcmp(obj->objecttype, "routine") == 0 ||
+				 strcmp(obj->objecttype, "aggregate") == 0)
+			cmdtype = DCT_ObjectDrop;
+		else
+			continue;
+
+		/* Change foreign-data wrapper to foreign data wrapper */
+		if (strncmp(obj->objecttype, "foreign-data wrapper", 20) == 0)
+		{
+			tmptype = pstrdup("foreign data wrapper");
+			command = deparse_drop_command(obj->objidentity, tmptype,
+										   stmt->behavior);
+		}
+
+		/* Change statistics object to statistics */
+		else if (strncmp(obj->objecttype, "statistics object",
+						 strlen("statistics object")) == 0)
+		{
+			tmptype = pstrdup("statistics");
+			command = deparse_drop_command(obj->objidentity, tmptype,
+										   stmt->behavior);
+		}
+
+		/*
+		 * Object identity needs to be modified to make the drop work
+		 *
+		 * FROM: <role> on server <servername> TO  : for <role> server
+		 * <servername>
+		 *
+		 */
+		else if (strncmp(obj->objecttype, "user mapping", 12) == 0)
+		{
+			char	   *on_server;
+
+			tmptype = palloc(strlen(obj->objidentity) + 2);
+			on_server = strstr(obj->objidentity, "on server");
+
+			sprintf((char *) tmptype, "for ");
+			strncat((char *) tmptype, obj->objidentity, on_server - obj->objidentity);
+			strcat((char *) tmptype, on_server + 3);
+			command = deparse_drop_command(tmptype, obj->objecttype,
+										   stmt->behavior);
+		}
+		else if (strncmp(obj->objecttype, "publication namespace",
+						 strlen("publication namespace")) == 0 ||
+				 strncmp(obj->objecttype, "publication relation",
+						 strlen("publication relation")) == 0)
+			command = deparse_AlterPublicationDropStmt(obj);
+		else
+			command = deparse_drop_command(obj->objidentity, obj->objecttype,
+										   stmt->behavior);
+
+		if (command)
+			LogLogicalDDLMessage("deparse", obj->address.objectId, cmdtype,
+								 command, strlen(command) + 1);
+	}
+
+	return PointerGetDatum(NULL);
+}
+
+
+/*
+ * publication_deparse_table_init_write
+ *
+ * Deparse the ddl table create command and log it.
+ */
+Datum
+publication_deparse_table_init_write(PG_FUNCTION_ARGS)
+{
+	char		relpersist;
+	CollectedCommand *cmd;
+	char	   *json_string;
+
+	if (!CALLED_AS_EVENT_TRIGGER(fcinfo))
+		elog(ERROR, "not fired by event trigger manager");
+
+	cmd = currentEventTriggerState->currentCommand;
+	Assert(cmd);
+
+	relpersist = get_rel_persistence(cmd->d.simple.address.objectId);
+
+	/*
+	 * Do not generate wal log for commands whose target table is a temporary
+	 * table.
+	 *
+	 * We will generate wal logs for unlogged tables so that unlogged tables
+	 * can also be created and altered on the subscriber side. This makes it
+	 * possible to directly replay the SET LOGGED command and the incoming
+	 * rewrite message without creating a new table.
+	 */
+	if (relpersist == RELPERSISTENCE_TEMP)
+		return PointerGetDatum(NULL);
+
+	/* Deparse the DDL command and WAL log it to allow decoding of the same. */
+	json_string = deparse_utility_command(cmd, false);
+
+	if (json_string != NULL)
+		LogLogicalDDLMessage("deparse", cmd->d.simple.address.objectId, DCT_SimpleCmd,
+							 json_string, strlen(json_string) + 1);
+
+	return PointerGetDatum(NULL);
+}
diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c
index 39e6861..f56a716 100644
--- a/src/backend/replication/logical/logical.c
+++ b/src/backend/replication/logical/logical.c
@@ -95,6 +95,11 @@ static void stream_change_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn
 static void stream_message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
 									  XLogRecPtr message_lsn, bool transactional,
 									  const char *prefix, Size message_size, const char *message);
+static void stream_ddl_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
+										 XLogRecPtr message_lsn,
+										 const char *prefix,
+										 Oid relid, DeparsedCommandType cmdtype,
+										 Size message_size, const char *message);
 static void stream_truncate_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
 									   int nrelations, Relation relations[], ReorderBufferChange *change);
 
@@ -245,6 +250,7 @@ StartupDecodingContext(List *output_plugin_options,
 		(ctx->callbacks.stream_commit_cb != NULL) ||
 		(ctx->callbacks.stream_change_cb != NULL) ||
 		(ctx->callbacks.stream_message_cb != NULL) ||
+		(ctx->callbacks.stream_ddl_cb != NULL) ||
 		(ctx->callbacks.stream_truncate_cb != NULL);
 
 	/*
@@ -262,6 +268,7 @@ StartupDecodingContext(List *output_plugin_options,
 	ctx->reorder->stream_commit = stream_commit_cb_wrapper;
 	ctx->reorder->stream_change = stream_change_cb_wrapper;
 	ctx->reorder->stream_message = stream_message_cb_wrapper;
+	ctx->reorder->stream_ddl = stream_ddl_cb_wrapper;
 	ctx->reorder->stream_truncate = stream_truncate_cb_wrapper;
 
 
@@ -1593,6 +1600,48 @@ stream_message_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
 }
 
 static void
+stream_ddl_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
+							 XLogRecPtr message_lsn,
+							 const char *prefix, Oid relid, DeparsedCommandType cmdtype,
+							 Size message_size,
+							 const char *message)
+{
+	LogicalDecodingContext *ctx = cache->private_data;
+	LogicalErrorCallbackState state;
+	ErrorContextCallback errcallback;
+
+	Assert(!ctx->fast_forward);
+
+	/* We're only supposed to call this when streaming is supported. */
+	Assert(ctx->streaming);
+
+	/* this callback is optional */
+	if (ctx->callbacks.stream_ddl_cb == NULL)
+		return;
+
+	/* Push callback + info on the error context stack */
+	state.ctx = ctx;
+	state.callback_name = "stream_ddl";
+	state.report_location = message_lsn;
+	errcallback.callback = output_plugin_error_callback;
+	errcallback.arg = (void *) &state;
+	errcallback.previous = error_context_stack;
+	error_context_stack = &errcallback;
+
+	/* set output state */
+	ctx->accept_writes = true;
+	ctx->write_xid = txn != NULL ? txn->xid : InvalidTransactionId;
+	ctx->write_location = message_lsn;
+
+	/* do the actual work: call callback */
+	ctx->callbacks.stream_ddl_cb(ctx, txn, message_lsn, prefix, relid,
+										cmdtype, message_size, message);
+
+	/* Pop the error context stack */
+	error_context_stack = errcallback.previous;
+}
+
+static void
 stream_truncate_cb_wrapper(ReorderBuffer *cache, ReorderBufferTXN *txn,
 						   int nrelations, Relation relations[],
 						   ReorderBufferChange *change)
diff --git a/src/backend/replication/logical/meson.build b/src/backend/replication/logical/meson.build
index 99c608d..05e7756 100644
--- a/src/backend/replication/logical/meson.build
+++ b/src/backend/replication/logical/meson.build
@@ -3,6 +3,7 @@
 backend_sources += files(
   'applyparallelworker.c',
   'ddlmessage.c',
+  'ddltrigger.c',
   'decode.c',
   'launcher.c',
   'logical.c',
diff --git a/src/backend/replication/logical/proto.c b/src/backend/replication/logical/proto.c
index f308713..1ba3feb 100644
--- a/src/backend/replication/logical/proto.c
+++ b/src/backend/replication/logical/proto.c
@@ -664,6 +664,47 @@ logicalrep_write_message(StringInfo out, TransactionId xid, XLogRecPtr lsn,
 }
 
 /*
+ * Read DDL MESSAGE from stream
+ */
+char *
+logicalrep_read_ddl(StringInfo in, XLogRecPtr *lsn,
+						   const char **prefix,
+						   Size *sz)
+{
+	uint8 flags;
+	char *msg;
+
+	flags = pq_getmsgint(in, 1);
+	if (flags != 0)
+		elog(ERROR, "unrecognized flags %u in ddl message", flags);
+
+	*lsn = pq_getmsgint64(in);
+	*prefix = pq_getmsgstring(in);
+	*sz = pq_getmsgint(in, 4);
+	msg = (char *) pq_getmsgbytes(in, *sz);
+
+	return msg;
+}
+
+/*
+ * Write DDL MESSAGE to stream
+ */
+void
+logicalrep_write_ddl(StringInfo out, XLogRecPtr lsn,
+							const char *prefix, Size sz, const char *message)
+{
+	uint8		flags = 0;
+
+	pq_sendbyte(out, LOGICAL_REP_MSG_DDL);
+
+	pq_sendint8(out, flags);
+	pq_sendint64(out, lsn);
+	pq_sendstring(out, prefix);
+	pq_sendint32(out, sz);
+	pq_sendbytes(out, message, sz);
+}
+
+/*
  * Write relation description to the output stream.
  */
 void
@@ -1238,6 +1279,8 @@ logicalrep_message_type(LogicalRepMsgType action)
 			return "TYPE";
 		case LOGICAL_REP_MSG_MESSAGE:
 			return "MESSAGE";
+		case LOGICAL_REP_MSG_DDL:
+			return "DDL";
 		case LOGICAL_REP_MSG_BEGIN_PREPARE:
 			return "BEGIN PREPARE";
 		case LOGICAL_REP_MSG_PREPARE:
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 811739b..03a3484 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -2052,12 +2052,20 @@ static inline void
 ReorderBufferApplyDDLMessage(ReorderBuffer *rb, ReorderBufferTXN *txn,
 							 ReorderBufferChange *change, bool streaming)
 {
-	rb->ddl(rb, txn, change->lsn,
-			change->data.ddl.prefix,
-			change->data.ddl.relid,
-			change->data.ddl.cmdtype,
-			change->data.ddl.message_size,
-			change->data.ddl.message);
+	if (streaming)
+		rb->stream_ddl(rb, txn, change->lsn,
+							  change->data.ddl.prefix,
+							  change->data.ddl.relid,
+							  change->data.ddl.cmdtype,
+							  change->data.ddl.message_size,
+							  change->data.ddl.message);
+	else
+		rb->ddl(rb, txn, change->lsn,
+					   change->data.ddl.prefix,
+					   change->data.ddl.relid,
+					   change->data.ddl.cmdtype,
+					   change->data.ddl.message_size,
+					   change->data.ddl.message);
 }
 
 /*
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index c7d1734..b9b652f 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -166,6 +166,7 @@
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
 #include "optimizer/optimizer.h"
+#include "parser/analyze.h"
 #include "parser/parse_relation.h"
 #include "pgstat.h"
 #include "postmaster/bgworker.h"
@@ -191,7 +192,10 @@
 #include "storage/lmgr.h"
 #include "storage/proc.h"
 #include "storage/procarray.h"
+#include "tcop/ddl_deparse.h"
+#include "tcop/pquery.h"
 #include "tcop/tcopprot.h"
+#include "tcop/utility.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/catcache.h"
@@ -3238,6 +3242,238 @@ apply_handle_truncate(StringInfo s)
 	end_replication_step();
 }
 
+/*
+ * Special handling for CREATE TABLE AS and SELECT INTO
+ * to not populate data from the source table on the subscriber.
+ * Allow the data to be replicated through INSERTs on the publisher.
+ */
+static void
+preprocess_create_table(RawStmt *command)
+{
+	CommandTag	commandTag;
+
+	commandTag = CreateCommandTag((Node *) command);
+
+	switch (commandTag)
+	{
+		case CMDTAG_CREATE_TABLE_AS:
+		case CMDTAG_SELECT_INTO:
+			{
+				CreateTableAsStmt *castmt = (CreateTableAsStmt *) command->stmt;
+
+				if (castmt->objtype == OBJECT_TABLE)
+				{
+					/*
+					 * Force skipping data population to avoid data
+					 * inconsistency. Data should be replicated from the
+					 * publisher instead.
+					 */
+					castmt->into->skipData = true;
+				}
+			}
+			break;
+		case CMDTAG_SELECT:
+			{
+				SelectStmt *sstmt = (SelectStmt *) command->stmt;
+
+				if (sstmt->intoClause != NULL)
+				{
+					/*
+					 * Force skipping data population to avoid data
+					 * inconsistency. Data should be replicated from the
+					 * publisher instead.
+					 */
+					sstmt->intoClause->skipData = true;
+				}
+			}
+			break;
+		default:
+			break;
+	}
+}
+
+/*
+ * Handle CREATE TABLE command
+ *
+ * Call AddSubscriptionRelState for CREATE LABEL command to set the relstate to
+ * SUBREL_STATE_READY so DML changes on this new table can be replicated without
+ * having to manually run "alter subscription ... refresh publication"
+ */
+static void
+handle_create_table(RawStmt *command)
+{
+	CommandTag	commandTag;
+	RangeVar   *rv = NULL;
+	Oid			relid;
+	Oid			relnamespace = InvalidOid;
+	CreateStmt *cstmt;
+	char	   *schemaname = NULL;
+	char	   *relname = NULL;
+
+	commandTag = CreateCommandTag((Node *) command);
+	cstmt = (CreateStmt *) command->stmt;
+	rv = cstmt->relation;
+
+	if (commandTag == CMDTAG_CREATE_TABLE)
+	{
+		cstmt = (CreateStmt *) command->stmt;
+		rv = cstmt->relation;
+	}
+	else
+	{
+		return;
+	}
+
+	if (!rv)
+		return;
+
+	schemaname = rv->schemaname;
+	relname = rv->relname;
+
+	if (schemaname != NULL)
+		relnamespace = get_namespace_oid(schemaname, false);
+
+	if (relnamespace != InvalidOid)
+		relid = get_relname_relid(relname, relnamespace);
+	else
+		relid = RelnameGetRelid(relname);
+
+	if (OidIsValid(relid))
+	{
+		AddSubscriptionRelState(MySubscription->oid, relid,
+								SUBREL_STATE_READY,
+								InvalidXLogRecPtr);
+		ereport(DEBUG1,
+				(errmsg_internal("table \"%s\" added to subscription \"%s\"",
+								 relname, MySubscription->name)));
+	}
+}
+
+/*
+ * Handle DDL replication messages.
+ */
+static void
+apply_handle_ddl(StringInfo s)
+{
+	XLogRecPtr	lsn;
+	const char *prefix = NULL;
+	char	   *message = NULL;
+	char	   *ddl_command;
+	Size		sz;
+	List	   *parsetree_list;
+	ListCell   *parsetree_item;
+	DestReceiver *receiver;
+	MemoryContext oldcontext;
+	const char *save_debug_query_string = debug_query_string;
+
+	message = logicalrep_read_ddl(s, &lsn, &prefix, &sz);
+
+	/* Make sure we are in a transaction command */
+	begin_replication_step();
+
+	ddl_command = deparse_ddl_json_to_string(message);
+	debug_query_string = ddl_command;
+
+	/* DestNone for logical replication */
+	receiver = CreateDestReceiver(DestNone);
+	parsetree_list = pg_parse_query(ddl_command);
+
+	foreach(parsetree_item, parsetree_list)
+	{
+		List	   *plantree_list;
+		List	   *querytree_list;
+		RawStmt    *command = (RawStmt *) lfirst(parsetree_item);
+		CommandTag	commandTag;
+		MemoryContext per_parsetree_context = NULL;
+		Portal		portal;
+		bool		snapshot_set = false;
+
+		commandTag = CreateCommandTag((Node *) command);
+
+		/* If we got a cancel signal in parsing or prior command, quit */
+		CHECK_FOR_INTERRUPTS();
+
+		/* Remove data population from the command */
+		preprocess_create_table(command);
+
+		/*
+		 * Set up a snapshot if parse analysis/planning will need one.
+		 */
+		if (analyze_requires_snapshot(command))
+		{
+			PushActiveSnapshot(GetTransactionSnapshot());
+			snapshot_set = true;
+		}
+
+		/*
+		 * We do the work for each parsetree in a short-lived context, to
+		 * limit the memory used when there are many commands in the string.
+		 */
+		per_parsetree_context =
+			AllocSetContextCreate(CurrentMemoryContext,
+								  "execute_sql_string per-statement context",
+								  ALLOCSET_DEFAULT_SIZES);
+		oldcontext = MemoryContextSwitchTo(per_parsetree_context);
+
+		querytree_list = pg_analyze_and_rewrite_fixedparams(command,
+															ddl_command,
+															NULL, 0, NULL);
+
+		plantree_list = pg_plan_queries(querytree_list, ddl_command, 0, NULL);
+
+		/* Done with the snapshot used for parsing/planning */
+		if (snapshot_set)
+			PopActiveSnapshot();
+
+		portal = CreatePortal("logical replication", true, true);
+
+		/*
+		 * We don't have to copy anything into the portal, because everything
+		 * we are passing here is in ApplyMessageContext or the
+		 * per_parsetree_context, and so will outlive the portal anyway.
+		 */
+		PortalDefineQuery(portal,
+						  NULL,
+						  ddl_command,
+						  commandTag,
+						  plantree_list,
+						  NULL);
+
+		/*
+		 * Start the portal.  No parameters here.
+		 */
+		PortalStart(portal, NULL, 0, InvalidSnapshot);
+
+		/*
+		 * Switch back to transaction context for execution.
+		 */
+		MemoryContextSwitchTo(oldcontext);
+
+		(void) PortalRun(portal,
+						 FETCH_ALL,
+						 true,
+						 true,
+						 receiver,
+						 receiver,
+						 NULL);
+
+		PortalDrop(portal, false);
+
+		CommandCounterIncrement();
+
+		/*
+		 * Table created by DDL replication (database level) is automatically
+		 * added to the subscription here.
+		 */
+		handle_create_table(command);
+
+		/* Now we may drop the per-parsetree context, if one was created. */
+		MemoryContextDelete(per_parsetree_context);
+	}
+
+	debug_query_string = save_debug_query_string;
+	end_replication_step();
+}
 
 /*
  * Logical replication protocol message dispatcher.
@@ -3303,6 +3539,10 @@ apply_dispatch(StringInfo s)
 			 */
 			break;
 
+		case LOGICAL_REP_MSG_DDL:
+			apply_handle_ddl(s);
+			break;
+
 		case LOGICAL_REP_MSG_STREAM_START:
 			apply_handle_stream_start(s);
 			break;
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 4e61ad3..2812805 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -56,6 +56,11 @@ static void pgoutput_message(LogicalDecodingContext *ctx,
 							 ReorderBufferTXN *txn, XLogRecPtr message_lsn,
 							 bool transactional, const char *prefix,
 							 Size sz, const char *message);
+static void pgoutput_ddl(LogicalDecodingContext *ctx,
+								ReorderBufferTXN *txn, XLogRecPtr message_lsn,
+								const char *prefix, Oid relid,
+								DeparsedCommandType cmdtype,
+								Size sz, const char *message);
 static bool pgoutput_origin_filter(LogicalDecodingContext *ctx,
 								   RepOriginId origin_id);
 static void pgoutput_begin_prepare_txn(LogicalDecodingContext *ctx,
@@ -255,6 +260,7 @@ _PG_output_plugin_init(OutputPluginCallbacks *cb)
 	cb->change_cb = pgoutput_change;
 	cb->truncate_cb = pgoutput_truncate;
 	cb->message_cb = pgoutput_message;
+	cb->ddl_cb = pgoutput_ddl;
 	cb->commit_cb = pgoutput_commit_txn;
 
 	cb->begin_prepare_cb = pgoutput_begin_prepare_txn;
@@ -271,6 +277,7 @@ _PG_output_plugin_init(OutputPluginCallbacks *cb)
 	cb->stream_commit_cb = pgoutput_stream_commit;
 	cb->stream_change_cb = pgoutput_change;
 	cb->stream_message_cb = pgoutput_message;
+	cb->stream_ddl_cb = pgoutput_ddl;
 	cb->stream_truncate_cb = pgoutput_truncate;
 	/* transaction streaming - two-phase commit */
 	cb->stream_prepare_cb = pgoutput_stream_prepare_txn;
@@ -426,6 +433,7 @@ pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
 
 	/* This plugin uses binary protocol. */
 	opt->output_type = OUTPUT_PLUGIN_BINARY_OUTPUT;
+	opt->receive_rewrites = true;
 
 	/*
 	 * This is replication start and not slot initialization.
@@ -506,6 +514,7 @@ pgoutput_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt,
 
 		/* Init publication state. */
 		data->publications = NIL;
+		data->deleted_relids = NIL;
 		publications_valid = false;
 
 		/*
@@ -1412,6 +1421,20 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
 	ReorderBufferChangeType action = change->action;
 	TupleTableSlot *old_slot = NULL;
 	TupleTableSlot *new_slot = NULL;
+	bool        table_rewrite = false;
+
+	/*
+	 * For heap rewrites, we might need to replicate them if the rewritten
+	 * table publishes rewrite ddl message. So get the actual relation here
+	 * and check the pubaction later.
+	 */
+	if (relation->rd_rel->relrewrite)
+	{
+		table_rewrite = true;
+		relation = RelationIdGetRelation(relation->rd_rel->relrewrite);
+		targetrel = relation;
+	}
+
 
 	if (!is_publishable_relation(relation))
 		return;
@@ -1446,6 +1469,13 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
 			Assert(false);
 	}
 
+	/*
+	 * We don't publish table rewrite change unless we publish the rewrite ddl
+	 * message.
+	 */
+	if (table_rewrite && !relentry->pubactions.pubddl_table)
+		return;
+
 	/* Avoid leaking memory by using and resetting our own context */
 	old = MemoryContextSwitchTo(data->context);
 
@@ -1475,8 +1505,8 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
 			}
 
 			/* Check row filter */
-			if (!pgoutput_row_filter(targetrel, NULL, &new_slot, relentry,
-									 &action))
+			if (!table_rewrite &&
+				!pgoutput_row_filter(targetrel, NULL, &new_slot, relentry, &action))
 				break;
 
 			/*
@@ -1496,8 +1526,19 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
 			maybe_send_schema(ctx, change, relation, relentry);
 
 			OutputPluginPrepareWrite(ctx, true);
-			logicalrep_write_insert(ctx->out, xid, targetrel, new_slot,
-									data->binary, relentry->columns);
+
+			/*
+			 * Convert the rewrite inserts to updates so that the subscriber
+			 * can replay it. This is needed to make sure the data between
+			 * publisher and subscriber is consistent.
+			 */
+			if (table_rewrite)
+				logicalrep_write_update(ctx->out, xid, targetrel,
+										NULL, new_slot, data->binary,
+										relentry->columns);
+			else
+				logicalrep_write_insert(ctx->out, xid, targetrel, new_slot,
+										data->binary, relentry->columns);
 			OutputPluginWrite(ctx, true);
 			break;
 		case REORDER_BUFFER_CHANGE_UPDATE:
@@ -1629,6 +1670,9 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
 		ancestor = NULL;
 	}
 
+	if (table_rewrite)
+		RelationClose(relation);
+
 	/* Cleanup */
 	MemoryContextSwitchTo(old);
 	MemoryContextReset(data->context);
@@ -1744,6 +1788,138 @@ pgoutput_message(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
 }
 
 /*
+ * Send the decoded DDL over wire.
+ */
+static void
+pgoutput_ddl(LogicalDecodingContext *ctx, ReorderBufferTXN *txn,
+					XLogRecPtr message_lsn,
+					const char *prefix, Oid relid, DeparsedCommandType cmdtype,
+					Size sz, const char *message)
+{
+	PGOutputData *data = (PGOutputData *) ctx->output_plugin_private;
+	PGOutputTxnData *txndata = (PGOutputTxnData *) txn->output_plugin_private;
+	Relation	relation = NULL;
+	RelationSyncEntry *relentry;
+
+	switch (cmdtype)
+	{
+		case DCT_TableDropStart:
+
+			/*
+			 * On DROP start, add the relid to a deleted_relid list if the
+			 * relid is part of a publication that supports ddl publication.
+			 * We need this because on DROP end, the relid will no longer be
+			 * valid. Later on Drop end, verify that the drop is for a relid
+			 * that is on the deleted_rid list, and only then send the ddl
+			 * message.
+			 */
+			relation = RelationIdGetRelation(relid);
+
+			Assert(relation);
+			relentry = get_rel_sync_entry(data, relation);
+
+			if (relentry->pubactions.pubddl_table)
+				data->deleted_relids = lappend_oid(data->deleted_relids, relid);
+
+			RelationClose(relation);
+			return;
+
+		case DCT_TableDropEnd:
+			if (!list_member_oid(data->deleted_relids, relid))
+				return;
+			else
+				data->deleted_relids = list_delete_oid(data->deleted_relids, relid);
+			break;
+
+		case DCT_TableAlter:
+
+			/*
+			 * For table rewrite ddl, we first send the original ddl message
+			 * to subscriber, then convert the upcoming rewrite INSERT to
+			 * UPDATE and send them to subscriber so that the data between
+			 * publisher and subscriber can always be consistent.
+			 *
+			 * We do this way because of two reason:
+			 *
+			 * (1) The data before the rewrite ddl could already be different
+			 * among publisher and subscriber. To make sure the extra data in
+			 * subscriber which doesn't exist in publisher also get rewritten,
+			 * we need to let the subscriber execute the original rewrite ddl
+			 * to rewrite all the data at first.
+			 *
+			 * (2) the data after executing rewrite ddl could be different
+			 * among publisher and subscriber(due to different
+			 * functions/operators used during rewrite), so we need to
+			 * replicate the rewrite UPDATEs to keep the data consistent.
+			 *
+			 * TO IMPROVE: We could improve this by letting the subscriber
+			 * only rewrite the extra data instead of doing fully rewrite and
+			 * use the upcoming rewrite UPDATEs to rewrite the rest data.
+			 * Besides, we may not need to send rewrite changes for all type
+			 * of rewrite ddl, for example, it seems fine to skip sending
+			 * rewrite changes for ALTER TABLE SET LOGGED as the data in the
+			 * table doesn't actually be changed.
+			 */
+			relation = RelationIdGetRelation(relid);
+			Assert(relation);
+
+			relentry = get_rel_sync_entry(data, relation);
+
+			/*
+			 * Skip sending this ddl if we don't publish ddl message or the
+			 * ddl need to be published via its root relation.
+			 */
+			if (!relentry->pubactions.pubddl_table ||
+				relentry->publish_as_relid != relid)
+			{
+				RelationClose(relation);
+				return;
+			}
+
+			break;
+
+		case DCT_SimpleCmd:
+			relation = RelationIdGetRelation(relid);
+
+			if (relation == NULL)
+				break;
+
+			relentry = get_rel_sync_entry(data, relation);
+
+			if (!relentry->pubactions.pubddl_table)
+			{
+				RelationClose(relation);
+				return;
+			}
+
+			break;
+
+		case DCT_ObjectDrop:
+			/* do nothing */
+			break;
+
+		default:
+			elog(ERROR, "unsupported type %d", cmdtype);
+			break;
+	}
+
+	/* Send BEGIN if we haven't yet */
+	if (txndata && !txndata->sent_begin_txn)
+		pgoutput_send_begin(ctx, txn);
+
+	OutputPluginPrepareWrite(ctx, true);
+	logicalrep_write_ddl(ctx->out,
+								message_lsn,
+								prefix,
+								sz,
+								message);
+	OutputPluginWrite(ctx, true);
+
+	if (relation)
+		RelationClose(relation);
+}
+
+/*
  * Return true if the data is associated with an origin and the user has
  * requested the changes that don't have an origin, false otherwise.
  */
@@ -2051,7 +2227,8 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
 		entry->schema_sent = false;
 		entry->streamed_txns = NIL;
 		entry->pubactions.pubinsert = entry->pubactions.pubupdate =
-			entry->pubactions.pubdelete = entry->pubactions.pubtruncate = false;
+			entry->pubactions.pubdelete = entry->pubactions.pubtruncate =
+			entry->pubactions.pubddl_all = entry->pubactions.pubddl_table = false;
 		entry->new_slot = NULL;
 		entry->old_slot = NULL;
 		memset(entry->exprstate, 0, sizeof(entry->exprstate));
@@ -2109,6 +2286,8 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
 		entry->pubactions.pubupdate = false;
 		entry->pubactions.pubdelete = false;
 		entry->pubactions.pubtruncate = false;
+		entry->pubactions.pubddl_all = false;
+		entry->pubactions.pubddl_table = false;
 
 		/*
 		 * Tuple slots cleanups. (Will be rebuilt later if needed).
@@ -2222,6 +2401,8 @@ get_rel_sync_entry(PGOutputData *data, Relation relation)
 				entry->pubactions.pubupdate |= pub->pubactions.pubupdate;
 				entry->pubactions.pubdelete |= pub->pubactions.pubdelete;
 				entry->pubactions.pubtruncate |= pub->pubactions.pubtruncate;
+				entry->pubactions.pubddl_all |= pub->pubactions.pubddl_all;
+				entry->pubactions.pubddl_table |= pub->pubactions.pubddl_table;
 
 				/*
 				 * We want to publish the changes as the top-most ancestor
diff --git a/src/backend/tcop/cmdtag.c b/src/backend/tcop/cmdtag.c
index 4bd713a..ce09c5f 100644
--- a/src/backend/tcop/cmdtag.c
+++ b/src/backend/tcop/cmdtag.c
@@ -26,10 +26,11 @@ typedef struct CommandTagBehavior
 	const bool	table_rewrite_ok;
 	const bool	display_rowcount;	/* should the number of rows affected be
 									 * shown in the command completion string */
+	const bool	ddl_replication_ok;
 } CommandTagBehavior;
 
-#define PG_CMDTAG(tag, name, evtrgok, rwrok, rowcnt) \
-	{ name, (uint8) (sizeof(name) - 1), evtrgok, rwrok, rowcnt },
+#define PG_CMDTAG(tag, name, evtrgok, rwrok, rowcnt, ddlreplok) \
+	{ name, (uint8) (sizeof(name) - 1), evtrgok, rwrok, rowcnt, ddlreplok },
 
 static const CommandTagBehavior tag_behavior[COMMAND_TAG_NEXTTAG] = {
 #include "tcop/cmdtaglist.h"
@@ -57,6 +58,21 @@ GetCommandTagNameAndLen(CommandTag commandTag, Size *len)
 	return tag_behavior[commandTag].name;
 }
 
+CommandTag *
+GetCommandTagsForDDLRepl(int *ncommands)
+{
+	CommandTag *ddlrepl_commands = palloc0(COMMAND_TAG_NEXTTAG * sizeof(CommandTag));
+	*ncommands = 0;
+
+	for(int i = 0; i < COMMAND_TAG_NEXTTAG; i++)
+	{
+		if (tag_behavior[i].ddl_replication_ok)
+			ddlrepl_commands[(*ncommands)++] = (CommandTag) i;
+	}
+
+	return ddlrepl_commands;
+}
+
 bool
 command_tag_display_rowcount(CommandTag commandTag)
 {
@@ -75,6 +91,12 @@ command_tag_table_rewrite_ok(CommandTag commandTag)
 	return tag_behavior[commandTag].table_rewrite_ok;
 }
 
+bool
+command_tag_ddl_replication_ok(CommandTag commandTag)
+{
+	return tag_behavior[commandTag].ddl_replication_ok;
+}
+
 /*
  * Search CommandTag by name
  *
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 6fd3d47..a7e0dce 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1666,8 +1666,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:
@@ -2253,6 +2256,8 @@ stringify_objtype(ObjectType objtype, bool isgrant)
 			return "POLICY";
 		case OBJECT_PROCEDURE:
 			return "PROCEDURE";
+		case OBJECT_PUBLICATION:
+			return "PUBLICATION";
 		case OBJECT_ROLE:
 			return "ROLE";
 		case OBJECT_ROUTINE:
@@ -2265,6 +2270,8 @@ stringify_objtype(ObjectType objtype, bool isgrant)
 			return "SEQUENCE";
 		case OBJECT_STATISTIC_EXT:
 			return "STATISTICS";
+		case OBJECT_SUBSCRIPTION:
+			return "SUBSCRIPTION";
 		case OBJECT_TABLE:
 			return "TABLE";
 		case OBJECT_TABLESPACE:
@@ -2293,10 +2300,8 @@ stringify_objtype(ObjectType objtype, bool isgrant)
 		case OBJECT_DEFACL:
 		case OBJECT_DOMCONSTRAINT:
 		case OBJECT_PARAMETER_ACL:
-		case OBJECT_PUBLICATION:
 		case OBJECT_PUBLICATION_NAMESPACE:
 		case OBJECT_PUBLICATION_REL:
-		case OBJECT_SUBSCRIPTION:
 		case OBJECT_TABCONSTRAINT:
 		case OBJECT_TRANSFORM:
 			elog(ERROR, "unsupported object type %d", objtype);
diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c
index 1f5e7eb..f2a9f5d 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/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 13f7987..cf76d38 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -5690,6 +5690,8 @@ RelationBuildPublicationDesc(Relation relation, PublicationDesc *pubdesc)
 		pubdesc->pubactions.pubupdate |= pubform->pubupdate;
 		pubdesc->pubactions.pubdelete |= pubform->pubdelete;
 		pubdesc->pubactions.pubtruncate |= pubform->pubtruncate;
+		pubdesc->pubactions.pubddl_all |= pubform->pubddl_all;
+		pubdesc->pubactions.pubddl_table |= pubform->pubddl_table;
 
 		/*
 		 * Check if all columns referenced in the filter expression are part
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 4217908..7ca878b 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -51,6 +51,7 @@
 #include "catalog/pg_largeobject_d.h"
 #include "catalog/pg_largeobject_metadata_d.h"
 #include "catalog/pg_proc_d.h"
+#include "catalog/pg_publication.h"
 #include "catalog/pg_subscription.h"
 #include "catalog/pg_trigger_d.h"
 #include "catalog/pg_type_d.h"
@@ -3964,6 +3965,8 @@ getPublications(Archive *fout, int *numPublications)
 	int			i_pubupdate;
 	int			i_pubdelete;
 	int			i_pubtruncate;
+	int			i_pubddl_all;
+	int			i_pubddl_table;
 	int			i_pubviaroot;
 	int			i,
 				ntups;
@@ -3979,23 +3982,23 @@ getPublications(Archive *fout, int *numPublications)
 	resetPQExpBuffer(query);
 
 	/* Get the publications. */
-	if (fout->remoteVersion >= 130000)
+	if (fout->remoteVersion >= 160000)
 		appendPQExpBufferStr(query,
 							 "SELECT p.tableoid, p.oid, p.pubname, "
 							 "p.pubowner, "
-							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, p.pubviaroot "
+							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, p.pubddl_all, p.pubddl_table, p.pubviaroot "
 							 "FROM pg_publication p");
 	else if (fout->remoteVersion >= 110000)
 		appendPQExpBufferStr(query,
 							 "SELECT p.tableoid, p.oid, p.pubname, "
 							 "p.pubowner, "
-							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false AS pubviaroot "
+							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false as p.pubddl_all, false as p.pubddl_table, false AS pubviaroot "
 							 "FROM pg_publication p");
 	else
 		appendPQExpBufferStr(query,
 							 "SELECT p.tableoid, p.oid, p.pubname, "
 							 "p.pubowner, "
-							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, false AS pubtruncate, false AS pubviaroot "
+							 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, false AS pubtruncate, false as p.pubddl_all, false as p.pubddl_table, false AS pubviaroot "
 							 "FROM pg_publication p");
 
 	res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -4011,6 +4014,8 @@ getPublications(Archive *fout, int *numPublications)
 	i_pubupdate = PQfnumber(res, "pubupdate");
 	i_pubdelete = PQfnumber(res, "pubdelete");
 	i_pubtruncate = PQfnumber(res, "pubtruncate");
+	i_pubddl_all = PQfnumber(res, "pubddl_all");
+	i_pubddl_table = PQfnumber(res, "pubddl_table");
 	i_pubviaroot = PQfnumber(res, "pubviaroot");
 
 	pubinfo = pg_malloc(ntups * sizeof(PublicationInfo));
@@ -4034,6 +4039,10 @@ getPublications(Archive *fout, int *numPublications)
 			(strcmp(PQgetvalue(res, i, i_pubdelete), "t") == 0);
 		pubinfo[i].pubtruncate =
 			(strcmp(PQgetvalue(res, i, i_pubtruncate), "t") == 0);
+		pubinfo[i].pubddl_all =
+			(strcmp(PQgetvalue(res, i, i_pubddl_all), "t") == 0);
+		pubinfo[i].pubddl_table =
+			(strcmp(PQgetvalue(res, i, i_pubddl_table), "t") == 0);
 		pubinfo[i].pubviaroot =
 			(strcmp(PQgetvalue(res, i, i_pubviaroot), "t") == 0);
 
@@ -4113,7 +4122,24 @@ dumpPublication(Archive *fout, const PublicationInfo *pubinfo)
 		first = false;
 	}
 
-	appendPQExpBufferChar(query, '\'');
+	appendPQExpBufferStr(query, "'");
+
+	if (pubinfo->pubddl_all || pubinfo->pubddl_table)
+	{
+		appendPQExpBufferStr(query, ", ddl = '");
+		if (pubinfo->pubddl_all)
+			appendPQExpBufferStr(query, "all");
+
+		if (pubinfo->pubddl_table)
+		{
+			if (pubinfo->pubddl_all)
+				appendPQExpBufferStr(query, ", ");
+
+			appendPQExpBufferStr(query, "table");
+		}
+
+		appendPQExpBufferStr(query, "'");
+	}
 
 	if (pubinfo->pubviaroot)
 		appendPQExpBufferStr(query, ", publish_via_partition_root = true");
@@ -7796,6 +7822,50 @@ getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
 }
 
 /*
+ * getPublicationEventTriggers
+ *	  get the publication event triggers that should be skipped
+ */
+static void
+getPublicationEventTriggers(Archive *fout, SimpleStringList *skipTriggers)
+{
+	PQExpBuffer query;
+	PGresult   *res;
+	int			i;
+	int			ntups;
+
+	query = createPQExpBuffer();
+
+	appendPQExpBufferStr(query,
+						 "SELECT oid FROM pg_publication "
+						 "WHERE pubddl_all OR pubddl_table");
+
+	res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+	ntups = PQntuples(res);
+
+	for (i = 0; i < ntups; i++)
+	{
+		char *trigname;
+		Oid pubid = atooid(PQgetvalue(res, 0, 0));
+
+		trigname = psprintf(PUB_EVENT_TRIG_PREFIX, PUB_TRIG_EVENT1, pubid);
+		simple_string_list_append(skipTriggers, trigname);
+
+		trigname = psprintf(PUB_EVENT_TRIG_PREFIX, PUB_TRIG_EVENT2, pubid);
+		simple_string_list_append(skipTriggers, trigname);
+
+		trigname = psprintf(PUB_EVENT_TRIG_PREFIX, PUB_TRIG_EVENT3, pubid);
+		simple_string_list_append(skipTriggers, trigname);
+
+		trigname = psprintf(PUB_EVENT_TRIG_PREFIX, PUB_TRIG_EVENT4, pubid);
+		simple_string_list_append(skipTriggers, trigname);
+	}
+
+	PQclear(res);
+
+	destroyPQExpBuffer(query);
+}
+
+/*
  * getEventTriggers
  *	  get information about event triggers
  */
@@ -7815,6 +7885,7 @@ getEventTriggers(Archive *fout, int *numEventTriggers)
 				i_evtfname,
 				i_evtenabled;
 	int			ntups;
+	SimpleStringList skipTriggers = {NULL, NULL};
 
 	/* Before 9.3, there are no event triggers */
 	if (fout->remoteVersion < 90300)
@@ -7823,6 +7894,8 @@ getEventTriggers(Archive *fout, int *numEventTriggers)
 		return NULL;
 	}
 
+	getPublicationEventTriggers(fout, &skipTriggers);
+
 	query = createPQExpBuffer();
 
 	appendPQExpBufferStr(query,
@@ -7867,9 +7940,14 @@ getEventTriggers(Archive *fout, int *numEventTriggers)
 		evtinfo[i].evtenabled = *(PQgetvalue(res, i, i_evtenabled));
 
 		/* Decide whether we want to dump it */
-		selectDumpableObject(&(evtinfo[i].dobj), fout);
+		if (simple_string_list_member(&skipTriggers, evtinfo[i].evtname))
+			evtinfo[i].dobj.dump= DUMP_COMPONENT_NONE;
+		else
+			selectDumpableObject(&(evtinfo[i].dobj), fout);
 	}
 
+	simple_string_list_destroy(&skipTriggers);
+
 	PQclear(res);
 
 	destroyPQExpBuffer(query);
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index cdca0b9..3ea30ce 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -618,6 +618,8 @@ typedef struct _PublicationInfo
 	bool		pubupdate;
 	bool		pubdelete;
 	bool		pubtruncate;
+	bool		pubddl_all;
+	bool		pubddl_table;
 	bool		pubviaroot;
 } PublicationInfo;
 
diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl
index 9c35421..810f643 100644
--- a/src/bin/pg_dump/t/002_pg_dump.pl
+++ b/src/bin/pg_dump/t/002_pg_dump.pl
@@ -2567,7 +2567,7 @@ my %tests = (
 		create_order => 50,
 		create_sql   => 'CREATE PUBLICATION pub2
 						 FOR ALL TABLES
-						 WITH (publish = \'\');',
+						 WITH (publish = \'\', ddl = \'\');',
 		regexp => qr/^
 			\QCREATE PUBLICATION pub2 FOR ALL TABLES WITH (publish = '');\E
 			/xm,
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 99e28f6..48bf37a 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -6183,7 +6183,7 @@ listPublications(const char *pattern)
 	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
-	static const bool translate_columns[] = {false, false, false, false, false, false, false, false};
+	static const bool translate_columns[] = {false, false, false, false, false, false, false, false, false, false};
 
 	if (pset.sversion < 100000)
 	{
@@ -6200,13 +6200,23 @@ listPublications(const char *pattern)
 	printfPQExpBuffer(&buf,
 					  "SELECT pubname AS \"%s\",\n"
 					  "  pg_catalog.pg_get_userbyid(pubowner) AS \"%s\",\n"
-					  "  puballtables AS \"%s\",\n"
-					  "  pubinsert AS \"%s\",\n"
-					  "  pubupdate AS \"%s\",\n"
-					  "  pubdelete AS \"%s\"",
+					  "  puballtables AS \"%s\"",
 					  gettext_noop("Name"),
 					  gettext_noop("Owner"),
-					  gettext_noop("All tables"),
+					  gettext_noop("All tables"));
+	if (pset.sversion >= 160000)
+	{
+		appendPQExpBuffer(&buf,
+						  ",\n  pubddl_all AS \"%s\"",
+						  gettext_noop("All DDLs"));
+		appendPQExpBuffer(&buf,
+						  ",\n  pubddl_table AS \"%s\"",
+						  gettext_noop("Table DDLs"));
+	}
+	appendPQExpBuffer(&buf,
+					  ",\n  pubinsert AS \"%s\",\n"
+					  "  pubupdate AS \"%s\",\n"
+					  "  pubdelete AS \"%s\"",
 					  gettext_noop("Inserts"),
 					  gettext_noop("Updates"),
 					  gettext_noop("Deletes"));
@@ -6218,7 +6228,6 @@ listPublications(const char *pattern)
 		appendPQExpBuffer(&buf,
 						  ",\n  pubviaroot AS \"%s\"",
 						  gettext_noop("Via root"));
-
 	appendPQExpBufferStr(&buf,
 						 "\nFROM pg_catalog.pg_publication\n");
 
@@ -6308,6 +6317,7 @@ describePublications(const char *pattern)
 	PGresult   *res;
 	bool		has_pubtruncate;
 	bool		has_pubviaroot;
+	bool		has_pubddl;
 
 	PQExpBufferData title;
 	printTableContent cont;
@@ -6324,13 +6334,19 @@ describePublications(const char *pattern)
 
 	has_pubtruncate = (pset.sversion >= 110000);
 	has_pubviaroot = (pset.sversion >= 130000);
+	has_pubddl =  (pset.sversion >= 160000);
 
 	initPQExpBuffer(&buf);
 
 	printfPQExpBuffer(&buf,
 					  "SELECT oid, pubname,\n"
 					  "  pg_catalog.pg_get_userbyid(pubowner) AS owner,\n"
-					  "  puballtables, pubinsert, pubupdate, pubdelete");
+					  "  puballtables");
+	if (has_pubddl)
+		appendPQExpBufferStr(&buf,
+							 ", pubddl_all, pubddl_table");
+	appendPQExpBufferStr(&buf,
+						 ",  pubinsert, pubupdate, pubdelete");
 	if (has_pubtruncate)
 		appendPQExpBufferStr(&buf,
 							 ", pubtruncate");
@@ -6388,6 +6404,8 @@ describePublications(const char *pattern)
 			ncols++;
 		if (has_pubviaroot)
 			ncols++;
+		if (has_pubddl)
+			ncols += 2;
 
 		initPQExpBuffer(&title);
 		printfPQExpBuffer(&title, _("Publication %s"), pubname);
@@ -6395,6 +6413,11 @@ describePublications(const char *pattern)
 
 		printTableAddHeader(&cont, gettext_noop("Owner"), true, align);
 		printTableAddHeader(&cont, gettext_noop("All tables"), true, align);
+		if (has_pubddl)
+		{
+			printTableAddHeader(&cont, gettext_noop("All DDLs"), true, align);
+			printTableAddHeader(&cont, gettext_noop("Table DDLs"), true, align);
+		}
 		printTableAddHeader(&cont, gettext_noop("Inserts"), true, align);
 		printTableAddHeader(&cont, gettext_noop("Updates"), true, align);
 		printTableAddHeader(&cont, gettext_noop("Deletes"), true, align);
@@ -6412,6 +6435,11 @@ describePublications(const char *pattern)
 			printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false);
 		if (has_pubviaroot)
 			printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
+		if (has_pubddl)
+		{
+			printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
+			printTableAddCell(&cont, PQgetvalue(res, i, 10), false, false);
+		}
 
 		if (!puballtables)
 		{
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 5cd263e..b6276d1 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -11953,5 +11953,17 @@
 { oid => '4643', descr => 'expand JSON format DDL to a plain text DDL command',
   proname => 'ddl_deparse_expand_command', prorettype => 'text',
   proargtypes => 'text', prosrc => 'ddl_deparse_expand_command' },
+{ oid => '4644', descr => 'trigger for ddl command deparse end',
+  proname => 'publication_deparse_ddl_command_end', prorettype => 'event_trigger',
+  proargtypes => '', prosrc => 'publication_deparse_ddl_command_end' },
+{ oid => '4645', descr => 'trigger for ddl command deparse start',
+  proname => 'publication_deparse_ddl_command_start', prorettype => 'event_trigger',
+  proargtypes => '', prosrc => 'publication_deparse_ddl_command_start' },
+{ oid => '4646', descr => 'trigger for ddl command deparse table rewrite',
+  proname => 'publication_deparse_table_rewrite', prorettype => 'event_trigger',
+  proargtypes => '', prosrc => 'publication_deparse_table_rewrite' },
+{ oid => '4647', descr => 'trigger for ddl command deparse table init',
+  proname => 'publication_deparse_table_init_write', prorettype => 'event_trigger',
+  proargtypes => '', prosrc => 'publication_deparse_table_init_write' },
 
 ]
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index 715f2a2..1cf02a4 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -21,6 +21,15 @@
 #include "catalog/pg_publication_d.h"
 #include "nodes/pg_list.h"
 
+/* Publication trigger events */
+#define PUB_TRIG_EVENT1 "ddl_command_end"
+#define PUB_TRIG_EVENT2 "ddl_command_start"
+#define PUB_TRIG_EVENT3 "table_rewrite"
+#define PUB_TRIG_EVENT4 "table_init_write"
+
+/* Publication event trigger prefix */
+#define PUB_EVENT_TRIG_PREFIX "pg_deparse_trig_%s_%u"
+
 /* ----------------
  *		pg_publication definition.  cpp turns this into
  *		typedef struct FormData_pg_publication
@@ -54,6 +63,12 @@ CATALOG(pg_publication,6104,PublicationRelationId)
 
 	/* true if partition changes are published using root schema */
 	bool		pubviaroot;
+
+	/* true if all supported ddls are published */
+	bool		pubddl_all;
+
+	/* true if table ddls are published */
+	bool		pubddl_table;
 } FormData_pg_publication;
 
 /* ----------------
@@ -72,6 +87,8 @@ typedef struct PublicationActions
 	bool		pubupdate;
 	bool		pubdelete;
 	bool		pubtruncate;
+	bool		pubddl_all;
+	bool		pubddl_table;
 } PublicationActions;
 
 typedef struct PublicationDesc
diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h
index a97e8b7..5f6dd22 100644
--- a/src/include/commands/event_trigger.h
+++ b/src/include/commands/event_trigger.h
@@ -94,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);
@@ -110,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);
@@ -120,6 +129,9 @@ extern void EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt,
 extern void EventTriggerCollectCreateOpClass(CreateOpClassStmt *stmt,
 											 Oid opcoid, List *operators,
 											 List *procedures);
+extern void EventTriggerCollectCreatePublication(CreatePublicationStmt *stmt,
+												 Oid pubid, List *relations,
+												 List *schemas);
 extern void EventTriggerCollectAlterTSConfig(AlterTSConfigurationStmt *stmt,
 											 Oid cfgId, Oid *dictIds, int ndicts);
 extern void EventTriggerCollectAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt);
diff --git a/src/include/replication/logicalproto.h b/src/include/replication/logicalproto.h
index 0ea2df5..5fb3baa 100644
--- a/src/include/replication/logicalproto.h
+++ b/src/include/replication/logicalproto.h
@@ -66,6 +66,7 @@ typedef enum LogicalRepMsgType
 	LOGICAL_REP_MSG_RELATION = 'R',
 	LOGICAL_REP_MSG_TYPE = 'Y',
 	LOGICAL_REP_MSG_MESSAGE = 'M',
+	LOGICAL_REP_MSG_DDL = 'L',
 	LOGICAL_REP_MSG_BEGIN_PREPARE = 'b',
 	LOGICAL_REP_MSG_PREPARE = 'P',
 	LOGICAL_REP_MSG_COMMIT_PREPARED = 'K',
@@ -246,6 +247,9 @@ extern List *logicalrep_read_truncate(StringInfo in,
 									  bool *cascade, bool *restart_seqs);
 extern void logicalrep_write_message(StringInfo out, TransactionId xid, XLogRecPtr lsn,
 									 bool transactional, const char *prefix, Size sz, const char *message);
+extern void logicalrep_write_ddl(StringInfo out, XLogRecPtr lsn,
+										const char *prefix, Size sz, const char *message);
+extern char *logicalrep_read_ddl(StringInfo in, XLogRecPtr *lsn, const char **prefix, Size *sz);
 extern void logicalrep_write_rel(StringInfo out, TransactionId xid,
 								 Relation rel, Bitmapset *columns);
 extern LogicalRepRelation *logicalrep_read_rel(StringInfo in);
diff --git a/src/include/replication/output_plugin.h b/src/include/replication/output_plugin.h
index 5ed5e6a..44baf40 100644
--- a/src/include/replication/output_plugin.h
+++ b/src/include/replication/output_plugin.h
@@ -9,7 +9,6 @@
 #ifndef OUTPUT_PLUGIN_H
 #define OUTPUT_PLUGIN_H
 
-#include "replication/ddlmessage.h"
 #include "replication/reorderbuffer.h"
 
 struct LogicalDecodingContext;
@@ -215,6 +214,19 @@ typedef void (*LogicalDecodeStreamMessageCB) (struct LogicalDecodingContext *ctx
 											  const char *message);
 
 /*
+ * Callback for streaming logical decoding DDL messages from in-progress
+ * transactions.
+ */
+typedef void (*LogicalDecodeStreamDDLMessageCB) (struct LogicalDecodingContext *ctx,
+												 ReorderBufferTXN *txn,
+												 XLogRecPtr message_lsn,
+												 const char *prefix,
+												 Oid relid,
+												 DeparsedCommandType cmdtype,
+												 Size message_size,
+												 const char *message);
+
+/*
  * Callback for streaming truncates from in-progress transactions.
  */
 typedef void (*LogicalDecodeStreamTruncateCB) (struct LogicalDecodingContext *ctx,
@@ -253,6 +265,7 @@ typedef struct OutputPluginCallbacks
 	LogicalDecodeStreamCommitCB stream_commit_cb;
 	LogicalDecodeStreamChangeCB stream_change_cb;
 	LogicalDecodeStreamMessageCB stream_message_cb;
+	LogicalDecodeStreamDDLMessageCB stream_ddl_cb;
 	LogicalDecodeStreamTruncateCB stream_truncate_cb;
 } OutputPluginCallbacks;
 
diff --git a/src/include/replication/pgoutput.h b/src/include/replication/pgoutput.h
index b4a8015..a2cf99b 100644
--- a/src/include/replication/pgoutput.h
+++ b/src/include/replication/pgoutput.h
@@ -25,6 +25,7 @@ typedef struct PGOutputData
 	uint32		protocol_version;
 	List	   *publication_names;
 	List	   *publications;
+	List	   *deleted_relids;
 	bool		binary;
 	char		streaming;
 	bool		messages;
diff --git a/src/include/replication/reorderbuffer.h b/src/include/replication/reorderbuffer.h
index e92b816..b0fade7 100644
--- a/src/include/replication/reorderbuffer.h
+++ b/src/include/replication/reorderbuffer.h
@@ -541,6 +541,17 @@ typedef void (*ReorderBufferStreamMessageCB) (
 											  const char *prefix, Size sz,
 											  const char *message);
 
+/* stream DDL message callback signature */
+typedef void (*ReorderBufferStreamDDLMessageCB) (
+												 ReorderBuffer *rb,
+												 ReorderBufferTXN *txn,
+												 XLogRecPtr message_lsn,
+												 const char *prefix,
+												 Oid relid,
+												 DeparsedCommandType cmdtype,
+												 Size sz,
+												 const char *message);
+
 /* stream truncate callback signature */
 typedef void (*ReorderBufferStreamTruncateCB) (
 											   ReorderBuffer *rb,
@@ -617,6 +628,7 @@ struct ReorderBuffer
 	ReorderBufferStreamCommitCB stream_commit;
 	ReorderBufferStreamChangeCB stream_change;
 	ReorderBufferStreamMessageCB stream_message;
+	ReorderBufferStreamDDLMessageCB stream_ddl;
 	ReorderBufferStreamTruncateCB stream_truncate;
 
 	/*
diff --git a/src/include/tcop/cmdtag.h b/src/include/tcop/cmdtag.h
index 1e7514d..076c27e 100644
--- a/src/include/tcop/cmdtag.h
+++ b/src/include/tcop/cmdtag.h
@@ -16,7 +16,7 @@
 /* buffer size required for command completion tags */
 #define COMPLETION_TAG_BUFSIZE	64
 
-#define PG_CMDTAG(tag, name, evtrgok, rwrok, rowcnt) \
+#define PG_CMDTAG(tag, name, evtrgok, rwrok, rowcnt, ddlreplok) \
 	tag,
 
 typedef enum CommandTag
@@ -53,9 +53,11 @@ CopyQueryCompletion(QueryCompletion *dst, const QueryCompletion *src)
 extern void InitializeQueryCompletion(QueryCompletion *qc);
 extern const char *GetCommandTagName(CommandTag commandTag);
 extern const char *GetCommandTagNameAndLen(CommandTag commandTag, Size *len);
+extern CommandTag *GetCommandTagsForDDLRepl(int *ncommands);
 extern bool command_tag_display_rowcount(CommandTag commandTag);
 extern bool command_tag_event_trigger_ok(CommandTag commandTag);
 extern bool command_tag_table_rewrite_ok(CommandTag commandTag);
+extern bool command_tag_ddl_replication_ok(CommandTag commandTag);
 extern CommandTag GetCommandTagEnum(const char *commandname);
 extern Size BuildQueryCompletionString(char *buff, const QueryCompletion *qc,
 									   bool nameonly);
diff --git a/src/include/tcop/cmdtaglist.h b/src/include/tcop/cmdtaglist.h
index e738ac1..18b69e4 100644
--- a/src/include/tcop/cmdtaglist.h
+++ b/src/include/tcop/cmdtaglist.h
@@ -23,196 +23,196 @@
  * textual name, so that we can bsearch on it; see GetCommandTagEnum().
  */
 
-/* symbol name, textual name, event_trigger_ok, table_rewrite_ok, rowcount */
-PG_CMDTAG(CMDTAG_UNKNOWN, "???", false, false, false)
-PG_CMDTAG(CMDTAG_ALTER_ACCESS_METHOD, "ALTER ACCESS METHOD", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_AGGREGATE, "ALTER AGGREGATE", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_CAST, "ALTER CAST", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_COLLATION, "ALTER COLLATION", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_CONSTRAINT, "ALTER CONSTRAINT", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_CONVERSION, "ALTER CONVERSION", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_DATABASE, "ALTER DATABASE", false, false, false)
-PG_CMDTAG(CMDTAG_ALTER_DEFAULT_PRIVILEGES, "ALTER DEFAULT PRIVILEGES", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_DOMAIN, "ALTER DOMAIN", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_EVENT_TRIGGER, "ALTER EVENT TRIGGER", false, false, false)
-PG_CMDTAG(CMDTAG_ALTER_EXTENSION, "ALTER EXTENSION", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_FOREIGN_DATA_WRAPPER, "ALTER FOREIGN DATA WRAPPER", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_FOREIGN_TABLE, "ALTER FOREIGN TABLE", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_FUNCTION, "ALTER FUNCTION", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_INDEX, "ALTER INDEX", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_LANGUAGE, "ALTER LANGUAGE", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_LARGE_OBJECT, "ALTER LARGE OBJECT", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_MATERIALIZED_VIEW, "ALTER MATERIALIZED VIEW", true, true, false)
-PG_CMDTAG(CMDTAG_ALTER_OPERATOR, "ALTER OPERATOR", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_OPERATOR_CLASS, "ALTER OPERATOR CLASS", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_OPERATOR_FAMILY, "ALTER OPERATOR FAMILY", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_POLICY, "ALTER POLICY", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_PROCEDURE, "ALTER PROCEDURE", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_PUBLICATION, "ALTER PUBLICATION", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_ROLE, "ALTER ROLE", false, false, false)
-PG_CMDTAG(CMDTAG_ALTER_ROUTINE, "ALTER ROUTINE", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_RULE, "ALTER RULE", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_SCHEMA, "ALTER SCHEMA", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_SEQUENCE, "ALTER SEQUENCE", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_SERVER, "ALTER SERVER", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_STATISTICS, "ALTER STATISTICS", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_SUBSCRIPTION, "ALTER SUBSCRIPTION", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_SYSTEM, "ALTER SYSTEM", false, false, false)
-PG_CMDTAG(CMDTAG_ALTER_TABLE, "ALTER TABLE", true, true, false)
-PG_CMDTAG(CMDTAG_ALTER_TABLESPACE, "ALTER TABLESPACE", false, false, false)
-PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_CONFIGURATION, "ALTER TEXT SEARCH CONFIGURATION", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_DICTIONARY, "ALTER TEXT SEARCH DICTIONARY", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_PARSER, "ALTER TEXT SEARCH PARSER", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_TEMPLATE, "ALTER TEXT SEARCH TEMPLATE", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_TRANSFORM, "ALTER TRANSFORM", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_TRIGGER, "ALTER TRIGGER", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_TYPE, "ALTER TYPE", true, true, false)
-PG_CMDTAG(CMDTAG_ALTER_USER_MAPPING, "ALTER USER MAPPING", true, false, false)
-PG_CMDTAG(CMDTAG_ALTER_VIEW, "ALTER VIEW", true, false, false)
-PG_CMDTAG(CMDTAG_ANALYZE, "ANALYZE", false, false, false)
-PG_CMDTAG(CMDTAG_BEGIN, "BEGIN", false, false, false)
-PG_CMDTAG(CMDTAG_CALL, "CALL", false, false, false)
-PG_CMDTAG(CMDTAG_CHECKPOINT, "CHECKPOINT", false, false, false)
-PG_CMDTAG(CMDTAG_CLOSE, "CLOSE", false, false, false)
-PG_CMDTAG(CMDTAG_CLOSE_CURSOR, "CLOSE CURSOR", false, false, false)
-PG_CMDTAG(CMDTAG_CLOSE_CURSOR_ALL, "CLOSE CURSOR ALL", false, false, false)
-PG_CMDTAG(CMDTAG_CLUSTER, "CLUSTER", false, false, false)
-PG_CMDTAG(CMDTAG_COMMENT, "COMMENT", true, false, false)
-PG_CMDTAG(CMDTAG_COMMIT, "COMMIT", false, false, false)
-PG_CMDTAG(CMDTAG_COMMIT_PREPARED, "COMMIT PREPARED", false, false, false)
-PG_CMDTAG(CMDTAG_COPY, "COPY", false, false, true)
-PG_CMDTAG(CMDTAG_COPY_FROM, "COPY FROM", false, false, false)
-PG_CMDTAG(CMDTAG_CREATE_ACCESS_METHOD, "CREATE ACCESS METHOD", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_AGGREGATE, "CREATE AGGREGATE", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_CAST, "CREATE CAST", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_COLLATION, "CREATE COLLATION", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_CONSTRAINT, "CREATE CONSTRAINT", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_CONVERSION, "CREATE CONVERSION", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_DATABASE, "CREATE DATABASE", false, false, false)
-PG_CMDTAG(CMDTAG_CREATE_DOMAIN, "CREATE DOMAIN", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_EVENT_TRIGGER, "CREATE EVENT TRIGGER", false, false, false)
-PG_CMDTAG(CMDTAG_CREATE_EXTENSION, "CREATE EXTENSION", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_FOREIGN_DATA_WRAPPER, "CREATE FOREIGN DATA WRAPPER", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_FOREIGN_TABLE, "CREATE FOREIGN TABLE", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_FUNCTION, "CREATE FUNCTION", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_INDEX, "CREATE INDEX", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_LANGUAGE, "CREATE LANGUAGE", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_MATERIALIZED_VIEW, "CREATE MATERIALIZED VIEW", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_OPERATOR, "CREATE OPERATOR", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_OPERATOR_CLASS, "CREATE OPERATOR CLASS", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_OPERATOR_FAMILY, "CREATE OPERATOR FAMILY", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_POLICY, "CREATE POLICY", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_PROCEDURE, "CREATE PROCEDURE", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_PUBLICATION, "CREATE PUBLICATION", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_ROLE, "CREATE ROLE", false, false, false)
-PG_CMDTAG(CMDTAG_CREATE_ROUTINE, "CREATE ROUTINE", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_RULE, "CREATE RULE", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_SCHEMA, "CREATE SCHEMA", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_SEQUENCE, "CREATE SEQUENCE", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_SERVER, "CREATE SERVER", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_STATISTICS, "CREATE STATISTICS", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_SUBSCRIPTION, "CREATE SUBSCRIPTION", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_TABLE, "CREATE TABLE", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_TABLE_AS, "CREATE TABLE AS", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_TABLESPACE, "CREATE TABLESPACE", false, false, false)
-PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_CONFIGURATION, "CREATE TEXT SEARCH CONFIGURATION", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_DICTIONARY, "CREATE TEXT SEARCH DICTIONARY", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_PARSER, "CREATE TEXT SEARCH PARSER", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_TEMPLATE, "CREATE TEXT SEARCH TEMPLATE", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_TRANSFORM, "CREATE TRANSFORM", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_TRIGGER, "CREATE TRIGGER", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_TYPE, "CREATE TYPE", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_USER_MAPPING, "CREATE USER MAPPING", true, false, false)
-PG_CMDTAG(CMDTAG_CREATE_VIEW, "CREATE VIEW", true, false, false)
-PG_CMDTAG(CMDTAG_DEALLOCATE, "DEALLOCATE", false, false, false)
-PG_CMDTAG(CMDTAG_DEALLOCATE_ALL, "DEALLOCATE ALL", false, false, false)
-PG_CMDTAG(CMDTAG_DECLARE_CURSOR, "DECLARE CURSOR", false, false, false)
-PG_CMDTAG(CMDTAG_DELETE, "DELETE", false, false, true)
-PG_CMDTAG(CMDTAG_DISCARD, "DISCARD", false, false, false)
-PG_CMDTAG(CMDTAG_DISCARD_ALL, "DISCARD ALL", false, false, false)
-PG_CMDTAG(CMDTAG_DISCARD_PLANS, "DISCARD PLANS", false, false, false)
-PG_CMDTAG(CMDTAG_DISCARD_SEQUENCES, "DISCARD SEQUENCES", false, false, false)
-PG_CMDTAG(CMDTAG_DISCARD_TEMP, "DISCARD TEMP", false, false, false)
-PG_CMDTAG(CMDTAG_DO, "DO", false, false, false)
-PG_CMDTAG(CMDTAG_DROP_ACCESS_METHOD, "DROP ACCESS METHOD", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_AGGREGATE, "DROP AGGREGATE", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_CAST, "DROP CAST", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_COLLATION, "DROP COLLATION", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_CONSTRAINT, "DROP CONSTRAINT", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_CONVERSION, "DROP CONVERSION", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_DATABASE, "DROP DATABASE", false, false, false)
-PG_CMDTAG(CMDTAG_DROP_DOMAIN, "DROP DOMAIN", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_EVENT_TRIGGER, "DROP EVENT TRIGGER", false, false, false)
-PG_CMDTAG(CMDTAG_DROP_EXTENSION, "DROP EXTENSION", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_FOREIGN_DATA_WRAPPER, "DROP FOREIGN DATA WRAPPER", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_FOREIGN_TABLE, "DROP FOREIGN TABLE", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_FUNCTION, "DROP FUNCTION", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_INDEX, "DROP INDEX", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_LANGUAGE, "DROP LANGUAGE", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_MATERIALIZED_VIEW, "DROP MATERIALIZED VIEW", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_OPERATOR, "DROP OPERATOR", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_OPERATOR_CLASS, "DROP OPERATOR CLASS", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_OPERATOR_FAMILY, "DROP OPERATOR FAMILY", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_OWNED, "DROP OWNED", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_POLICY, "DROP POLICY", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_PROCEDURE, "DROP PROCEDURE", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_PUBLICATION, "DROP PUBLICATION", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_ROLE, "DROP ROLE", false, false, false)
-PG_CMDTAG(CMDTAG_DROP_ROUTINE, "DROP ROUTINE", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_RULE, "DROP RULE", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_SCHEMA, "DROP SCHEMA", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_SEQUENCE, "DROP SEQUENCE", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_SERVER, "DROP SERVER", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_STATISTICS, "DROP STATISTICS", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_SUBSCRIPTION, "DROP SUBSCRIPTION", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_TABLE, "DROP TABLE", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_TABLESPACE, "DROP TABLESPACE", false, false, false)
-PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_CONFIGURATION, "DROP TEXT SEARCH CONFIGURATION", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_DICTIONARY, "DROP TEXT SEARCH DICTIONARY", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_PARSER, "DROP TEXT SEARCH PARSER", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_TEMPLATE, "DROP TEXT SEARCH TEMPLATE", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_TRANSFORM, "DROP TRANSFORM", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_TRIGGER, "DROP TRIGGER", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_TYPE, "DROP TYPE", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_USER_MAPPING, "DROP USER MAPPING", true, false, false)
-PG_CMDTAG(CMDTAG_DROP_VIEW, "DROP VIEW", true, false, false)
-PG_CMDTAG(CMDTAG_EXECUTE, "EXECUTE", false, false, false)
-PG_CMDTAG(CMDTAG_EXPLAIN, "EXPLAIN", false, false, false)
-PG_CMDTAG(CMDTAG_FETCH, "FETCH", false, false, true)
-PG_CMDTAG(CMDTAG_GRANT, "GRANT", true, false, false)
-PG_CMDTAG(CMDTAG_GRANT_ROLE, "GRANT ROLE", false, false, false)
-PG_CMDTAG(CMDTAG_IMPORT_FOREIGN_SCHEMA, "IMPORT FOREIGN SCHEMA", true, false, false)
-PG_CMDTAG(CMDTAG_INSERT, "INSERT", false, false, true)
-PG_CMDTAG(CMDTAG_LISTEN, "LISTEN", false, false, false)
-PG_CMDTAG(CMDTAG_LOAD, "LOAD", false, false, false)
-PG_CMDTAG(CMDTAG_LOCK_TABLE, "LOCK TABLE", false, false, false)
-PG_CMDTAG(CMDTAG_MERGE, "MERGE", false, false, true)
-PG_CMDTAG(CMDTAG_MOVE, "MOVE", false, false, true)
-PG_CMDTAG(CMDTAG_NOTIFY, "NOTIFY", false, false, false)
-PG_CMDTAG(CMDTAG_PREPARE, "PREPARE", false, false, false)
-PG_CMDTAG(CMDTAG_PREPARE_TRANSACTION, "PREPARE TRANSACTION", false, false, false)
-PG_CMDTAG(CMDTAG_REASSIGN_OWNED, "REASSIGN OWNED", false, false, false)
-PG_CMDTAG(CMDTAG_REFRESH_MATERIALIZED_VIEW, "REFRESH MATERIALIZED VIEW", true, false, false)
-PG_CMDTAG(CMDTAG_REINDEX, "REINDEX", false, false, false)
-PG_CMDTAG(CMDTAG_RELEASE, "RELEASE", false, false, false)
-PG_CMDTAG(CMDTAG_RESET, "RESET", false, false, false)
-PG_CMDTAG(CMDTAG_REVOKE, "REVOKE", true, false, false)
-PG_CMDTAG(CMDTAG_REVOKE_ROLE, "REVOKE ROLE", false, false, false)
-PG_CMDTAG(CMDTAG_ROLLBACK, "ROLLBACK", false, false, false)
-PG_CMDTAG(CMDTAG_ROLLBACK_PREPARED, "ROLLBACK PREPARED", false, false, false)
-PG_CMDTAG(CMDTAG_SAVEPOINT, "SAVEPOINT", false, false, false)
-PG_CMDTAG(CMDTAG_SECURITY_LABEL, "SECURITY LABEL", true, false, false)
-PG_CMDTAG(CMDTAG_SELECT, "SELECT", false, false, true)
-PG_CMDTAG(CMDTAG_SELECT_FOR_KEY_SHARE, "SELECT FOR KEY SHARE", false, false, false)
-PG_CMDTAG(CMDTAG_SELECT_FOR_NO_KEY_UPDATE, "SELECT FOR NO KEY UPDATE", false, false, false)
-PG_CMDTAG(CMDTAG_SELECT_FOR_SHARE, "SELECT FOR SHARE", false, false, false)
-PG_CMDTAG(CMDTAG_SELECT_FOR_UPDATE, "SELECT FOR UPDATE", false, false, false)
-PG_CMDTAG(CMDTAG_SELECT_INTO, "SELECT INTO", true, false, false)
-PG_CMDTAG(CMDTAG_SET, "SET", false, false, false)
-PG_CMDTAG(CMDTAG_SET_CONSTRAINTS, "SET CONSTRAINTS", false, false, false)
-PG_CMDTAG(CMDTAG_SHOW, "SHOW", false, false, false)
-PG_CMDTAG(CMDTAG_START_TRANSACTION, "START TRANSACTION", false, false, false)
-PG_CMDTAG(CMDTAG_TRUNCATE_TABLE, "TRUNCATE TABLE", false, false, false)
-PG_CMDTAG(CMDTAG_UNLISTEN, "UNLISTEN", false, false, false)
-PG_CMDTAG(CMDTAG_UPDATE, "UPDATE", false, false, true)
-PG_CMDTAG(CMDTAG_VACUUM, "VACUUM", false, false, false)
+/* symbol name, textual name, event_trigger_ok, table_rewrite_ok, rowcount, ddlreplok */
+PG_CMDTAG(CMDTAG_UNKNOWN, "???", false, false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_ACCESS_METHOD, "ALTER ACCESS METHOD", true, false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_AGGREGATE, "ALTER AGGREGATE", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_CAST, "ALTER CAST", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_COLLATION, "ALTER COLLATION", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_CONSTRAINT, "ALTER CONSTRAINT", true, false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_CONVERSION, "ALTER CONVERSION", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_DATABASE, "ALTER DATABASE", false, false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_DEFAULT_PRIVILEGES, "ALTER DEFAULT PRIVILEGES", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_DOMAIN, "ALTER DOMAIN", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_EVENT_TRIGGER, "ALTER EVENT TRIGGER", false, false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_EXTENSION, "ALTER EXTENSION", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_FOREIGN_DATA_WRAPPER, "ALTER FOREIGN DATA WRAPPER", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_FOREIGN_TABLE, "ALTER FOREIGN TABLE", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_FUNCTION, "ALTER FUNCTION", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_INDEX, "ALTER INDEX", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_LANGUAGE, "ALTER LANGUAGE", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_LARGE_OBJECT, "ALTER LARGE OBJECT", true, false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_MATERIALIZED_VIEW, "ALTER MATERIALIZED VIEW", true, true, false, true)
+PG_CMDTAG(CMDTAG_ALTER_OPERATOR, "ALTER OPERATOR", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_OPERATOR_CLASS, "ALTER OPERATOR CLASS", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_OPERATOR_FAMILY, "ALTER OPERATOR FAMILY", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_POLICY, "ALTER POLICY", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_PROCEDURE, "ALTER PROCEDURE", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_PUBLICATION, "ALTER PUBLICATION", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_ROLE, "ALTER ROLE", false, false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_ROUTINE, "ALTER ROUTINE", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_RULE, "ALTER RULE", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_SCHEMA, "ALTER SCHEMA", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_SEQUENCE, "ALTER SEQUENCE", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_SERVER, "ALTER SERVER", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_STATISTICS, "ALTER STATISTICS", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_SUBSCRIPTION, "ALTER SUBSCRIPTION", true, false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_SYSTEM, "ALTER SYSTEM", false, false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_TABLE, "ALTER TABLE", true, true, false, true)
+PG_CMDTAG(CMDTAG_ALTER_TABLESPACE, "ALTER TABLESPACE", false, false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_CONFIGURATION, "ALTER TEXT SEARCH CONFIGURATION", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_DICTIONARY, "ALTER TEXT SEARCH DICTIONARY", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_PARSER, "ALTER TEXT SEARCH PARSER", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_TEXT_SEARCH_TEMPLATE, "ALTER TEXT SEARCH TEMPLATE", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_TRANSFORM, "ALTER TRANSFORM", true, false, false, false)
+PG_CMDTAG(CMDTAG_ALTER_TRIGGER, "ALTER TRIGGER", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_TYPE, "ALTER TYPE", true, true, false, true)
+PG_CMDTAG(CMDTAG_ALTER_USER_MAPPING, "ALTER USER MAPPING", true, false, false, true)
+PG_CMDTAG(CMDTAG_ALTER_VIEW, "ALTER VIEW", true, false, false, true)
+PG_CMDTAG(CMDTAG_ANALYZE, "ANALYZE", false, false, false, false)
+PG_CMDTAG(CMDTAG_BEGIN, "BEGIN", false, false, false, false)
+PG_CMDTAG(CMDTAG_CALL, "CALL", false, false, false, false)
+PG_CMDTAG(CMDTAG_CHECKPOINT, "CHECKPOINT", false, false, false, false)
+PG_CMDTAG(CMDTAG_CLOSE, "CLOSE", false, false, false, false)
+PG_CMDTAG(CMDTAG_CLOSE_CURSOR, "CLOSE CURSOR", false, false, false, false)
+PG_CMDTAG(CMDTAG_CLOSE_CURSOR_ALL, "CLOSE CURSOR ALL", false, false, false, false)
+PG_CMDTAG(CMDTAG_CLUSTER, "CLUSTER", false, false, false, false)
+PG_CMDTAG(CMDTAG_COMMENT, "COMMENT", true, false, false, true)
+PG_CMDTAG(CMDTAG_COMMIT, "COMMIT", false, false, false, false)
+PG_CMDTAG(CMDTAG_COMMIT_PREPARED, "COMMIT PREPARED", false, false, false, false)
+PG_CMDTAG(CMDTAG_COPY, "COPY", false, false, true, false)
+PG_CMDTAG(CMDTAG_COPY_FROM, "COPY FROM", false, false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_ACCESS_METHOD, "CREATE ACCESS METHOD", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_AGGREGATE, "CREATE AGGREGATE", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_CAST, "CREATE CAST", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_COLLATION, "CREATE COLLATION", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_CONSTRAINT, "CREATE CONSTRAINT", true, false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_CONVERSION, "CREATE CONVERSION", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_DATABASE, "CREATE DATABASE", false, false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_DOMAIN, "CREATE DOMAIN", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_EVENT_TRIGGER, "CREATE EVENT TRIGGER", false, false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_EXTENSION, "CREATE EXTENSION", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_FOREIGN_DATA_WRAPPER, "CREATE FOREIGN DATA WRAPPER", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_FOREIGN_TABLE, "CREATE FOREIGN TABLE", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_FUNCTION, "CREATE FUNCTION", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_INDEX, "CREATE INDEX", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_LANGUAGE, "CREATE LANGUAGE", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_MATERIALIZED_VIEW, "CREATE MATERIALIZED VIEW", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_OPERATOR, "CREATE OPERATOR", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_OPERATOR_CLASS, "CREATE OPERATOR CLASS", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_OPERATOR_FAMILY, "CREATE OPERATOR FAMILY", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_POLICY, "CREATE POLICY", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_PROCEDURE, "CREATE PROCEDURE", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_PUBLICATION, "CREATE PUBLICATION", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_ROLE, "CREATE ROLE", false, false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_ROUTINE, "CREATE ROUTINE", true, false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_RULE, "CREATE RULE", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_SCHEMA, "CREATE SCHEMA", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_SEQUENCE, "CREATE SEQUENCE", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_SERVER, "CREATE SERVER", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_STATISTICS, "CREATE STATISTICS", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_SUBSCRIPTION, "CREATE SUBSCRIPTION", true, false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_TABLE, "CREATE TABLE", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_TABLE_AS, "CREATE TABLE AS", true, false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_TABLESPACE, "CREATE TABLESPACE", false, false, false, false)
+PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_CONFIGURATION, "CREATE TEXT SEARCH CONFIGURATION", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_DICTIONARY, "CREATE TEXT SEARCH DICTIONARY", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_PARSER, "CREATE TEXT SEARCH PARSER", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_TEXT_SEARCH_TEMPLATE, "CREATE TEXT SEARCH TEMPLATE", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_TRANSFORM, "CREATE TRANSFORM", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_TRIGGER, "CREATE TRIGGER", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_TYPE, "CREATE TYPE", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_USER_MAPPING, "CREATE USER MAPPING", true, false, false, true)
+PG_CMDTAG(CMDTAG_CREATE_VIEW, "CREATE VIEW", true, false, false, true)
+PG_CMDTAG(CMDTAG_DEALLOCATE, "DEALLOCATE", false, false, false, false)
+PG_CMDTAG(CMDTAG_DEALLOCATE_ALL, "DEALLOCATE ALL", false, false, false, false)
+PG_CMDTAG(CMDTAG_DECLARE_CURSOR, "DECLARE CURSOR", false, false, false, false)
+PG_CMDTAG(CMDTAG_DELETE, "DELETE", false, false, true, false)
+PG_CMDTAG(CMDTAG_DISCARD, "DISCARD", false, false, false, false)
+PG_CMDTAG(CMDTAG_DISCARD_ALL, "DISCARD ALL", false, false, false, false)
+PG_CMDTAG(CMDTAG_DISCARD_PLANS, "DISCARD PLANS", false, false, false, false)
+PG_CMDTAG(CMDTAG_DISCARD_SEQUENCES, "DISCARD SEQUENCES", false, false, false, false)
+PG_CMDTAG(CMDTAG_DISCARD_TEMP, "DISCARD TEMP", false, false, false, false)
+PG_CMDTAG(CMDTAG_DO, "DO", false, false, false, false)
+PG_CMDTAG(CMDTAG_DROP_ACCESS_METHOD, "DROP ACCESS METHOD", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_AGGREGATE, "DROP AGGREGATE", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_CAST, "DROP CAST", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_COLLATION, "DROP COLLATION", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_CONSTRAINT, "DROP CONSTRAINT", true, false, false, false)
+PG_CMDTAG(CMDTAG_DROP_CONVERSION, "DROP CONVERSION", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_DATABASE, "DROP DATABASE", false, false, false, false)
+PG_CMDTAG(CMDTAG_DROP_DOMAIN, "DROP DOMAIN", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_EVENT_TRIGGER, "DROP EVENT TRIGGER", false, false, false, false)
+PG_CMDTAG(CMDTAG_DROP_EXTENSION, "DROP EXTENSION", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_FOREIGN_DATA_WRAPPER, "DROP FOREIGN DATA WRAPPER", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_FOREIGN_TABLE, "DROP FOREIGN TABLE", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_FUNCTION, "DROP FUNCTION", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_INDEX, "DROP INDEX", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_LANGUAGE, "DROP LANGUAGE", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_MATERIALIZED_VIEW, "DROP MATERIALIZED VIEW", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_OPERATOR, "DROP OPERATOR", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_OPERATOR_CLASS, "DROP OPERATOR CLASS", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_OPERATOR_FAMILY, "DROP OPERATOR FAMILY", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_OWNED, "DROP OWNED", true, false, false, false)
+PG_CMDTAG(CMDTAG_DROP_POLICY, "DROP POLICY", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_PROCEDURE, "DROP PROCEDURE", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_PUBLICATION, "DROP PUBLICATION", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_ROLE, "DROP ROLE", false, false, false, false)
+PG_CMDTAG(CMDTAG_DROP_ROUTINE, "DROP ROUTINE", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_RULE, "DROP RULE", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_SCHEMA, "DROP SCHEMA", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_SEQUENCE, "DROP SEQUENCE", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_SERVER, "DROP SERVER", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_STATISTICS, "DROP STATISTICS", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_SUBSCRIPTION, "DROP SUBSCRIPTION", true, false, false, false)
+PG_CMDTAG(CMDTAG_DROP_TABLE, "DROP TABLE", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_TABLESPACE, "DROP TABLESPACE", false, false, false, false)
+PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_CONFIGURATION, "DROP TEXT SEARCH CONFIGURATION", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_DICTIONARY, "DROP TEXT SEARCH DICTIONARY", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_PARSER, "DROP TEXT SEARCH PARSER", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_TEXT_SEARCH_TEMPLATE, "DROP TEXT SEARCH TEMPLATE", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_TRANSFORM, "DROP TRANSFORM", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_TRIGGER, "DROP TRIGGER", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_TYPE, "DROP TYPE", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_USER_MAPPING, "DROP USER MAPPING", true, false, false, true)
+PG_CMDTAG(CMDTAG_DROP_VIEW, "DROP VIEW", true, false, false, true)
+PG_CMDTAG(CMDTAG_EXECUTE, "EXECUTE", false, false, false, false)
+PG_CMDTAG(CMDTAG_EXPLAIN, "EXPLAIN", false, false, false, false)
+PG_CMDTAG(CMDTAG_FETCH, "FETCH", false, false, true, false)
+PG_CMDTAG(CMDTAG_GRANT, "GRANT", true, false, false, true)
+PG_CMDTAG(CMDTAG_GRANT_ROLE, "GRANT ROLE", false, false, false, false)
+PG_CMDTAG(CMDTAG_IMPORT_FOREIGN_SCHEMA, "IMPORT FOREIGN SCHEMA", true, false, false, true)
+PG_CMDTAG(CMDTAG_INSERT, "INSERT", false, false, true, false)
+PG_CMDTAG(CMDTAG_LISTEN, "LISTEN", false, false, false, false)
+PG_CMDTAG(CMDTAG_LOAD, "LOAD", false, false, false, false)
+PG_CMDTAG(CMDTAG_LOCK_TABLE, "LOCK TABLE", false, false, false, false)
+PG_CMDTAG(CMDTAG_MERGE, "MERGE", false, false, true, false)
+PG_CMDTAG(CMDTAG_MOVE, "MOVE", false, false, true, false)
+PG_CMDTAG(CMDTAG_NOTIFY, "NOTIFY", false, false, false, false)
+PG_CMDTAG(CMDTAG_PREPARE, "PREPARE", false, false, false, false)
+PG_CMDTAG(CMDTAG_PREPARE_TRANSACTION, "PREPARE TRANSACTION", false, false, false, false)
+PG_CMDTAG(CMDTAG_REASSIGN_OWNED, "REASSIGN OWNED", false, false, false, false)
+PG_CMDTAG(CMDTAG_REFRESH_MATERIALIZED_VIEW, "REFRESH MATERIALIZED VIEW", true, false, false, true)
+PG_CMDTAG(CMDTAG_REINDEX, "REINDEX", false, false, false, false)
+PG_CMDTAG(CMDTAG_RELEASE, "RELEASE", false, false, false, false)
+PG_CMDTAG(CMDTAG_RESET, "RESET", false, false, false, false)
+PG_CMDTAG(CMDTAG_REVOKE, "REVOKE", true, false, false, true)
+PG_CMDTAG(CMDTAG_REVOKE_ROLE, "REVOKE ROLE", false, false, false, false)
+PG_CMDTAG(CMDTAG_ROLLBACK, "ROLLBACK", false, false, false, false)
+PG_CMDTAG(CMDTAG_ROLLBACK_PREPARED, "ROLLBACK PREPARED", false, false, false, false)
+PG_CMDTAG(CMDTAG_SAVEPOINT, "SAVEPOINT", false, false, false, false)
+PG_CMDTAG(CMDTAG_SECURITY_LABEL, "SECURITY LABEL", true, false, false, true)
+PG_CMDTAG(CMDTAG_SELECT, "SELECT", false, false, true, false)
+PG_CMDTAG(CMDTAG_SELECT_FOR_KEY_SHARE, "SELECT FOR KEY SHARE", false, false, false, false)
+PG_CMDTAG(CMDTAG_SELECT_FOR_NO_KEY_UPDATE, "SELECT FOR NO KEY UPDATE", false, false, false, false)
+PG_CMDTAG(CMDTAG_SELECT_FOR_SHARE, "SELECT FOR SHARE", false, false, false, false)
+PG_CMDTAG(CMDTAG_SELECT_FOR_UPDATE, "SELECT FOR UPDATE", false, false, false, false)
+PG_CMDTAG(CMDTAG_SELECT_INTO, "SELECT INTO", true, false, false, false)
+PG_CMDTAG(CMDTAG_SET, "SET", false, false, false, false)
+PG_CMDTAG(CMDTAG_SET_CONSTRAINTS, "SET CONSTRAINTS", false, false, false, false)
+PG_CMDTAG(CMDTAG_SHOW, "SHOW", false, false, false, false)
+PG_CMDTAG(CMDTAG_START_TRANSACTION, "START TRANSACTION", false, false, false, false)
+PG_CMDTAG(CMDTAG_TRUNCATE_TABLE, "TRUNCATE TABLE", false, false, false, false)
+PG_CMDTAG(CMDTAG_UNLISTEN, "UNLISTEN", false, false, false, false)
+PG_CMDTAG(CMDTAG_UPDATE, "UPDATE", false, false, true, false)
+PG_CMDTAG(CMDTAG_VACUUM, "VACUUM", false, false, false, false)
diff --git a/src/include/tcop/deparse_utility.h b/src/include/tcop/deparse_utility.h
index 9e262d7..fbd0976 100644
--- a/src/include/tcop/deparse_utility.h
+++ b/src/include/tcop/deparse_utility.h
@@ -65,6 +65,7 @@ typedef struct CollectedCommand
 		{
 			Oid			objectId;
 			Oid			classId;
+			bool		rewrite;
 			List	   *subcmds;
 		}			alterTable;
 
diff --git a/src/include/utils/evtcache.h b/src/include/utils/evtcache.h
index d340026..91d4bdd 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
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index c00e283..722b391 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -6223,9 +6223,9 @@ List of schemas
 (0 rows)
 
 \dRp "no.such.publication"
-                              List of publications
- Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root 
-------+-------+------------+---------+---------+---------+-----------+----------
+                                          List of publications
+ Name | Owner | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+------+-------+------------+----------+------------+---------+---------+---------+-----------+----------
 (0 rows)
 
 \dRs "no.such.subscription"
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 427f87e..b2317e7 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -30,20 +30,20 @@ ERROR:  conflicting or redundant options
 LINE 1: ...ub_xxx WITH (publish_via_partition_root = 'true', publish_vi...
                                                              ^
 \dRp
-                                              List of publications
-        Name        |          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------+--------------------------+------------+---------+---------+---------+-----------+----------
- testpib_ins_trunct | regress_publication_user | f          | t       | f       | f       | f         | f
- testpub_default    | regress_publication_user | f          | f       | t       | f       | f         | f
+                                                          List of publications
+        Name        |          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ testpib_ins_trunct | regress_publication_user | f          | f        | f          | t       | f       | f       | f         | f
+ testpub_default    | regress_publication_user | f          | f        | f          | f       | t       | f       | f         | f
 (2 rows)
 
 ALTER PUBLICATION testpub_default SET (publish = 'insert, update, delete');
 \dRp
-                                              List of publications
-        Name        |          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------+--------------------------+------------+---------+---------+---------+-----------+----------
- testpib_ins_trunct | regress_publication_user | f          | t       | f       | f       | f         | f
- testpub_default    | regress_publication_user | f          | t       | t       | t       | f         | f
+                                                          List of publications
+        Name        |          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ testpib_ins_trunct | regress_publication_user | f          | f        | f          | t       | f       | f       | f         | f
+ testpub_default    | regress_publication_user | f          | f        | f          | t       | t       | t       | f         | f
 (2 rows)
 
 --- adding tables
@@ -87,10 +87,10 @@ RESET client_min_messages;
 -- should be able to add schema to 'FOR TABLE' publication
 ALTER PUBLICATION testpub_fortable ADD TABLES IN SCHEMA pub_test;
 \dRp+ testpub_fortable
-                                Publication testpub_fortable
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                            Publication testpub_fortable
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "public.testpub_tbl1"
 Tables from schemas:
@@ -99,20 +99,20 @@ Tables from schemas:
 -- should be able to drop schema from 'FOR TABLE' publication
 ALTER PUBLICATION testpub_fortable DROP TABLES IN SCHEMA pub_test;
 \dRp+ testpub_fortable
-                                Publication testpub_fortable
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                            Publication testpub_fortable
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "public.testpub_tbl1"
 
 -- should be able to set schema to 'FOR TABLE' publication
 ALTER PUBLICATION testpub_fortable SET TABLES IN SCHEMA pub_test;
 \dRp+ testpub_fortable
-                                Publication testpub_fortable
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                            Publication testpub_fortable
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test"
 
@@ -123,10 +123,10 @@ CREATE PUBLICATION testpub_forschema FOR TABLES IN SCHEMA pub_test;
 CREATE PUBLICATION testpub_for_tbl_schema FOR TABLES IN SCHEMA pub_test, TABLE pub_test.testpub_nopk;
 RESET client_min_messages;
 \dRp+ testpub_for_tbl_schema
-                             Publication testpub_for_tbl_schema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                         Publication testpub_for_tbl_schema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "pub_test.testpub_nopk"
 Tables from schemas:
@@ -135,10 +135,10 @@ Tables from schemas:
 -- should be able to add a table of the same schema to the schema publication
 ALTER PUBLICATION testpub_forschema ADD TABLE pub_test.testpub_nopk;
 \dRp+ testpub_forschema
-                               Publication testpub_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "pub_test.testpub_nopk"
 Tables from schemas:
@@ -147,10 +147,10 @@ Tables from schemas:
 -- should be able to drop the table
 ALTER PUBLICATION testpub_forschema DROP TABLE pub_test.testpub_nopk;
 \dRp+ testpub_forschema
-                               Publication testpub_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test"
 
@@ -161,10 +161,10 @@ ERROR:  relation "testpub_nopk" is not part of the publication
 -- should be able to set table to schema publication
 ALTER PUBLICATION testpub_forschema SET TABLE pub_test.testpub_nopk;
 \dRp+ testpub_forschema
-                               Publication testpub_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "pub_test.testpub_nopk"
 
@@ -186,10 +186,10 @@ Publications:
     "testpub_foralltables"
 
 \dRp+ testpub_foralltables
-                              Publication testpub_foralltables
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | t          | t       | t       | f       | f         | f
+                                          Publication testpub_foralltables
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | t          | f        | f          | t       | t       | f       | f         | f
 (1 row)
 
 DROP TABLE testpub_tbl2;
@@ -201,19 +201,19 @@ CREATE PUBLICATION testpub3 FOR TABLE testpub_tbl3;
 CREATE PUBLICATION testpub4 FOR TABLE ONLY testpub_tbl3;
 RESET client_min_messages;
 \dRp+ testpub3
-                                    Publication testpub3
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                                Publication testpub3
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "public.testpub_tbl3"
     "public.testpub_tbl3a"
 
 \dRp+ testpub4
-                                    Publication testpub4
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                                Publication testpub4
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "public.testpub_tbl3"
 
@@ -234,10 +234,10 @@ UPDATE testpub_parted1 SET a = 1;
 -- only parent is listed as being in publication, not the partition
 ALTER PUBLICATION testpub_forparted ADD TABLE testpub_parted;
 \dRp+ testpub_forparted
-                               Publication testpub_forparted
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub_forparted
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "public.testpub_parted"
 
@@ -252,10 +252,10 @@ ALTER TABLE testpub_parted DETACH PARTITION testpub_parted1;
 UPDATE testpub_parted1 SET a = 1;
 ALTER PUBLICATION testpub_forparted SET (publish_via_partition_root = true);
 \dRp+ testpub_forparted
-                               Publication testpub_forparted
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | t
+                                           Publication testpub_forparted
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | t
 Tables:
     "public.testpub_parted"
 
@@ -284,10 +284,10 @@ SET client_min_messages = 'ERROR';
 CREATE PUBLICATION testpub5 FOR TABLE testpub_rf_tbl1, testpub_rf_tbl2 WHERE (c <> 'test' AND d < 5) WITH (publish = 'insert');
 RESET client_min_messages;
 \dRp+ testpub5
-                                    Publication testpub5
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | f       | f       | f         | f
+                                                Publication testpub5
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | f       | f       | f         | f
 Tables:
     "public.testpub_rf_tbl1"
     "public.testpub_rf_tbl2" WHERE ((c <> 'test'::text) AND (d < 5))
@@ -300,10 +300,10 @@ Tables:
 
 ALTER PUBLICATION testpub5 ADD TABLE testpub_rf_tbl3 WHERE (e > 1000 AND e < 2000);
 \dRp+ testpub5
-                                    Publication testpub5
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | f       | f       | f         | f
+                                                Publication testpub5
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | f       | f       | f         | f
 Tables:
     "public.testpub_rf_tbl1"
     "public.testpub_rf_tbl2" WHERE ((c <> 'test'::text) AND (d < 5))
@@ -319,10 +319,10 @@ Publications:
 
 ALTER PUBLICATION testpub5 DROP TABLE testpub_rf_tbl2;
 \dRp+ testpub5
-                                    Publication testpub5
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | f       | f       | f         | f
+                                                Publication testpub5
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | f       | f       | f         | f
 Tables:
     "public.testpub_rf_tbl1"
     "public.testpub_rf_tbl3" WHERE ((e > 1000) AND (e < 2000))
@@ -330,10 +330,10 @@ Tables:
 -- remove testpub_rf_tbl1 and add testpub_rf_tbl3 again (another WHERE expression)
 ALTER PUBLICATION testpub5 SET TABLE testpub_rf_tbl3 WHERE (e > 300 AND e < 500);
 \dRp+ testpub5
-                                    Publication testpub5
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | f       | f       | f         | f
+                                                Publication testpub5
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | f       | f       | f         | f
 Tables:
     "public.testpub_rf_tbl3" WHERE ((e > 300) AND (e < 500))
 
@@ -366,10 +366,10 @@ SET client_min_messages = 'ERROR';
 CREATE PUBLICATION testpub_syntax1 FOR TABLE testpub_rf_tbl1, ONLY testpub_rf_tbl3 WHERE (e < 999) WITH (publish = 'insert');
 RESET client_min_messages;
 \dRp+ testpub_syntax1
-                                Publication testpub_syntax1
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | f       | f       | f         | f
+                                            Publication testpub_syntax1
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | f       | f       | f         | f
 Tables:
     "public.testpub_rf_tbl1"
     "public.testpub_rf_tbl3" WHERE (e < 999)
@@ -379,10 +379,10 @@ SET client_min_messages = 'ERROR';
 CREATE PUBLICATION testpub_syntax2 FOR TABLE testpub_rf_tbl1, testpub_rf_schema1.testpub_rf_tbl5 WHERE (h < 999) WITH (publish = 'insert');
 RESET client_min_messages;
 \dRp+ testpub_syntax2
-                                Publication testpub_syntax2
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | f       | f       | f         | f
+                                            Publication testpub_syntax2
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | f       | f       | f         | f
 Tables:
     "public.testpub_rf_tbl1"
     "testpub_rf_schema1.testpub_rf_tbl5" WHERE (h < 999)
@@ -497,10 +497,10 @@ CREATE PUBLICATION testpub6 FOR TABLES IN SCHEMA testpub_rf_schema2;
 ALTER PUBLICATION testpub6 SET TABLES IN SCHEMA testpub_rf_schema2, TABLE testpub_rf_schema2.testpub_rf_tbl6 WHERE (i < 99);
 RESET client_min_messages;
 \dRp+ testpub6
-                                    Publication testpub6
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                                Publication testpub6
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "testpub_rf_schema2.testpub_rf_tbl6" WHERE (i < 99)
 Tables from schemas:
@@ -714,10 +714,10 @@ CREATE PUBLICATION testpub_table_ins WITH (publish = 'insert, truncate');
 RESET client_min_messages;
 ALTER PUBLICATION testpub_table_ins ADD TABLE testpub_tbl5 (a);		-- ok
 \dRp+ testpub_table_ins
-                               Publication testpub_table_ins
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | f       | f       | t         | f
+                                           Publication testpub_table_ins
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | f       | f       | t         | f
 Tables:
     "public.testpub_tbl5" (a)
 
@@ -891,10 +891,10 @@ CREATE TABLE testpub_tbl_both_filters (a int, b int, c int, PRIMARY KEY (a,c));
 ALTER TABLE testpub_tbl_both_filters REPLICA IDENTITY USING INDEX testpub_tbl_both_filters_pkey;
 ALTER PUBLICATION testpub_both_filters ADD TABLE testpub_tbl_both_filters (a,c) WHERE (c != 1);
 \dRp+ testpub_both_filters
-                              Publication testpub_both_filters
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                          Publication testpub_both_filters
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "public.testpub_tbl_both_filters" (a, c) WHERE (c <> 1)
 
@@ -1099,10 +1099,10 @@ ERROR:  relation "testpub_tbl1" is already member of publication "testpub_fortbl
 CREATE PUBLICATION testpub_fortbl FOR TABLE testpub_tbl1;
 ERROR:  publication "testpub_fortbl" already exists
 \dRp+ testpub_fortbl
-                                 Publication testpub_fortbl
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                             Publication testpub_fortbl
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "pub_test.testpub_nopk"
     "public.testpub_tbl1"
@@ -1140,10 +1140,10 @@ Publications:
     "testpub_fortbl"
 
 \dRp+ testpub_default
-                                Publication testpub_default
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | f         | f
+                                            Publication testpub_default
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | f         | f
 Tables:
     "pub_test.testpub_nopk"
     "public.testpub_tbl1"
@@ -1221,10 +1221,10 @@ REVOKE CREATE ON DATABASE regression FROM regress_publication_user2;
 DROP TABLE testpub_parted;
 DROP TABLE testpub_tbl1;
 \dRp+ testpub_default
-                                Publication testpub_default
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | f         | f
+                                            Publication testpub_default
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | f         | f
 (1 row)
 
 -- fail - must be owner of publication
@@ -1234,20 +1234,20 @@ ERROR:  must be owner of publication testpub_default
 RESET ROLE;
 ALTER PUBLICATION testpub_default RENAME TO testpub_foo;
 \dRp testpub_foo
-                                           List of publications
-    Name     |          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
--------------+--------------------------+------------+---------+---------+---------+-----------+----------
- testpub_foo | regress_publication_user | f          | t       | t       | t       | f         | f
+                                                       List of publications
+    Name     |          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+-------------+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ testpub_foo | regress_publication_user | f          | f        | f          | t       | t       | t       | f         | f
 (1 row)
 
 -- rename back to keep the rest simple
 ALTER PUBLICATION testpub_foo RENAME TO testpub_default;
 ALTER PUBLICATION testpub_default OWNER TO regress_publication_user2;
 \dRp testpub_default
-                                             List of publications
-      Name       |           Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
------------------+---------------------------+------------+---------+---------+---------+-----------+----------
- testpub_default | regress_publication_user2 | f          | t       | t       | t       | f         | f
+                                                         List of publications
+      Name       |           Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+-----------------+---------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ testpub_default | regress_publication_user2 | f          | f        | f          | t       | t       | t       | f         | f
 (1 row)
 
 -- adding schemas and tables
@@ -1263,19 +1263,19 @@ CREATE TABLE "CURRENT_SCHEMA"."CURRENT_SCHEMA"(id int);
 SET client_min_messages = 'ERROR';
 CREATE PUBLICATION testpub1_forschema FOR TABLES IN SCHEMA pub_test1;
 \dRp+ testpub1_forschema
-                               Publication testpub1_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub1_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
 
 CREATE PUBLICATION testpub2_forschema FOR TABLES IN SCHEMA pub_test1, pub_test2, pub_test3;
 \dRp+ testpub2_forschema
-                               Publication testpub2_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub2_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1289,44 +1289,44 @@ CREATE PUBLICATION testpub6_forschema FOR TABLES IN SCHEMA "CURRENT_SCHEMA", CUR
 CREATE PUBLICATION testpub_fortable FOR TABLE "CURRENT_SCHEMA"."CURRENT_SCHEMA";
 RESET client_min_messages;
 \dRp+ testpub3_forschema
-                               Publication testpub3_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub3_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "public"
 
 \dRp+ testpub4_forschema
-                               Publication testpub4_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub4_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "CURRENT_SCHEMA"
 
 \dRp+ testpub5_forschema
-                               Publication testpub5_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub5_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "CURRENT_SCHEMA"
     "public"
 
 \dRp+ testpub6_forschema
-                               Publication testpub6_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub6_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "CURRENT_SCHEMA"
     "public"
 
 \dRp+ testpub_fortable
-                                Publication testpub_fortable
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                            Publication testpub_fortable
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "CURRENT_SCHEMA.CURRENT_SCHEMA"
 
@@ -1360,10 +1360,10 @@ ERROR:  schema "testpub_view" does not exist
 -- dropping the schema should reflect the change in publication
 DROP SCHEMA pub_test3;
 \dRp+ testpub2_forschema
-                               Publication testpub2_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub2_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1371,20 +1371,20 @@ Tables from schemas:
 -- renaming the schema should reflect the change in publication
 ALTER SCHEMA pub_test1 RENAME to pub_test1_renamed;
 \dRp+ testpub2_forschema
-                               Publication testpub2_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub2_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1_renamed"
     "pub_test2"
 
 ALTER SCHEMA pub_test1_renamed RENAME to pub_test1;
 \dRp+ testpub2_forschema
-                               Publication testpub2_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub2_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1392,10 +1392,10 @@ Tables from schemas:
 -- alter publication add schema
 ALTER PUBLICATION testpub1_forschema ADD TABLES IN SCHEMA pub_test2;
 \dRp+ testpub1_forschema
-                               Publication testpub1_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub1_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1404,10 +1404,10 @@ Tables from schemas:
 ALTER PUBLICATION testpub1_forschema ADD TABLES IN SCHEMA non_existent_schema;
 ERROR:  schema "non_existent_schema" does not exist
 \dRp+ testpub1_forschema
-                               Publication testpub1_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub1_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1416,10 +1416,10 @@ Tables from schemas:
 ALTER PUBLICATION testpub1_forschema ADD TABLES IN SCHEMA pub_test1;
 ERROR:  schema "pub_test1" is already member of publication "testpub1_forschema"
 \dRp+ testpub1_forschema
-                               Publication testpub1_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub1_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1427,10 +1427,10 @@ Tables from schemas:
 -- alter publication drop schema
 ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test2;
 \dRp+ testpub1_forschema
-                               Publication testpub1_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub1_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
 
@@ -1438,10 +1438,10 @@ Tables from schemas:
 ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test2;
 ERROR:  tables from schema "pub_test2" are not part of the publication
 \dRp+ testpub1_forschema
-                               Publication testpub1_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub1_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
 
@@ -1449,29 +1449,29 @@ Tables from schemas:
 ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA non_existent_schema;
 ERROR:  schema "non_existent_schema" does not exist
 \dRp+ testpub1_forschema
-                               Publication testpub1_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub1_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
 
 -- drop all schemas
 ALTER PUBLICATION testpub1_forschema DROP TABLES IN SCHEMA pub_test1;
 \dRp+ testpub1_forschema
-                               Publication testpub1_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub1_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 (1 row)
 
 -- alter publication set multiple schema
 ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA pub_test1, pub_test2;
 \dRp+ testpub1_forschema
-                               Publication testpub1_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub1_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1480,10 +1480,10 @@ Tables from schemas:
 ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA non_existent_schema;
 ERROR:  schema "non_existent_schema" does not exist
 \dRp+ testpub1_forschema
-                               Publication testpub1_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub1_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
     "pub_test2"
@@ -1492,10 +1492,10 @@ Tables from schemas:
 -- removing the duplicate schemas
 ALTER PUBLICATION testpub1_forschema SET TABLES IN SCHEMA pub_test1, pub_test1;
 \dRp+ testpub1_forschema
-                               Publication testpub1_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub1_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
 
@@ -1574,18 +1574,18 @@ SET client_min_messages = 'ERROR';
 CREATE PUBLICATION testpub3_forschema;
 RESET client_min_messages;
 \dRp+ testpub3_forschema
-                               Publication testpub3_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub3_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 (1 row)
 
 ALTER PUBLICATION testpub3_forschema SET TABLES IN SCHEMA pub_test1;
 \dRp+ testpub3_forschema
-                               Publication testpub3_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                           Publication testpub3_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables from schemas:
     "pub_test1"
 
@@ -1595,20 +1595,20 @@ CREATE PUBLICATION testpub_forschema_fortable FOR TABLES IN SCHEMA pub_test1, TA
 CREATE PUBLICATION testpub_fortable_forschema FOR TABLE pub_test2.tbl1, TABLES IN SCHEMA pub_test1;
 RESET client_min_messages;
 \dRp+ testpub_forschema_fortable
-                           Publication testpub_forschema_fortable
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                       Publication testpub_forschema_fortable
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "pub_test2.tbl1"
 Tables from schemas:
     "pub_test1"
 
 \dRp+ testpub_fortable_forschema
-                           Publication testpub_fortable_forschema
-          Owner           | All tables | Inserts | Updates | Deletes | Truncates | Via root 
---------------------------+------------+---------+---------+---------+-----------+----------
- regress_publication_user | f          | t       | t       | t       | t         | f
+                                       Publication testpub_fortable_forschema
+          Owner           | All tables | All DDLs | Table DDLs | Inserts | Updates | Deletes | Truncates | Via root 
+--------------------------+------------+----------+------------+---------+---------+---------+-----------+----------
+ regress_publication_user | f          | f        | f          | t       | t       | t       | t         | f
 Tables:
     "pub_test2.tbl1"
 Tables from schemas:
diff --git a/src/test/subscription/t/032_ddl_replication.pl b/src/test/subscription/t/032_ddl_replication.pl
new file mode 100644
index 0000000..4bc4ff2
--- /dev/null
+++ b/src/test/subscription/t/032_ddl_replication.pl
@@ -0,0 +1,465 @@
+# Copyright (c) 2022, PostgreSQL Global Development Group
+# Regression tests for logical replication of DDLs
+#
+use strict;
+use warnings;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+my $node_publisher = PostgreSQL::Test::Cluster->new('publisher');
+$node_publisher->init(allows_streaming => 'logical');
+$node_publisher->start;
+
+my $node_subscriber = PostgreSQL::Test::Cluster->new('subscriber');
+$node_subscriber->init(allows_streaming => 'logical');
+$node_subscriber->start;
+
+my $ddl = "CREATE TABLE test_rep(id int primary key, name varchar, value integer);";
+$node_publisher->safe_psql('postgres', $ddl);
+$node_publisher->safe_psql('postgres', "INSERT INTO test_rep VALUES (1, 'data1', 1);");
+$node_subscriber->safe_psql('postgres', $ddl);
+
+my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
+$node_publisher->safe_psql('postgres',
+	"CREATE PUBLICATION mypub FOR ALL TABLES with (publish = 'insert, update, delete', ddl = 'all');");
+$node_subscriber->safe_psql('postgres',
+	"CREATE SUBSCRIPTION mysub CONNECTION '$publisher_connstr' PUBLICATION mypub;");
+$node_publisher->wait_for_catchup('mysub');
+
+# Make sure we have fully synchronized the table.
+# This prevents ALTER TABLE command below from being executed during table synchronization.
+$node_subscriber->poll_query_until('postgres',
+   "SELECT COUNT(1) = 0 FROM pg_subscription_rel sr WHERE sr.srsubstate NOT IN ('s', 'r') AND sr.srrelid = 'test_rep'::regclass"
+);
+
+# Test ALTER TABLE ADD
+$node_publisher->safe_psql('postgres', "ALTER TABLE test_rep ADD c4 int;");
+$node_publisher->safe_psql('postgres', "INSERT INTO test_rep VALUES (2, 'data2', 2, 2);");
+$node_publisher->wait_for_catchup('mysub');
+my $result = $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_rep WHERE c4 = 2;");
+is($result, qq(1), 'ALTER test_rep ADD replicated');
+
+# Test ALTER TABLE DROP
+$node_publisher->safe_psql('postgres', "ALTER TABLE test_rep DROP c4;");
+$node_publisher->safe_psql('postgres', "DELETE FROM test_rep where id = 2;");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from test_rep;");
+is($result, qq(1), 'ALTER test_rep DROP replicated');
+
+# Test ALTER TABLE ALTER TYPE
+$node_publisher->safe_psql('postgres', "ALTER TABLE test_rep ALTER value TYPE varchar");
+$node_publisher->safe_psql('postgres', "INSERT INTO test_rep VALUES (3, 'data3', '3');");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_rep WHERE value = '3';");
+is($result, qq(1), 'ALTER test_rep ALTER COLUMN TYPE replicated');
+
+# Test ALTER TABLE ALTER SET DEFAULT
+# Check if we have the default value after the direct insert to subscriber node.
+$node_publisher->safe_psql('postgres', "ALTER TABLE test_rep ALTER COLUMN value SET DEFAULT 'foo'");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->safe_psql('postgres', "INSERT INTO test_rep VALUES (4, 'data4');");
+$result = $node_subscriber->safe_psql('postgres', "SELECT value FROM test_rep WHERE id = 4;");
+is($result, 'foo', 'ALTER test_rep ALTER SET DEFAULT replicated');
+
+# Test ALTER TABLE ALTER DROP DEFAULT
+# Check if we don't have the default value previously defined.
+$node_publisher->safe_psql('postgres', "ALTER TABLE test_rep ALTER COLUMN value DROP DEFAULT;");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->safe_psql('postgres', "INSERT INTO test_rep VALUES (5, 'data5');");
+$result = $node_subscriber->safe_psql('postgres', "SELECT value IS NULL FROM test_rep WHERE id = 5;");
+is($result, q(t), 'ALTER test_rep ALTER DROP DEFAULT replicated');
+
+# Test ALTER TABLE ALTER SET NOT NULL
+# Remove the existing record that contains null value first.
+my ($stdout, $stderr);
+$node_subscriber->safe_psql('postgres', "DELETE FROM test_rep WHERE id = 5;");
+$node_publisher->safe_psql('postgres', "ALTER TABLE test_rep ALTER value SET NOT NULL;");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->psql('postgres', "INSERT INTO test_rep VALUES (6, 'data6');",
+					   on_error_stop => 0,
+					   stderr => \$stderr,
+					   stdout => \$stdout);
+$stderr =~ /ERROR:  null value in column \"value\" of relation \"test_rep\" violates not-null constraint/
+  or die "failed to replicate ALTER TABLE ALTER SET NOT NULL";
+
+# Test ALTER TABLE ALTER DROP NOT NULL
+$node_publisher->safe_psql('postgres', "ALTER TABLE test_rep ALTER value DROP NOT NULL;");
+$node_publisher->wait_for_catchup('mysub');
+# Insert same data that has NULL value. This failed before but now should succeed.
+$node_subscriber->safe_psql('postgres', "INSERT INTO test_rep VALUES (6, 'data6');");
+$result = $node_subscriber->safe_psql('postgres', "SELECT value IS NULL FROM test_rep WHERE id = 6;");
+is($result, q(t), "ALTER test_rep ALTER DROP NOT NULL replicated");
+
+# Test ALTER TABLE SET UNLOGGED
+$node_publisher->safe_psql('postgres', 'ALTER TABLE test_rep SET UNLOGGED;');
+$node_publisher->wait_for_catchup('mysub');
+$node_publisher->safe_psql('postgres', "INSERT INTO test_rep VALUES (7, 'data7', '7');");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_rep WHERE id = 7;");
+is($result, qq(0), 'ALTER test_rep SET UNLOGGED replicated');
+
+# Test ALTER TABLE SET LOGGED
+$node_publisher->safe_psql('postgres', 'ALTER TABLE test_rep SET LOGGED;');
+$node_publisher->wait_for_catchup('mysub');
+$node_publisher->safe_psql('postgres', "INSERT INTO test_rep VALUES (8, 'data8', '8');");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM test_rep WHERE id = 8;");
+is($result, qq(1), 'ALTER test_rep SET LOGGED replicated');
+
+# Test CREATE TABLE and DML changes
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (a int, b varchar);");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from pg_tables where tablename = 'tmp';");
+is($result, qq(1), 'CREATE tmp is replicated');
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp values (1, 'a')");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp values (2, 'b')");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from tmp;");
+is($result, qq(2), 'DML Changes to tmp are replicated');
+
+# Test CREATE TABLE INHERITS
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp2 (c3 int) INHERITS (tmp);");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp2 VALUES (1, 'a', 1);");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from pg_tables where tablename = 'tmp2';");
+is($result, qq(1), 'CREATE TABLE INHERITS is replicated');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from tmp2;");
+is($result, qq(1), 'inserting some data to inherited table replicated');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp2");
+
+# Test CREATE TABLE LIKE
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp3 (c3 int, LIKE tmp);");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp3 VALUES (1, 1, 'a');");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from pg_tables where tablename = 'tmp3';");
+is($result, qq(1), 'CREATE TABLE LIKE replicated');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from tmp3;");
+is($result, qq(1), 'insert some data to a table defined with LIKE replicated');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp3");
+
+# Test DROP TABLE
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp;");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from pg_tables where tablename = 'tmp';");
+is($result, qq(0), 'TABLE tmp is dropped');
+
+# Test CREATE UNLOGGED TABLE
+$node_publisher->safe_psql('postgres', "CREATE UNLOGGED TABLE tmp (id int);");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (1);");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from pg_tables where tablename = 'tmp';");
+is($result, qq(1), 'CREATE UNLOGGED TABLE is replicated correctly');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from tmp;");
+is($result, qq(0), 'inserting data to unlogged table is not replicated correctly');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp");
+
+# Test CREATE TABLE IF NOT EXISTS
+$node_publisher->safe_psql('postgres', "CREATE TABLE IF NOT EXISTS tmp (id int);");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (1);");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from pg_tables where tablename = 'tmp';");
+is($result, qq(1), 'CREATE TABLE IF NOT EXISTS replicated');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from tmp;");
+is($result, qq(1), 'inserting data to a table replicated');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp");
+
+# Test CREATE TABLE IF NOT EXISTS (check if we skip to create a table
+# when we have the table on the subscriber in advance, and if we succeed
+# in replicating changes.)
+$node_subscriber->safe_psql('postgres', "CREATE TABLE tmp (id int);");
+$node_publisher->safe_psql('postgres', "CREATE TABLE IF NOT EXISTS tmp (id int);");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (1);");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from tmp;");
+is($result, qq(1), 'CREATE TABLE IF NOT EXISTS replicated');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp");
+
+# Test CREATE TABLE IF NOT EXISTS (check if we skip to create a table
+# when we have the table on the publisher, but not on the subscriber.)
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (id int);");
+$node_publisher->safe_psql('postgres', "CREATE TABLE IF NOT EXISTS tmp (id int);");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (1);");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from tmp;");
+is($result, qq(1), 'CREATE TABLE IF NOT EXISTS replicated');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp");
+
+# Test CREATE TABLE with collate
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (name text COLLATE \"C\");");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES ('foo');");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT collation_name FROM information_schema.columns WHERE table_name = 'tmp';");
+is($result, qq(C), 'CREATE TABLE with collate replicated');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp");
+
+# Test CREATE TABLE with named constraint
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (id int CONSTRAINT \"must be bigger than 10\" CHECK (id > 10));");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->psql('postgres', "INSERT INTO tmp VALUES (1);",
+					   on_error_stop => 0,
+					   stderr => \$stderr,
+					   stdout => \$stdout);
+$stderr =~ /ERROR:  new row for relation "tmp" violates check constraint "must be bigger than 10"/
+  or die "failed to replicate named constraint at creating table";
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp;");
+
+# Test CREATE TABLE with various types of constraints.
+# NOT NULL constraint
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (id int, name text NOT NULL);");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->psql('postgres', "INSERT INTO tmp VALUES (1);",
+					   on_error_stop => 0,
+					   stderr => \$stderr,
+					   stdout => \$stdout);
+$stderr =~ /ERROR:  null value in column "name" of relation "tmp" violates not-null constraint/
+  or die "failed to replicate non null constraint at creating table";
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp;");
+
+# NULL constraint
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (id int, name text NULL);");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->safe_psql('postgres', "INSERT INTO tmp VALUES (1);");
+$result = $node_subscriber->safe_psql('postgres', "SELECT name IS NULL FROM tmp;");
+is($result, qq(t), "CREATE TABLE with NULL constraint replicated");
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp");
+
+# CHECK constraint
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (id int, product_ame text, price int CHECK (price > 0));");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->psql('postgres', "INSERT INTO tmp VALUES (1, 'foo', -100);",
+					   on_error_stop => 0,
+					   stderr => \$stderr,
+					   stdout => \$stdout);
+$stderr =~ /ERROR:  new row for relation "tmp" violates check constraint "tmp_price_check"/
+  or die "failed to replicate CHECK constraint";
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp;");
+
+# DEFAULT
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (id int, name text DEFAULT 'foo');");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->safe_psql('postgres', "INSERT INTO tmp VALUES (1);");
+$result = $node_subscriber->safe_psql('postgres', "SELECT name from tmp;");
+is($result, qq(foo), "CREATE TABLE with default value replicated");
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp");
+
+# UNIQUE constraint
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (id int UNIQUE);");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (1);");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->psql('postgres', "INSERT INTO tmp VALUES (1);",
+					   on_error_stop => 0,
+					   stderr => \$stderr,
+					   stdout => \$stdout);
+$stderr =~ /ERROR:  duplicate key value violates unique constraint "tmp_id_key"/
+  or die "failed to replicate constraint at creating table";
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp;");
+
+# PRIMARY KEY
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (id int PRIMARY KEY, name text);");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (1, 'foo');");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->psql('postgres', "INSERT INTO tmp VALUES (1, 'bar');",
+					   on_error_stop => 0,
+					   stderr => \$stderr,
+					   stdout => \$stdout);
+$stderr =~ /ERROR:  duplicate key value violates unique constraint "tmp_pkey"/
+  or die "failed to replicate primary key at creating table";
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp;");
+
+# EXCLUDE
+$node_publisher->safe_psql('postgres', "CREATE TABLE circles (c circle, EXCLUDE USING gist (c WITH &&));");
+$node_publisher->safe_psql('postgres', "INSERT INTO circles VALUES ('<(1, 1), 1>'::circle);");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->psql('postgres', "INSERT INTO circles VALUES ('<(1, 1), 1>'::circle);",
+					   on_error_stop => 0,
+					   stderr => \$stderr,
+					   stdout => \$stdout);
+$stderr =~ /ERROR:  conflicting key value violates exclusion constraint "circles_c_excl"/
+  or die "failed to replicate EXCLUDE at creating table";
+$node_publisher->safe_psql('postgres', "DROP TABLE circles");
+
+# REFERENCES
+$node_publisher->safe_psql('postgres', "CREATE TABLE product (id int PRIMARY KEY, name text);");
+$node_publisher->safe_psql('postgres', "INSERT INTO product VALUES (1, 'foo');");
+$node_publisher->safe_psql('postgres', "INSERT INTO product VALUES (2, 'bar');");
+$node_publisher->safe_psql('postgres', "CREATE TABLE orders (order_id int PRIMARY KEY, product_id int REFERENCES product (id))");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->psql('postgres', "INSERT INTO orders VALUES (1, 10)",
+					   on_error_stop => 0,
+					   stderr => \$stderr,
+					   stdout => \$stdout);
+$stderr =~ /ERROR:  insert or update on table "orders" violates foreign key constraint "orders_product_id_fkey"/
+  or die "failed to replicate REFERENCES at creating table";
+$node_publisher->safe_psql('postgres', "DROP TABLE orders");
+$node_publisher->safe_psql('postgres', "DROP TABLE product");
+
+# DEFERRABLE
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (id int PRIMARY KEY DEFERRABLE, name text);");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (1, 'foo');");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (2, 'bar');");
+$node_publisher->wait_for_catchup('mysub');
+# Quick check of deferrable clause
+$node_subscriber->safe_psql('postgres', "UPDATE tmp SET id = id + 1;");
+# Also, execute a test that should fail for INITIALLY IMMEDIATE(the default)
+$node_subscriber->psql('postgres', qq(
+BEGIN;
+UPDATE tmp SET id = id + 1;
+INSERT INTO tmp VALUES (3, 'foobar');
+DELETE FROM tmp WHERE id = 3;
+COMMIT;
+), on_error_stop => 0, stderr => \$stderr, stdout => \$stdout);
+$stderr =~ /ERROR:  duplicate key value violates unique constraint "tmp_pkey"/
+  or die "failed to replicate DEFERRABLE at creating table";
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp;");
+
+# NOT DEFERRABLE
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (id int PRIMARY KEY NOT DEFERRABLE, name text);");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (1, 'foo');");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (2, 'bar');");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->psql('postgres', "UPDATE tmp SET id = id + 1;",
+					   on_error_stop => 0,
+					   stderr => \$stderr,
+					   stdout => \$stdout);
+$stderr =~ /ERROR:  duplicate key value violates unique constraint "tmp_pkey"/
+  or die "failed to replicate NOT DEFERRABLE at creating table";
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp;");
+
+# DEFERRABLE and INITIALLY DEFERRED
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (id int PRIMARY KEY DEFERRABLE INITIALLY DEFERRED, name text);");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (1, 'foo');");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (2, 'bar');");
+$node_publisher->wait_for_catchup('mysub');
+# Quick check of deferrable clause
+$node_subscriber->safe_psql('postgres', "UPDATE tmp SET id = id + 1;");
+# Also, execute a test that should succeed for INITIALLY DEFERRED
+$node_subscriber->safe_psql('postgres', qq(
+BEGIN;
+UPDATE tmp SET id = id + 1;
+INSERT INTO tmp VALUES (3, 'foobar');
+DELETE FROM tmp WHERE id = 3;
+COMMIT;
+));
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp;");
+
+# Test CREATE TABLE with table constraint
+# We will set two checks and conduct two inserts that should fail respectively.
+$node_publisher->safe_psql('postgres',
+	"CREATE TABLE tmp (price int, discounted_price int, CHECK (discounted_price > 0 AND price > discounted_price));");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->psql('postgres', "INSERT INTO tmp VALUES (100, 0);",
+					   on_error_stop => 0,
+					   stderr => \$stderr,
+					   stdout => \$stdout);
+$stderr =~ /ERROR:  new row for relation "tmp" violates check constraint "tmp_check"/
+  or die "failed to replicate table constraint (first condition) at creating table";
+$node_subscriber->psql('postgres', "INSERT INTO tmp VALUES (50, 100);",
+					   on_error_stop => 0,
+					   stderr => \$stderr,
+					   stdout => \$stdout);
+$stderr =~ /ERROR:  new row for relation "tmp" violates check constraint "tmp_check"/
+  or die "failed to replicate table constraint (second condition) at creating table";
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp;");
+
+# Test CREATE TABLE WITH strorage_parameter
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (id int) WITH (fillfactor = 80);");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (1);");
+$node_publisher->wait_for_catchup('mysub');
+$node_subscriber->psql('postgres', "SELECT reloptions FROM pg_class WHERE relname = 'tmp';",
+					   on_error_stop => 0,
+					   stderr => \$stderr,
+					   stdout => \$stdout);
+$stdout =~ /{fillfactor=80}/
+  or die "failed to replicate storage option";
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from tmp;");
+is($result, qq(1), 'CREATE TABLE with storage_parameter replicated');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp;");
+
+# Test CREATE TABLE TABLESPACE (creating a tablespace is not replicated)
+# Prepare the directories for the publisher and subscriber first.
+my ($basedir, $tablespace_dir);
+
+$basedir = $node_publisher->basedir;
+$tablespace_dir = "$basedir/tblspc_pub";
+mkdir($tablespace_dir);
+$node_publisher->safe_psql('postgres', "CREATE TABLESPACE mytblspc LOCATION '$tablespace_dir';");
+$basedir = $node_subscriber->basedir;
+$tablespace_dir = "$basedir/tblspc_sub";
+mkdir ($tablespace_dir);
+$node_subscriber->safe_psql('postgres', "CREATE TABLESPACE mytblspc LOCATION '$tablespace_dir';");
+
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (id int) TABLESPACE mytblspc;");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (1);");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from tmp;");
+is($result, qq(1), 'CREATE TABLE TABLESPACE replicated');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp;");
+
+# Test CREATE TYPE
+$node_publisher->safe_psql('postgres', "CREATE TYPE mytype AS (id int, name text, age int);");
+$node_publisher->wait_for_catchup('mysub');
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp OF mytype;");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES (1, 'bar');");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT count(*) from tmp;");
+is($result, qq(1), 'CREATE TABLE OF replicated');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp");
+$node_publisher->safe_psql('postgres', "DROP TYPE mytype");
+
+# Test CREATE ENUM TYPE
+$node_publisher->safe_psql('postgres', "CREATE TYPE myenumtype AS ENUM ('new', 'open', 'closed');");
+$node_publisher->wait_for_catchup('mysub');
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (status myenumtype);");
+$node_publisher->safe_psql('postgres', "INSERT INTO tmp VALUES ('new');");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT * from tmp;");
+is($result, qq(new), 'CREATE TABLE OF replicated');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp");
+$node_publisher->safe_psql('postgres', "DROP TYPE myenumtype");
+
+# Test CREATE RANGE TYPE
+$node_publisher->safe_psql('postgres', "CREATE TYPE float8_range AS RANGE (subtype = float8, subtype_diff = float8mi);");
+$node_publisher->wait_for_catchup('mysub');
+$node_publisher->safe_psql('postgres', "CREATE TABLE tmp (val float8_range);");
+$node_publisher->safe_psql('postgres', "insert into tmp values(float8_range(-12.34, '1.111113e3'));");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT * from tmp;");
+is($result, qq([-12.34,1111.113\)), 'CREATE TABLE OF replicated');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp");
+$node_publisher->safe_psql('postgres', "DROP TYPE float8_range");
+
+# Test CREATE BASE DATA TYPE and use it in table definition
+$node_publisher->safe_psql('postgres', "
+CREATE TYPE int42;
+CREATE FUNCTION int42_in(cstring)
+   RETURNS int42
+   AS 'int4in'
+   LANGUAGE internal STRICT IMMUTABLE;
+CREATE FUNCTION int42_out(int42)
+   RETURNS cstring
+   AS 'int4out'
+   LANGUAGE internal STRICT IMMUTABLE;
+CREATE TYPE int42 (
+   internallength = 4,
+   input = int42_in,
+   output = int42_out,
+   alignment = int4,
+   default = 42,
+   passedbyvalue
+);
+CREATE TABLE tmp (f1 int42);
+INSERT INTO tmp DEFAULT VALUES;
+");
+$node_publisher->wait_for_catchup('mysub');
+$result = $node_subscriber->safe_psql('postgres', "SELECT * from tmp;");
+is($result, qq(42), 'CREATE TABLE OF replicated');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp");
+$node_publisher->safe_psql('postgres', "DROP TYPE int42 cascade");
+
+pass "DDL replication tests passed:";
+
+$node_subscriber->stop;
+$node_publisher->stop;
+
+done_testing();
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 4a31818..b745a9b 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -561,6 +561,7 @@ DefElemAction
 DefaultACLInfo
 DefineStmt
 DeleteStmt
+DeparsedCommandType
 DependencyGenerator
 DependencyGeneratorData
 DependencyType
@@ -1449,6 +1450,8 @@ LogicalDecodeBeginPrepareCB
 LogicalDecodeChangeCB
 LogicalDecodeCommitCB
 LogicalDecodeCommitPreparedCB
+LogicalDecodeDDLMessageCB
+LogicalDecodeStreamDDLMessageCB
 LogicalDecodeFilterByOriginCB
 LogicalDecodeFilterPrepareCB
 LogicalDecodeMessageCB
@@ -2305,6 +2308,8 @@ ReorderBufferChange
 ReorderBufferChangeType
 ReorderBufferCommitCB
 ReorderBufferCommitPreparedCB
+ReorderBufferDDLMessageCB
+ReorderBufferStreamDDLMessageCB
 ReorderBufferDiskChange
 ReorderBufferIterTXNEntry
 ReorderBufferIterTXNState
@@ -3607,6 +3612,7 @@ pthread_mutex_t
 pthread_once_t
 pthread_t
 ptrdiff_t
+publication_rel
 pull_var_clause_context
 pull_varattnos_context
 pull_varnos_context
-- 
1.8.3.1



  [application/octet-stream] v80-0007-Document-DDL-replication-and-DDL-deparser.patch (40.6K, 8-v80-0007-Document-DDL-replication-and-DDL-deparser.patch)
  download | inline diff:
From dbbc4dd5d342b548b1d6c0b957ca3fbf2a29d0e7 Mon Sep 17 00:00:00 2001
From: Ajin Cherian <ajinc@fast.au.fujitsu.com>
Date: Tue, 14 Mar 2023 00:00:02 -0400
Subject: [PATCH v80 7/8] Document DDL replication and DDL deparser.

---
 doc/src/sgml/logical-replication.sgml | 1057 +++++++++++++++++++++++++++++++++
 1 file changed, 1057 insertions(+)

diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 1bd5660..928e0ef 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -1437,6 +1437,1063 @@ test_sub=# SELECT * FROM t1 ORDER BY id;
 
  </sect1>
 
+ <sect1 id="logical-replication-ddl">
+  <title>DDL Replication</title>
+  <para>
+    Data Definition Commands (DDLs) can be replicated using logical replication.
+    While enabled this feature automatically replicates supported DDL commands
+    that are successfully executed on a publisher to a subscriber. This is
+    especially useful if you have lots schema changes over time that need replication.
+  </para>
+
+  <para>
+    For example, when enabled a CREATE TABLE command executed on the publisher gets
+    WAL-logged, and forwarded to the subscriber to replay; a subsequent "ALTER
+    SUBSCRIPTION ... REFRESH PUBLICATION" is run on the subscrier database so any
+    following DML changes on the new table can be replicated without a hitch.
+  </para>
+
+  <para>
+    DDL replication is disabled by default, it can be enabled at different levels
+    using the ddl PUBLICATION option. This option currently has two levels and are
+    only allowed to be set if the PUBLICATION is FOR ALL TABLES.
+  </para>
+
+  <itemizedlist>
+    <listitem>
+      <para>
+        all: this option enables replication of all supported DDL commands.
+      </para>
+    </listitem>
+
+    <listitem>
+      <para>
+        table: this option enables replication of Table DDL commands,
+        which include:
+        <itemizedlist>
+          <listitem>
+            <para>
+              CREATE/ALTER/DROP TABLE
+            </para>
+          </listitem>
+
+          <listitem>
+            <para>
+              CREATE TABLE AS
+            </para>
+          </listitem>
+
+        </itemizedlist>
+      </para>
+    </listitem>
+  </itemizedlist>
+
+  <sect2 id="ddl-replication-option-examples">
+    <title>Examples - Setup DDL Replication on the Publisher</title>
+
+    <para>
+      Create a new publication with all ddl replication enabled:
+<programlisting>
+CREATE PUBLICATION mypub FOR ALL TABLES with (ddl = 'all');
+</programlisting></para>
+
+    <para>
+      Enable table ddl replication for an existing Publication:
+<programlisting>
+ALTER PUBLICATION mypub SET (ddl = 'table');
+</programlisting></para>
+
+  </sect2>
+
+  <sect2 id="ddl-replication-supported-commands">
+    <title>Supported DDL commands</title>
+
+    <para>
+      The DDL commands supported for logical replication are listed in the following
+      matrix. Note that global commands can be executed at any database and are currently
+      not supported for replication, global commands include ROLE statements, Database
+      statements, TableSpace statements and some of the GrantStmt/RevokeStmt if the target
+      object is a global object.
+    </para>
+
+    <table id="ddl-replication-by-command-tag">
+      <title>DDL Replication Support by Command Tag</title>
+      <tgroup cols="3">
+        <colspec colname="col1" colwidth="2*"/>
+        <colspec colname="col2" colwidth="1*"/>
+        <colspec colname="col3" colwidth="1*"/>
+      <thead>
+       <row>
+        <entry>Command Tag</entry>
+        <entry>For Replication</entry>
+        <entry>Notes</entry>
+       </row>
+      </thead>
+      <tbody>
+       <row>
+        <entry align="left"><literal>ALTER AGGREGATE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER CAST</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER COLLATION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER CONVERSION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER DATABASE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER DEFAULT PRIVILEGES</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER DOMAIN</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER EVENT TRIGGER</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER EXTENSION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER FOREIGN DATA WRAPPER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER FOREIGN TABLE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER FUNCTION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER INDEX</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER LANGUAGE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER LARGE OBJECT</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER MATERIALIZED VIEW</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER OPERATOR</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER OPERATOR CLASS</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER OPERATOR FAMILY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER POLICY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER PROCEDURE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER PUBLICATION</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER ROLE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER ROUTINE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER RULER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER SCHEMA</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER SEQUENCE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER SERVER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER STATISTICS</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER SUBSCRIPTION</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER SYSTEM</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TABLE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TABLESPACE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TEXT SEARCH CONFIGURATION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TEXT SEARCH DICTIONARY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TEXT SEARCH PARSER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TEXT SEARCH TEMPLATE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TRANSFORM</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TRIGGER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER TYPE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER USER MAPPING</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ALTER VIEW</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ANALYZE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>BEGIN</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CALL</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CHECKPOINT</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CLOSE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CLOSE CURSOR</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CLOSE CURSOR ALL</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CLUSTER</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>COMMENT</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>COMMIT</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>COMMIT PREPARED</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>COPY</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>COPY FROM</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE ACCESS METHOD</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE AGGREGATE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE CAST</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE COLLATION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE CONSTRAINT</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE CONVERSION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE DATABASE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE DOMAIN</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE EVENT TRIGGER</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE EXTENSION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE FOREIGN DATA WRAPPER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE FOREIGN TABLE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE FUNCTION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE INDEX</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE LANGUAGE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE MATERIALIZED VIEW</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE OPERATOR</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE OPERATOR CLASS</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE OPERATOR FAMILY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE POLICY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE PROCEDURE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE PUBLICATION</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE ROLE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE RULE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE SCHEMA</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE SEQUENCE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE SERVER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE STATISTICS</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE SUBSCRIPTION</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TABLE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TABLE AS</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TABLESPACE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TEXT SEARCH CONFIGURATION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TEXT SEARCH DICTIONARY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TEXT SEARCH PARSER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TEXT SEARCH TEMPLATE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TRANSFORM</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TRIGGER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE TYPE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE USER MAPPING</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>CREATE VIEW</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DEALLOCATE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DEALLOCATE ALL</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DECLARE CURSOR</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DELETE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DISCARD</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DISCARD ALL</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DISCARD PLANS</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DISCARD SEQUENCES</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DISCARD TEMP</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DO</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP ACCESS METHOD</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP AGGREGATE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP CAST</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP COLLATION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP CONSTRAINT</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP CONVERSION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP DATABASE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP DOMAIN</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP EVENT TRIGGER</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP EXTENSION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP FOREIGN DATA WRAPPER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP FOREIGN TABLE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP FUNCTION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP INDEX</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP LANGUAGE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP MATERIALIZED VIEW</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP OPERATOR</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP OPERATOR CLASS</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP OPERATOR FAMILY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP OWNED</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP POLICY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP PROCEDURE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP PUBLICATION</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP ROLE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP ROUTINE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP RULE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP SCHEMA</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP SEQUENCE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP SERVER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP STATISTICS</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP SUBSCRIPTION</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TABLE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TABLESPACE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TEXT SEARCH CONFIGURATION</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TEXT SEARCH DICTIONARY</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TEXT SEARCH PARSER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TEXT SEARCH TEMPLATE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TRANSFORM</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TRIGGER</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP TYPE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP USER MAPPING</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>DROP VIEW</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>EXECUTE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>EXPLAIN</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>FETCH</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>GRANT</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>GRANT ROLE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>IMPORT FOREIGN SCHEMA</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>INSERT</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>LISTEN</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>LOAD</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>LOCK TABLE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>MERGE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>MOVE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>NOTIFY</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>PREPARE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>PREPARE TRANSACTION</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>REASSIGN OWNED</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>REFRESH MATERIALIZED VIEW</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>REINDEX</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>RELEASE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>RESET</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>REVOKE</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>REVOKE ROLE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ROLLBACK</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>ROLLBACK PREPARED</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>SAVEPOINT</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>SECURITY LABEL</literal></entry>
+        <entry align="center"><literal>X</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>SET</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>SET CONSTRAINTS</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>SHOW</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>START TRANSACTION</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>UNLISTEN</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>UPDATE</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+       <row>
+        <entry align="left"><literal>VACUUM</literal></entry>
+        <entry align="center"><literal>-</literal></entry>
+        <entry align="left"></entry>
+       </row>
+    </tbody>
+    </tgroup>
+    </table>
+  </sect2>
+
+  <sect2 id="ddl-replication-ddl-deparser">
+    <title>DDL Deparser</title>
+    <para>
+      The DDL deparser utility is invoked during the replication of DDLs. The DDL
+      deparser is capable of converting a DDL command into formatted JSON blob, with
+      the necessary information to reconstruct the DDL commands at the destination. The
+      benefit of using the deparser output compared to the original command string
+      includes:
+      <itemizedlist>
+        <listitem>
+          <para>
+            Every database object in the deparsed output is schema-qualified, so that
+            there are no ambiguities even in the face of search_path changes.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            The structured JSON and the formatted output makes it possible for
+            machine editing. This can be useful if the subscriber is on a different
+            PG version and has certain DDL syntax differences which need to be
+            resolved before apply.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+    </para>
+
+    <para>
+      The DDL deparser exposes two SQL functions:
+      <itemizedlist>
+        <listitem>
+          <para>
+            ddl_deparse_to_json: given a CollectedCommand from event trigger,
+            returns a JSON representation of it. The command is expanded fully
+            so that there are no ambiguities even in the face of search_path
+            changes.
+          </para>
+        </listitem>
+      </itemizedlist>
+
+      <itemizedlist>
+        <listitem>
+          <para>
+            ddl_deparse_expand_command: Expand JSON format DDL generated by
+            ddl_deparse_to_json to a plain DDL command.
+          </para>
+        </listitem>
+      </itemizedlist>
+    </para>
+  </sect2>
+
+ </sect1>
+
  <sect1 id="logical-replication-conflicts">
   <title>Conflicts</title>
 
-- 
1.8.3.1



  [application/octet-stream] v80-0008-Allow-replicated-objects-to-have-the-same-owner-.patch (59.1K, 9-v80-0008-Allow-replicated-objects-to-have-the-same-owner-.patch)
  download | inline diff:
From 8eeea13e195dcc2e64fa9ba99660cc30dafaea1e Mon Sep 17 00:00:00 2001
From: Ajin Cherian <ajinc@fast.au.fujitsu.com>
Date: Tue, 14 Mar 2023 00:08:34 -0400
Subject: [PATCH v80 8/8] Allow replicated objects to have the same owner from
 the  publisher. Specifically, the changes include:

1. Change event trigger functions to collect the current role in CollectedCommand.

2. Change Deparser function deparse_utility_command to encode owner role in the top-level
element such as {myowner:role_name, fmt:..., identity:...} of the deparsed jsonb output
for commands that create database objects. Also change function deparse_ddl_json_to_string
to retrieve the myowner element from a jsonb string.

3. Introduce a new subscription option match_ddl_owner: when turned on, the apply worker
will apply DDL messages in the role retrieved from the "myowner" field of the deparsed
jsonb string. The default value of match_ddl_owner is on.
---
 src/backend/catalog/pg_subscription.c          |   1 +
 src/backend/commands/ddl_deparse.c             |  86 ++++++++++++---
 src/backend/commands/ddl_json.c                |  25 ++++-
 src/backend/commands/event_trigger.c           |   6 ++
 src/backend/commands/subscriptioncmds.c        |  27 ++++-
 src/backend/replication/logical/ddltrigger.c   |   6 +-
 src/backend/replication/logical/worker.c       |  22 +++-
 src/bin/pg_dump/pg_dump.c                      |  16 ++-
 src/bin/pg_dump/pg_dump.h                      |   1 +
 src/bin/psql/describe.c                        |   8 +-
 src/include/catalog/pg_subscription.h          |   5 +
 src/include/tcop/ddl_deparse.h                 |   4 +-
 src/include/tcop/deparse_utility.h             |   1 +
 src/test/regress/expected/subscription.out     | 144 ++++++++++++-------------
 src/test/subscription/t/032_ddl_replication.pl |  17 +++
 15 files changed, 269 insertions(+), 100 deletions(-)

diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
index a56ae31..022aab0 100644
--- a/src/backend/catalog/pg_subscription.c
+++ b/src/backend/catalog/pg_subscription.c
@@ -71,6 +71,7 @@ GetSubscription(Oid subid, bool missing_ok)
 	sub->stream = subform->substream;
 	sub->twophasestate = subform->subtwophasestate;
 	sub->disableonerr = subform->subdisableonerr;
+	sub->matchddlowner = subform->submatchddlowner;
 
 	/* Get conninfo */
 	datum = SysCacheGetAttr(SUBSCRIPTIONOID,
diff --git a/src/backend/commands/ddl_deparse.c b/src/backend/commands/ddl_deparse.c
index 373aab7..d8d6851 100644
--- a/src/backend/commands/ddl_deparse.c
+++ b/src/backend/commands/ddl_deparse.c
@@ -172,7 +172,7 @@ static ObjElem *new_object_object(ObjTree *value);
 static ObjTree *new_objtree_VA(char *fmt, int numobjs,...);
 static ObjTree *new_objtree(char *fmt);
 static ObjElem *new_string_object(char *value);
-static JsonbValue *objtree_to_jsonb_rec(ObjTree *tree, JsonbParseState *state);
+static JsonbValue *objtree_to_jsonb_rec(ObjTree *tree, JsonbParseState *state, char *owner);
 static void pg_get_indexdef_detailed(Oid indexrelid,
 									 char **index_am,
 									 char **definition,
@@ -993,14 +993,39 @@ objtree_fmt_to_jsonb_element(JsonbParseState *state, ObjTree *tree)
 }
 
 /*
- * Create a JSONB representation from an ObjTree.
+ * Process the role string into the output parse state.
+ */
+static void
+role_to_jsonb_element(JsonbParseState *state, char *owner)
+{
+	JsonbValue	key;
+	JsonbValue	val;
+
+	if (owner == NULL)
+		return;
+
+	/* Push the key first */
+	key.type = jbvString;
+	key.val.string.val = "myowner";
+	key.val.string.len = strlen(key.val.string.val);
+	pushJsonbValue(&state, WJB_KEY, &key);
+
+	/* Then process the role string */
+	val.type = jbvString;
+	val.val.string.len = strlen(owner);
+	val.val.string.val = owner;
+	pushJsonbValue(&state, WJB_VALUE, &val);
+}
+
+/*
+ * Create a JSONB representation from an ObjTree and its owner (if given).
  */
 static Jsonb *
-objtree_to_jsonb(ObjTree *tree)
+objtree_to_jsonb(ObjTree *tree, char *owner)
 {
 	JsonbValue *value;
 
-	value = objtree_to_jsonb_rec(tree, NULL);
+	value = objtree_to_jsonb_rec(tree, NULL, owner);
 	return JsonbValueToJsonb(value);
 }
 
@@ -1052,7 +1077,7 @@ objtree_to_jsonb_element(JsonbParseState *state, ObjElem *object,
 
 		case ObjTypeObject:
 			/* Recursively add the object into the existing parse state */
-			objtree_to_jsonb_rec(object->value.object, state);
+			objtree_to_jsonb_rec(object->value.object, state, NULL);
 			break;
 
 		case ObjTypeArray:
@@ -1080,12 +1105,13 @@ objtree_to_jsonb_element(JsonbParseState *state, ObjElem *object,
  * Recursive helper for objtree_to_jsonb.
  */
 static JsonbValue *
-objtree_to_jsonb_rec(ObjTree *tree, JsonbParseState *state)
+objtree_to_jsonb_rec(ObjTree *tree, JsonbParseState *state, char *owner)
 {
 	slist_iter	iter;
 
 	pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
 
+	role_to_jsonb_element(state, owner);
 	objtree_fmt_to_jsonb_element(state, tree);
 
 	slist_foreach(iter, &tree->params)
@@ -3711,7 +3737,7 @@ deparse_drop_command(const char *objidentity, const char *objecttype,
 							"present", ObjTypeBool, behavior == DROP_CASCADE);
 	append_object_object(stmt, "%{cascade}s", tmp_obj);
 
-	jsonb = objtree_to_jsonb(stmt);
+	jsonb = objtree_to_jsonb(stmt, NULL /* Owner/role can be skipped for drop command */);
 	command = JsonbToCString(&str, &jsonb->root, JSONB_ESTIMATED_LEN);
 
 	return command;
@@ -9816,7 +9842,7 @@ deparse_AlterPublicationDropStmt(SQLDropObject *obj)
 	append_object_object(alterpub, "%{drop_object}s", drop_object);
 
 	initStringInfo(&str);
-	jsonb = objtree_to_jsonb(alterpub);
+	jsonb = objtree_to_jsonb(alterpub, NULL /* Owner/role can be skipped for drop command */);
 	command = JsonbToCString(&str, &jsonb->root, JSONB_ESTIMATED_LEN);
 
 	return command;
@@ -9828,7 +9854,7 @@ deparse_AlterPublicationDropStmt(SQLDropObject *obj)
  * This function should cover all cases handled in ProcessUtilitySlow.
  */
 static ObjTree *
-deparse_simple_command(CollectedCommand *cmd)
+deparse_simple_command(CollectedCommand *cmd, bool *include_owner)
 {
 	Oid			objectId;
 	Node	   *parsetree;
@@ -9845,64 +9871,83 @@ deparse_simple_command(CollectedCommand *cmd)
 	switch (nodeTag(parsetree))
 	{
 		case T_AlterCollationStmt:
+			*include_owner = false;
 			return deparse_AlterCollation(objectId, parsetree);
 
 		case T_AlterDomainStmt:
+			*include_owner = false;
 			return deparse_AlterDomainStmt(objectId, parsetree,
 										   cmd->d.simple.secondaryObject);
 
 		case T_AlterEnumStmt:
+			*include_owner = false;
 			return deparse_AlterEnumStmt(objectId, parsetree);
 
 		case T_AlterExtensionContentsStmt:
+			*include_owner = false;
 			return deparse_AlterExtensionContentsStmt(objectId, parsetree,
 													  cmd->d.simple.secondaryObject);
 
 		case T_AlterExtensionStmt:
+			*include_owner = false;
 			return deparse_AlterExtensionStmt(objectId, parsetree);
 
 		case T_AlterFdwStmt:
+			*include_owner = false;
 			return deparse_AlterFdwStmt(objectId, parsetree);
 
 		case T_AlterForeignServerStmt:
+			*include_owner = false;
 			return deparse_AlterForeignServerStmt(objectId, parsetree);
 
 		case T_AlterFunctionStmt:
+			*include_owner = false;
 			return deparse_AlterFunction(objectId, parsetree);
 
 		case T_AlterObjectDependsStmt:
+			*include_owner = false;
 			return deparse_AlterDependStmt(objectId, parsetree);
 
 		case T_AlterObjectSchemaStmt:
+			*include_owner = false;
 			return deparse_AlterObjectSchemaStmt(cmd->d.simple.address,
 												 parsetree,
 												 cmd->d.simple.secondaryObject);
 
 		case T_AlterOperatorStmt:
+			*include_owner = false;
 			return deparse_AlterOperatorStmt(objectId, parsetree);
 
 		case T_AlterOwnerStmt:
+			*include_owner = false;
 			return deparse_AlterOwnerStmt(cmd->d.simple.address, parsetree);
 
 		case T_AlterPolicyStmt:
+			*include_owner = false;
 			return deparse_AlterPolicyStmt(objectId, parsetree);
 
 		case T_AlterSeqStmt:
+			*include_owner = false;
 			return deparse_AlterSeqStmt(objectId, parsetree);
 
 		case T_AlterStatsStmt:
+			*include_owner = false;
 			return deparse_AlterStatsStmt(objectId, parsetree);
 
 		case T_AlterTSDictionaryStmt:
+			*include_owner = false;
 			return deparse_AlterTSDictionaryStmt(objectId, parsetree);
 
 		case T_AlterTypeStmt:
+			*include_owner = false;
 			return deparse_AlterTypeSetStmt(objectId, parsetree);
 
 		case T_AlterUserMappingStmt:
+			*include_owner = false;
 			return deparse_AlterUserMappingStmt(objectId, parsetree);
 
 		case T_CommentStmt:
+			*include_owner = false;
 			return deparse_CommentStmt(cmd->d.simple.address, parsetree);
 
 		case T_CompositeTypeStmt:
@@ -9982,9 +10027,11 @@ deparse_simple_command(CollectedCommand *cmd)
 			return deparse_IndexStmt(objectId, parsetree);
 
 		case T_RefreshMatViewStmt:
+			*include_owner = false;
 			return deparse_RefreshMatViewStmt(objectId, parsetree);
 
 		case T_RenameStmt:
+			*include_owner = false;
 			return deparse_RenameStmt(cmd->d.simple.address, parsetree);
 
 		case T_RuleStmt:
@@ -10009,9 +10056,15 @@ deparse_simple_command(CollectedCommand *cmd)
 
 /*
  * Workhorse to deparse a CollectedCommand.
+ *
+ * include_owner indicates if the owner/role of the command should be
+ * included in the deparsed Json output. It is set to false for any commands
+ * that don't CREATE database objects (ALTER commands for example), this is
+ * to avoid encoding and sending the owner to downstream for replay as it is
+ * unnecessary for such commands.
  */
 char *
-deparse_utility_command(CollectedCommand *cmd, bool verbose_mode)
+deparse_utility_command(CollectedCommand *cmd, bool include_owner, bool verbose_mode)
 {
 	OverrideSearchPath *overridePath;
 	MemoryContext oldcxt;
@@ -10052,30 +10105,36 @@ deparse_utility_command(CollectedCommand *cmd, bool verbose_mode)
 	switch (cmd->type)
 	{
 		case SCT_Simple:
-			tree = deparse_simple_command(cmd);
+			tree = deparse_simple_command(cmd, &include_owner);
 			break;
 		case SCT_AlterTable:
 			tree = deparse_AlterRelation(cmd);
+			include_owner = false;
 			break;
 		case SCT_Grant:
 			tree = deparse_GrantStmt(cmd);
+			include_owner = false;
 			break;
 		case SCT_CreateTableAs:
 			tree = deparse_CreateTableAsStmt(cmd);
 			break;
 		case SCT_AlterOpFamily:
+			include_owner = false;
 			tree = deparse_AlterOpFamily(cmd);
 			break;
 		case SCT_CreateOpClass:
 			tree = deparse_CreateOpClassStmt(cmd);
 			break;
 		case SCT_AlterDefaultPrivileges:
+			include_owner = false;
 			tree = deparse_AlterDefaultPrivilegesStmt(cmd);
 			break;
 		case SCT_AlterTSConfig:
+			include_owner = false;
 			tree = deparse_AlterTSConfigurationStmt(cmd);
 			break;
 		case SCT_SecurityLabel:
+			include_owner = false;
 			tree = deparse_SecLabelStmt(cmd);
 			break;
 		default:
@@ -10088,7 +10147,8 @@ deparse_utility_command(CollectedCommand *cmd, bool verbose_mode)
 	{
 		Jsonb	   *jsonb;
 
-		jsonb = objtree_to_jsonb(tree);
+		jsonb = include_owner ? objtree_to_jsonb(tree, cmd->role) :
+								objtree_to_jsonb(tree, NULL);
 		command = JsonbToCString(&str, &jsonb->root, JSONB_ESTIMATED_LEN);
 	}
 
@@ -10114,7 +10174,7 @@ ddl_deparse_to_json(PG_FUNCTION_ARGS)
 	CollectedCommand *cmd = (CollectedCommand *) PG_GETARG_POINTER(0);
 	char	   *command;
 
-	command = deparse_utility_command(cmd, true);
+	command = deparse_utility_command(cmd, false, true);
 
 	if (command)
 		PG_RETURN_TEXT_P(cstring_to_text(command));
diff --git a/src/backend/commands/ddl_json.c b/src/backend/commands/ddl_json.c
index 536c6d8..38b2d90 100644
--- a/src/backend/commands/ddl_json.c
+++ b/src/backend/commands/ddl_json.c
@@ -719,7 +719,7 @@ expand_jsonb_array(StringInfo buf, char *param,
  * Workhorse for ddl_deparse_expand_command.
  */
 char *
-deparse_ddl_json_to_string(char *json_str)
+deparse_ddl_json_to_string(char *json_str, char** owner)
 {
 	Datum		d;
 	Jsonb	   *jsonb;
@@ -730,6 +730,27 @@ deparse_ddl_json_to_string(char *json_str)
 	d = DirectFunctionCall1(jsonb_in, PointerGetDatum(json_str));
 	jsonb = (Jsonb *) DatumGetPointer(d);
 
+	if (owner != NULL)
+	{
+		const char *key = "myowner";
+		JsonbValue *value;
+
+		value = getKeyJsonValueFromContainer(&jsonb->root, key, strlen(key), NULL);
+		if (value)
+		{
+			char *str;
+
+			/* value->val.string.val may not be NULL terminated */
+			str = palloc(value->val.string.len + 1);
+			memcpy(str, value->val.string.val, value->val.string.len);
+			str[value->val.string.len] = '\0';
+			*owner = str;
+		}
+		else
+			/* myowner is not given in this jsonb, e.g. for Drop Commands */
+			*owner = NULL;
+	}
+
 	expand_fmt_recursive(buf, &jsonb->root);
 
 	return buf->data;
@@ -766,7 +787,7 @@ ddl_deparse_expand_command(PG_FUNCTION_ARGS)
 
 	json_str = text_to_cstring(json);
 
-	PG_RETURN_TEXT_P(cstring_to_text(deparse_ddl_json_to_string(json_str)));
+	PG_RETURN_TEXT_P(cstring_to_text(deparse_ddl_json_to_string(json_str, NULL)));
 }
 
 /*
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index b3f6849..275c400 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -882,6 +882,7 @@ EventTriggerTableInitWriteStart(Node *parsetree)
 
 	command->type = (stmt->objtype == OBJECT_TABLE) ? SCT_CreateTableAs : SCT_Simple;
 	command->in_extension = creating_extension;
+	command->role = GetUserNameFromId(GetUserId(), false);
 	command->d.ctas.address = InvalidObjectAddress;
 	command->d.ctas.real_create = NULL;
 	command->parsetree = copyObject(parsetree);
@@ -1627,6 +1628,7 @@ EventTriggerCollectSimpleCommand(ObjectAddress address,
 
 	command->type = SCT_Simple;
 	command->in_extension = creating_extension;
+	command->role = GetUserNameFromId(GetUserId(), false);
 
 	command->d.simple.address = address;
 	command->d.simple.secondaryObject = secondaryObject;
@@ -1663,6 +1665,7 @@ EventTriggerAlterTableStart(Node *parsetree)
 
 	command->type = SCT_AlterTable;
 	command->in_extension = creating_extension;
+	command->role = GetUserNameFromId(GetUserId(), false);
 
 	command->d.alterTable.classId = RelationRelationId;
 	command->d.alterTable.objectId = InvalidOid;
@@ -1930,6 +1933,7 @@ EventTriggerCollectGrant(InternalGrant *istmt)
 	command = palloc(sizeof(CollectedCommand));
 	command->type = SCT_Grant;
 	command->in_extension = creating_extension;
+	command->role = GetUserNameFromId(GetUserId(), false);
 	command->d.grant.istmt = icopy;
 	command->parsetree = NULL;
 
@@ -1961,6 +1965,7 @@ EventTriggerCollectAlterOpFam(AlterOpFamilyStmt *stmt, Oid opfamoid,
 	command = palloc(sizeof(CollectedCommand));
 	command->type = SCT_AlterOpFamily;
 	command->in_extension = creating_extension;
+	command->role = GetUserNameFromId(GetUserId(), false);
 	ObjectAddressSet(command->d.opfam.address,
 					 OperatorFamilyRelationId, opfamoid);
 	command->d.opfam.operators = operators;
@@ -2091,6 +2096,7 @@ EventTriggerCollectSecLabel(ObjectAddress address, char *provider,
 	command = palloc0(sizeof(CollectedCommand));
 	command->type = SCT_SecurityLabel;
 	command->in_extension = creating_extension;
+	command->role = GetUserNameFromId(GetUserId(), false);
 	command->d.seclabel.address = address;
 	command->d.seclabel.provider = provider;
 	command->parsetree = (Node *) copyObject(stmt);
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 464db6d..f7bb738 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -66,6 +66,7 @@
 #define SUBOPT_DISABLE_ON_ERR		0x00000400
 #define SUBOPT_LSN					0x00000800
 #define SUBOPT_ORIGIN				0x00001000
+#define SUBOPT_MATCH_DDL_OWNER		0x00002000
 
 /* check if the 'val' has 'bits' set */
 #define IsSet(val, bits)  (((val) & (bits)) == (bits))
@@ -89,6 +90,7 @@ typedef struct SubOpts
 	bool		twophase;
 	bool		disableonerr;
 	char	   *origin;
+	bool		matchddlowner;
 	XLogRecPtr	lsn;
 } SubOpts;
 
@@ -146,6 +148,8 @@ parse_subscription_options(ParseState *pstate, List *stmt_options,
 		opts->disableonerr = false;
 	if (IsSet(supported_opts, SUBOPT_ORIGIN))
 		opts->origin = pstrdup(LOGICALREP_ORIGIN_ANY);
+	if (IsSet(supported_opts, SUBOPT_MATCH_DDL_OWNER))
+		opts->matchddlowner = true;
 
 	/* Parse options */
 	foreach(lc, stmt_options)
@@ -324,6 +328,15 @@ parse_subscription_options(ParseState *pstate, List *stmt_options,
 			opts->specified_opts |= SUBOPT_LSN;
 			opts->lsn = lsn;
 		}
+		else if (IsSet(supported_opts, SUBOPT_MATCH_DDL_OWNER) &&
+				 strcmp(defel->defname, "match_ddl_owner") == 0)
+		{
+			if (IsSet(opts->specified_opts, SUBOPT_MATCH_DDL_OWNER))
+				errorConflictingDefElem(defel, pstate);
+
+			opts->specified_opts |= SUBOPT_MATCH_DDL_OWNER;
+			opts->matchddlowner = defGetBoolean(defel);
+		}
 		else
 			ereport(ERROR,
 					(errcode(ERRCODE_SYNTAX_ERROR),
@@ -560,7 +573,8 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
 					  SUBOPT_SLOT_NAME | SUBOPT_COPY_DATA |
 					  SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
 					  SUBOPT_STREAMING | SUBOPT_TWOPHASE_COMMIT |
-					  SUBOPT_DISABLE_ON_ERR | SUBOPT_ORIGIN);
+					  SUBOPT_DISABLE_ON_ERR | SUBOPT_ORIGIN |
+					  SUBOPT_MATCH_DDL_OWNER);
 	parse_subscription_options(pstate, stmt->options, supported_opts, &opts);
 
 	/*
@@ -649,6 +663,7 @@ CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt,
 		publicationListToArray(publications);
 	values[Anum_pg_subscription_suborigin - 1] =
 		CStringGetTextDatum(opts.origin);
+	values[Anum_pg_subscription_submatchddlowner - 1] = BoolGetDatum(opts.matchddlowner);
 
 	tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
 
@@ -1054,7 +1069,7 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
 				supported_opts = (SUBOPT_SLOT_NAME |
 								  SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
 								  SUBOPT_STREAMING | SUBOPT_DISABLE_ON_ERR |
-								  SUBOPT_ORIGIN);
+								  SUBOPT_ORIGIN | SUBOPT_MATCH_DDL_OWNER);
 
 				parse_subscription_options(pstate, stmt->options,
 										   supported_opts, &opts);
@@ -1118,6 +1133,14 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
 					replaces[Anum_pg_subscription_suborigin - 1] = true;
 				}
 
+				if (IsSet(opts.specified_opts, SUBOPT_MATCH_DDL_OWNER))
+				{
+					values[Anum_pg_subscription_submatchddlowner - 1]
+						= BoolGetDatum(opts.matchddlowner);
+					replaces[Anum_pg_subscription_submatchddlowner - 1]
+						= true;
+				}
+
 				update_tuple = true;
 				break;
 			}
diff --git a/src/backend/replication/logical/ddltrigger.c b/src/backend/replication/logical/ddltrigger.c
index d68a507..5ccfefe 100644
--- a/src/backend/replication/logical/ddltrigger.c
+++ b/src/backend/replication/logical/ddltrigger.c
@@ -122,7 +122,7 @@ publication_deparse_table_rewrite(PG_FUNCTION_ARGS)
 	if (relpersist != RELPERSISTENCE_TEMP)
 	{
 		/* Deparse the DDL command and WAL log it to allow decoding of the same. */
-		json_string = deparse_utility_command(cmd, false);
+		json_string = deparse_utility_command(cmd, true, false);
 
 		if (json_string != NULL)
 			LogLogicalDDLMessage("deparse", cmd->d.alterTable.objectId, DCT_TableAlter,
@@ -200,7 +200,7 @@ publication_deparse_ddl_command_end(PG_FUNCTION_ARGS)
 			 * Deparse the DDL command and WAL log it to allow decoding of the
 			 * same.
 			 */
-			json_string = deparse_utility_command(cmd, false);
+			json_string = deparse_utility_command(cmd, true, false);
 
 			if (json_string != NULL)
 				LogLogicalDDLMessage("deparse", relid, type, json_string,
@@ -355,7 +355,7 @@ publication_deparse_table_init_write(PG_FUNCTION_ARGS)
 		return PointerGetDatum(NULL);
 
 	/* Deparse the DDL command and WAL log it to allow decoding of the same. */
-	json_string = deparse_utility_command(cmd, false);
+	json_string = deparse_utility_command(cmd, true, false);
 
 	if (json_string != NULL)
 		LogLogicalDDLMessage("deparse", cmd->d.simple.address.objectId, DCT_SimpleCmd,
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index b9b652f..52aee31 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -3359,21 +3359,33 @@ apply_handle_ddl(StringInfo s)
 	const char *prefix = NULL;
 	char	   *message = NULL;
 	char	   *ddl_command;
+	char	   *owner;
 	Size		sz;
 	List	   *parsetree_list;
 	ListCell   *parsetree_item;
 	DestReceiver *receiver;
 	MemoryContext oldcontext;
 	const char *save_debug_query_string = debug_query_string;
+	int			save_nestlevel = 0;
 
 	message = logicalrep_read_ddl(s, &lsn, &prefix, &sz);
 
 	/* Make sure we are in a transaction command */
 	begin_replication_step();
 
-	ddl_command = deparse_ddl_json_to_string(message);
+	ddl_command = deparse_ddl_json_to_string(message, &owner);
 	debug_query_string = ddl_command;
 
+	if (MySubscription->matchddlowner && owner)
+	{
+		/*
+		 * Set the current role to the owner that executed the command on the
+		 * publication server.
+		 */
+		save_nestlevel = NewGUCNestLevel();
+		SetConfigOption("role", owner, PGC_INTERNAL, PGC_S_OVERRIDE);
+	}
+
 	/* DestNone for logical replication */
 	receiver = CreateDestReceiver(DestNone);
 	parsetree_list = pg_parse_query(ddl_command);
@@ -3471,6 +3483,14 @@ apply_handle_ddl(StringInfo s)
 		MemoryContextDelete(per_parsetree_context);
 	}
 
+	/*
+	 * Restore the GUC variables we set above.
+	 */
+	if (save_nestlevel > 0)
+	{
+		AtEOXact_GUC(true, save_nestlevel);
+	}
+
 	debug_query_string = save_debug_query_string;
 	end_replication_step();
 }
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 7ca878b..470f4a9 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -4535,6 +4535,7 @@ getSubscriptions(Archive *fout)
 	int			i_subsynccommit;
 	int			i_subpublications;
 	int			i_subbinary;
+	int			i_submatchddlowner;
 	int			i,
 				ntups;
 
@@ -4587,9 +4588,14 @@ getSubscriptions(Archive *fout)
 						  LOGICALREP_TWOPHASE_STATE_DISABLED);
 
 	if (fout->remoteVersion >= 160000)
-		appendPQExpBufferStr(query, " s.suborigin\n");
+		appendPQExpBufferStr(query,
+							 " s.suborigin,\n"
+							 " s.submatchddlowner\n");
 	else
-		appendPQExpBuffer(query, " '%s' AS suborigin\n", LOGICALREP_ORIGIN_ANY);
+		appendPQExpBuffer(query,
+						  " '%s' AS suborigin,\n"
+						  " false AS submatchddlowner\n",
+						  LOGICALREP_ORIGIN_ANY);
 
 	appendPQExpBufferStr(query,
 						 "FROM pg_subscription s\n"
@@ -4617,6 +4623,7 @@ getSubscriptions(Archive *fout)
 	i_subtwophasestate = PQfnumber(res, "subtwophasestate");
 	i_subdisableonerr = PQfnumber(res, "subdisableonerr");
 	i_suborigin = PQfnumber(res, "suborigin");
+	i_submatchddlowner = PQfnumber(res, "submatchddlowner");
 
 	subinfo = pg_malloc(ntups * sizeof(SubscriptionInfo));
 
@@ -4647,6 +4654,8 @@ getSubscriptions(Archive *fout)
 		subinfo[i].subdisableonerr =
 			pg_strdup(PQgetvalue(res, i, i_subdisableonerr));
 		subinfo[i].suborigin = pg_strdup(PQgetvalue(res, i, i_suborigin));
+		subinfo[i].submatchddlowner =
+			pg_strdup(PQgetvalue(res, i, i_submatchddlowner));
 
 		/* Decide whether we want to dump it */
 		selectDumpableObject(&(subinfo[i].dobj), fout);
@@ -4725,6 +4734,9 @@ dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo)
 	if (pg_strcasecmp(subinfo->suborigin, LOGICALREP_ORIGIN_ANY) != 0)
 		appendPQExpBuffer(query, ", origin = %s", subinfo->suborigin);
 
+	if (strcmp(subinfo->submatchddlowner, "f") == 0)
+		appendPQExpBufferStr(query, ", match_ddl_owner = false");
+
 	if (strcmp(subinfo->subsynccommit, "off") != 0)
 		appendPQExpBuffer(query, ", synchronous_commit = %s", fmtId(subinfo->subsynccommit));
 
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 3ea30ce..56451d6 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -663,6 +663,7 @@ typedef struct _SubscriptionInfo
 	char	   *suborigin;
 	char	   *subsynccommit;
 	char	   *subpublications;
+	char	   *submatchddlowner;
 } SubscriptionInfo;
 
 /*
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 48bf37a..69b37f2 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -6521,7 +6521,7 @@ describeSubscriptions(const char *pattern, bool verbose)
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 	static const bool translate_columns[] = {false, false, false, false,
-	false, false, false, false, false, false, false, false};
+	false, false, false, false, false, false, false, false, false};
 
 	if (pset.sversion < 100000)
 	{
@@ -6578,8 +6578,10 @@ describeSubscriptions(const char *pattern, bool verbose)
 
 		if (pset.sversion >= 160000)
 			appendPQExpBuffer(&buf,
-							  ", suborigin AS \"%s\"\n",
-							  gettext_noop("Origin"));
+							  ", suborigin AS \"%s\"\n"
+							  ", submatchddlowner AS \"%s\"\n",
+							  gettext_noop("Origin"),
+							  gettext_noop("Match DDL owner"));
 
 		appendPQExpBuffer(&buf,
 						  ",  subsynccommit AS \"%s\"\n"
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index b0f2a17..17af7c7 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -88,6 +88,9 @@ CATALOG(pg_subscription,6100,SubscriptionRelationId) BKI_SHARED_RELATION BKI_ROW
 	bool		subdisableonerr;	/* True if a worker error should cause the
 									 * subscription to be disabled */
 
+	bool		submatchddlowner;	/* True if replicated objects by DDL replication
+									 * should match the original owner on the publisher */
+
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
 	/* Connection string to the publisher */
 	text		subconninfo BKI_FORCE_NOT_NULL;
@@ -137,6 +140,8 @@ typedef struct Subscription
 	List	   *publications;	/* List of publication names to subscribe to */
 	char	   *origin;			/* Only publish data originating from the
 								 * specified origin */
+	bool		matchddlowner;  /* Indicates if replicated objects by DDL replication
+								 * should match the original owner on the publisher */
 } Subscription;
 
 /* Disallow streaming in-progress transactions. */
diff --git a/src/include/tcop/ddl_deparse.h b/src/include/tcop/ddl_deparse.h
index e261a3e..581a470 100644
--- a/src/include/tcop/ddl_deparse.h
+++ b/src/include/tcop/ddl_deparse.h
@@ -15,8 +15,8 @@
 #include "commands/event_trigger.h"
 #include "tcop/deparse_utility.h"
 
-extern char *deparse_utility_command(CollectedCommand *cmd, bool verbose_mode);
-extern char *deparse_ddl_json_to_string(char *jsonb);
+extern char *deparse_utility_command(CollectedCommand *cmd, bool include_owner, bool verbose_mode);
+extern char *deparse_ddl_json_to_string(char *jsonb, char** owner);
 extern char *deparse_drop_command(const char *objidentity, const char *objecttype,
 								  DropBehavior behavior);
 extern char * deparse_AlterPublicationDropStmt(SQLDropObject *obj);
diff --git a/src/include/tcop/deparse_utility.h b/src/include/tcop/deparse_utility.h
index fbd0976..cce3c07 100644
--- a/src/include/tcop/deparse_utility.h
+++ b/src/include/tcop/deparse_utility.h
@@ -49,6 +49,7 @@ typedef struct CollectedCommand
 	CollectedCommandType type;
 
 	bool		in_extension;
+	char	   *role;
 	Node	   *parsetree;
 
 	union
diff --git a/src/test/regress/expected/subscription.out b/src/test/regress/expected/subscription.out
index 3f99b14..af894f7 100644
--- a/src/test/regress/expected/subscription.out
+++ b/src/test/regress/expected/subscription.out
@@ -114,18 +114,18 @@ CREATE SUBSCRIPTION regress_testsub4 CONNECTION 'dbname=regress_doesnotexist' PU
 WARNING:  subscription was created, but is not connected
 HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
 \dRs+ regress_testsub4
-                                                                                         List of subscriptions
-       Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
-------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub4 | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | none   | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+       Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub4 | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | none   | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub4 SET (origin = any);
 \dRs+ regress_testsub4
-                                                                                         List of subscriptions
-       Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
-------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub4 | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+       Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub4 | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 DROP SUBSCRIPTION regress_testsub3;
@@ -143,10 +143,10 @@ ALTER SUBSCRIPTION regress_testsub CONNECTION 'foobar';
 ERROR:  invalid connection string syntax: missing "=" after "foobar" in connection info string
 
 \dRs+
-                                                                                         List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET PUBLICATION testpub2, testpub3 WITH (refresh = false);
@@ -163,10 +163,10 @@ ERROR:  unrecognized subscription parameter: "create_slot"
 -- ok
 ALTER SUBSCRIPTION regress_testsub SKIP (lsn = '0/12345');
 \dRs+
-                                                                                             List of subscriptions
-      Name       |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |           Conninfo           | Skip LSN 
------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+--------------------+------------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub2,testpub3} | f      | off       | d                | f                | any    | off                | dbname=regress_doesnotexist2 | 0/12345
+                                                                                                      List of subscriptions
+      Name       |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |           Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+------------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub2,testpub3} | f      | off       | d                | f                | any    | t               | off                | dbname=regress_doesnotexist2 | 0/12345
 (1 row)
 
 -- ok - with lsn = NONE
@@ -175,10 +175,10 @@ ALTER SUBSCRIPTION regress_testsub SKIP (lsn = NONE);
 ALTER SUBSCRIPTION regress_testsub SKIP (lsn = '0/0');
 ERROR:  invalid WAL location (LSN): 0/0
 \dRs+
-                                                                                             List of subscriptions
-      Name       |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |           Conninfo           | Skip LSN 
------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+--------------------+------------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub2,testpub3} | f      | off       | d                | f                | any    | off                | dbname=regress_doesnotexist2 | 0/0
+                                                                                                      List of subscriptions
+      Name       |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |           Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+------------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub2,testpub3} | f      | off       | d                | f                | any    | t               | off                | dbname=regress_doesnotexist2 | 0/0
 (1 row)
 
 BEGIN;
@@ -210,10 +210,10 @@ ALTER SUBSCRIPTION regress_testsub_foo SET (synchronous_commit = foobar);
 ERROR:  invalid value for parameter "synchronous_commit": "foobar"
 HINT:  Available values: local, remote_write, remote_apply, on, off.
 \dRs+
-                                                                                               List of subscriptions
-        Name         |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |           Conninfo           | Skip LSN 
----------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+--------------------+------------------------------+----------
- regress_testsub_foo | regress_subscription_user | f       | {testpub2,testpub3} | f      | off       | d                | f                | any    | local              | dbname=regress_doesnotexist2 | 0/0
+                                                                                                        List of subscriptions
+        Name         |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |           Conninfo           | Skip LSN 
+---------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+------------------------------+----------
+ regress_testsub_foo | regress_subscription_user | f       | {testpub2,testpub3} | f      | off       | d                | f                | any    | t               | local              | dbname=regress_doesnotexist2 | 0/0
 (1 row)
 
 -- rename back to keep the rest simple
@@ -247,19 +247,19 @@ CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUB
 WARNING:  subscription was created, but is not connected
 HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
 \dRs+
-                                                                                         List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | t      | off       | d                | f                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | t      | off       | d                | f                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (binary = false);
 ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
 \dRs+
-                                                                                         List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 DROP SUBSCRIPTION regress_testsub;
@@ -271,27 +271,27 @@ CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUB
 WARNING:  subscription was created, but is not connected
 HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
 \dRs+
-                                                                                         List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | on        | d                | f                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | on        | d                | f                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (streaming = parallel);
 \dRs+
-                                                                                         List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (streaming = false);
 ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
 \dRs+
-                                                                                         List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 -- fail - publication already exists
@@ -306,10 +306,10 @@ ALTER SUBSCRIPTION regress_testsub ADD PUBLICATION testpub1, testpub2 WITH (refr
 ALTER SUBSCRIPTION regress_testsub ADD PUBLICATION testpub1, testpub2 WITH (refresh = false);
 ERROR:  publication "testpub1" is already in subscription "regress_testsub"
 \dRs+
-                                                                                                 List of subscriptions
-      Name       |           Owner           | Enabled |         Publication         | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-----------------------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub,testpub1,testpub2} | f      | off       | d                | f                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                          List of subscriptions
+      Name       |           Owner           | Enabled |         Publication         | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+-----------------------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub,testpub1,testpub2} | f      | off       | d                | f                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 -- fail - publication used more than once
@@ -324,10 +324,10 @@ ERROR:  publication "testpub3" is not in subscription "regress_testsub"
 -- ok - delete publications
 ALTER SUBSCRIPTION regress_testsub DROP PUBLICATION testpub1, testpub2 WITH (refresh = false);
 \dRs+
-                                                                                         List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 DROP SUBSCRIPTION regress_testsub;
@@ -363,10 +363,10 @@ CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUB
 WARNING:  subscription was created, but is not connected
 HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
 \dRs+
-                                                                                         List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | p                | f                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | p                | f                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 --fail - alter of two_phase option not supported.
@@ -375,10 +375,10 @@ ERROR:  unrecognized subscription parameter: "two_phase"
 -- but can alter streaming when two_phase enabled
 ALTER SUBSCRIPTION regress_testsub SET (streaming = true);
 \dRs+
-                                                                                         List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | on        | p                | f                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | on        | p                | f                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
@@ -388,10 +388,10 @@ CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUB
 WARNING:  subscription was created, but is not connected
 HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
 \dRs+
-                                                                                         List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | on        | p                | f                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | on        | p                | f                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
@@ -404,18 +404,18 @@ CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUB
 WARNING:  subscription was created, but is not connected
 HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
 \dRs+
-                                                                                         List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (disable_on_error = true);
 \dRs+
-                                                                                         List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | t                | any    | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                  List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Match DDL owner | Synchronous commit |          Conninfo           | Skip LSN 
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-----------------+--------------------+-----------------------------+----------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | t                | any    | t               | off                | dbname=regress_doesnotexist | 0/0
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
diff --git a/src/test/subscription/t/032_ddl_replication.pl b/src/test/subscription/t/032_ddl_replication.pl
index 4bc4ff2..902d203 100644
--- a/src/test/subscription/t/032_ddl_replication.pl
+++ b/src/test/subscription/t/032_ddl_replication.pl
@@ -457,6 +457,23 @@ is($result, qq(42), 'CREATE TABLE OF replicated');
 $node_publisher->safe_psql('postgres', "DROP TABLE tmp");
 $node_publisher->safe_psql('postgres', "DROP TYPE int42 cascade");
 
+# Test owner of replicated table on subscriber matches the owner on publisher when
+# the match_ddl_owner subscription option is enabled
+$node_publisher->safe_psql('postgres', "CREATE ROLE ddl_replication_user LOGIN SUPERUSER;");
+
+$node_subscriber->safe_psql('postgres', "CREATE ROLE ddl_replication_user LOGIN SUPERUSER;");
+$node_subscriber->safe_psql('postgres', "ALTER SUBSCRIPTION mysub SET (match_ddl_owner = true);");
+
+$node_publisher->safe_psql('postgres', "SET SESSION AUTHORIZATION 'ddl_replication_user'; CREATE TABLE tmp (a int, b varchar);");
+$node_publisher->wait_for_catchup('mysub');
+
+$result = $node_subscriber->safe_psql('postgres', "SELECT tableowner from pg_catalog.pg_tables where tablename = 'tmp';");
+is($result, qq(ddl_replication_user), 'Owner of tmp is ddl_replication_user');
+$node_publisher->safe_psql('postgres', "DROP TABLE tmp");
+# reset match_ddl_owner
+$node_subscriber->safe_psql('postgres', "ALTER SUBSCRIPTION mysub SET (match_ddl_owner = false);");
+
+
 pass "DDL replication tests passed:";
 
 $node_subscriber->stop;
-- 
1.8.3.1



reply

Reply instructions:

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

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

  To: pgsql-general@postgresql.org
  Cc: itsajin@gmail.com, zhengli10@gmail.com, runqidev@gmail.com, vignesh21@gmail.com, smithpb2250@gmail.com, ggysxcq@gmail.com, dilipbalaut@gmail.com, alvherre@alvh.no-ip.org, houzj.fnst@fujitsu.com, amit.kapila16@gmail.com, sawada.mshk@gmail.com, japinli@hotmail.com, rajesh.rs0541@gmail.com, pgsql-hackers@lists.postgresql.org
  Subject: Re: Support logical replication of DDLs
  In-Reply-To: <CAFPTHDaaewvYUznZD1YjUQnvHycgvgMKNK4w=V8Q-8MKTpVDrw@mail.gmail.com>

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

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