On Tue, Jul 26, 2022 at 01:00:41PM +0000, houzj.f...@fujitsu.com wrote:
> Thanks for the suggestion. I have removed the default and found some missed
> subcommands in 0003 patch. Attach the new version patch here
> (The 0001 and 0002 is unchanged).

I have reviewed what you have here, and I found that the change is too
timid, with a coverage of 32% for test_ddl_deparse.  Attached is an
updated patch, that provides coverage for the most obvious cases I
could see in tablecmds.c, bringing the coverage to 64% here.

Some cases are straight-forward, like the four cases for RLS or the
three subcases for RelOptions (where we'd better return an address
even if doing doing for the replace case).  Some cases that I have not
included here would need more thoughts, like constraint validation and
drop or even SET ACCESS METHOD, so I have discarded for now all the
cases where we don't (or cannot) report properly an ObjectAddress
yet.

There is also a fancy case with DROP COLUMN, where we get an
ObjectAddress referring to the column already dropped, aka roughly a 
".....pg_dropped.N.....", and it is not like we should switch to only
a reference of the table here because we want to know the name of the
column dropped.  I have discarded this last one as well, for now.

All that could be expanded in more patches (triggers are an easy one),
but what I have here is already a good cut.
--
Michael
From a386086af62c661f0e41a8789266e0fc13579d83 Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@paquier.xyz>
Date: Sat, 30 Jul 2022 15:54:38 +0900
Subject: [PATCH v4] Improve coverage for test_ddl_deparse

---
 src/backend/commands/tablecmds.c              |  56 +++++---
 .../test_ddl_deparse/expected/alter_table.out | 122 +++++++++++++++++-
 .../expected/create_table.out                 |   8 +-
 .../test_ddl_deparse/expected/create_view.out |   2 +-
 .../expected/test_ddl_deparse.out             |   4 +-
 .../test_ddl_deparse/sql/alter_table.sql      |  54 ++++++++
 .../test_ddl_deparse/sql/test_ddl_deparse.sql |   4 +-
 .../test_ddl_deparse--1.0.sql                 |   6 +-
 .../test_ddl_deparse/test_ddl_deparse.c       |  73 +++++++++--
 9 files changed, 279 insertions(+), 50 deletions(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index e7aef2f6b0..ef95332d95 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -576,7 +576,7 @@ static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel,
 								const char *tablespacename, LOCKMODE lockmode);
 static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode);
 static void ATExecSetTableSpaceNoStorage(Relation rel, Oid newTableSpace);
-static void ATExecSetRelOptions(Relation rel, List *defList,
+static ObjectAddress ATExecSetRelOptions(Relation rel, List *defList,
 								AlterTableType operation,
 								LOCKMODE lockmode);
 static void ATExecEnableDisableTrigger(Relation rel, const char *trigname,
@@ -592,8 +592,8 @@ static ObjectAddress ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKM
 static void ATExecDropOf(Relation rel, LOCKMODE lockmode);
 static void ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode);
 static void ATExecGenericOptions(Relation rel, List *options);
-static void ATExecSetRowSecurity(Relation rel, bool rls);
-static void ATExecForceNoForceRowSecurity(Relation rel, bool force_rls);
+static ObjectAddress ATExecSetRowSecurity(Relation rel, bool rls);
+static ObjectAddress ATExecForceNoForceRowSecurity(Relation rel, bool force_rls);
 static ObjectAddress ATExecSetCompression(Relation rel,
 										  const char *column, Node *newValue, LOCKMODE lockmode);
 
@@ -5115,7 +5115,7 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
 		case AT_SetRelOptions:	/* SET (...) */
 		case AT_ResetRelOptions:	/* RESET (...) */
 		case AT_ReplaceRelOptions:	/* replace entire option list */
-			ATExecSetRelOptions(rel, (List *) cmd->def, cmd->subtype, lockmode);
+			address = ATExecSetRelOptions(rel, (List *) cmd->def, cmd->subtype, lockmode);
 			break;
 		case AT_EnableTrig:		/* ENABLE TRIGGER name */
 			ATExecEnableDisableTrigger(rel, cmd->name,
@@ -5183,16 +5183,16 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
 			ATExecReplicaIdentity(rel, (ReplicaIdentityStmt *) cmd->def, lockmode);
 			break;
 		case AT_EnableRowSecurity:
-			ATExecSetRowSecurity(rel, true);
+			address = ATExecSetRowSecurity(rel, true);
 			break;
 		case AT_DisableRowSecurity:
-			ATExecSetRowSecurity(rel, false);
+			address = ATExecSetRowSecurity(rel, false);
 			break;
 		case AT_ForceRowSecurity:
-			ATExecForceNoForceRowSecurity(rel, true);
+			address = ATExecForceNoForceRowSecurity(rel, true);
 			break;
 		case AT_NoForceRowSecurity:
-			ATExecForceNoForceRowSecurity(rel, false);
+			address = ATExecForceNoForceRowSecurity(rel, false);
 			break;
 		case AT_GenericOptions:
 			ATExecGenericOptions(rel, (List *) cmd->def);
@@ -5202,11 +5202,11 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
 									  cur_pass, context);
 			Assert(cmd != NULL);
 			if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
-				ATExecAttachPartition(wqueue, rel, (PartitionCmd *) cmd->def,
-									  context);
+				address = ATExecAttachPartition(wqueue, rel, (PartitionCmd *) cmd->def,
+												context);
 			else
-				ATExecAttachPartitionIdx(wqueue, rel,
-										 ((PartitionCmd *) cmd->def)->name);
+				address = ATExecAttachPartitionIdx(wqueue, rel,
+												   ((PartitionCmd *) cmd->def)->name);
 			break;
 		case AT_DetachPartition:
 			cmd = ATParseTransformCmd(wqueue, tab, rel, cmd, false, lockmode,
@@ -5214,12 +5214,12 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab,
 			Assert(cmd != NULL);
 			/* ATPrepCmd ensures it must be a table */
 			Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
-			ATExecDetachPartition(wqueue, tab, rel,
-								  ((PartitionCmd *) cmd->def)->name,
-								  ((PartitionCmd *) cmd->def)->concurrent);
+			address = ATExecDetachPartition(wqueue, tab, rel,
+											((PartitionCmd *) cmd->def)->name,
+											((PartitionCmd *) cmd->def)->concurrent);
 			break;
 		case AT_DetachPartitionFinalize:
-			ATExecDetachPartitionFinalize(rel, ((PartitionCmd *) cmd->def)->name);
+			address = ATExecDetachPartitionFinalize(rel, ((PartitionCmd *) cmd->def)->name);
 			break;
 		default:				/* oops */
 			elog(ERROR, "unrecognized alter table type: %d",
@@ -14102,7 +14102,7 @@ ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, const char *tablespacen
 /*
  * Set, reset, or replace reloptions.
  */
-static void
+static ObjectAddress
 ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 					LOCKMODE lockmode)
 {
@@ -14117,9 +14117,13 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 	bool		repl_null[Natts_pg_class];
 	bool		repl_repl[Natts_pg_class];
 	static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
+	ObjectAddress address;
 
 	if (defList == NIL && operation != AT_ReplaceRelOptions)
-		return;					/* nothing to do */
+	{
+		ObjectAddressSet(address, RelationRelationId, RelationGetRelid(rel));
+		return address;					/* nothing to do */
+	}
 
 	pgclass = table_open(RelationRelationId, RowExclusiveLock);
 
@@ -14298,7 +14302,9 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 		table_close(toastrel, NoLock);
 	}
 
+	ObjectAddressSet(address, RelationRelationId, RelationGetRelid(rel));
 	table_close(pgclass, RowExclusiveLock);
+	return address;
 }
 
 /*
@@ -15992,12 +15998,13 @@ ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode
 /*
  * ALTER TABLE ENABLE/DISABLE ROW LEVEL SECURITY
  */
-static void
+static ObjectAddress
 ATExecSetRowSecurity(Relation rel, bool rls)
 {
 	Relation	pg_class;
 	Oid			relid;
 	HeapTuple	tuple;
+	ObjectAddress address;
 
 	relid = RelationGetRelid(rel);
 
@@ -16012,19 +16019,24 @@ ATExecSetRowSecurity(Relation rel, bool rls)
 	((Form_pg_class) GETSTRUCT(tuple))->relrowsecurity = rls;
 	CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
 
+	ObjectAddressSet(address, RelationRelationId, relid);
+
 	table_close(pg_class, RowExclusiveLock);
 	heap_freetuple(tuple);
+
+	return address;
 }
 
 /*
  * ALTER TABLE FORCE/NO FORCE ROW LEVEL SECURITY
  */
-static void
+static ObjectAddress
 ATExecForceNoForceRowSecurity(Relation rel, bool force_rls)
 {
 	Relation	pg_class;
 	Oid			relid;
 	HeapTuple	tuple;
+	ObjectAddress address;
 
 	relid = RelationGetRelid(rel);
 
@@ -16038,8 +16050,12 @@ ATExecForceNoForceRowSecurity(Relation rel, bool force_rls)
 	((Form_pg_class) GETSTRUCT(tuple))->relforcerowsecurity = force_rls;
 	CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
 
+	ObjectAddressSet(address, RelationRelationId, relid);
+
 	table_close(pg_class, RowExclusiveLock);
 	heap_freetuple(tuple);
+
+	return address;
 }
 
 /*
diff --git a/src/test/modules/test_ddl_deparse/expected/alter_table.out b/src/test/modules/test_ddl_deparse/expected/alter_table.out
index 141060fbdc..14151fe021 100644
--- a/src/test/modules/test_ddl_deparse/expected/alter_table.out
+++ b/src/test/modules/test_ddl_deparse/expected/alter_table.out
@@ -2,6 +2,18 @@ CREATE TABLE parent (
 	a int
 );
 NOTICE:  DDL test: type simple, tag CREATE TABLE
+ALTER TABLE parent SET (fillfactor = 50);
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type SET RELOPTIONS desc table parent
+ALTER TABLE parent RESET (fillfactor);
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type RESET RELOPTIONS desc table parent
+CREATE INDEX parent_index ON parent(a);
+NOTICE:  DDL test: type simple, tag CREATE INDEX
+ALTER TABLE parent CLUSTER ON parent_index;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type CLUSTER desc index parent_index
+DROP INDEX parent_index;
 CREATE TABLE child () INHERITS (parent);
 NOTICE:  DDL test: type simple, tag CREATE TABLE
 CREATE TABLE grandchild () INHERITS (child);
@@ -9,21 +21,119 @@ NOTICE:  DDL test: type simple, tag CREATE TABLE
 ALTER TABLE parent ADD COLUMN b serial;
 NOTICE:  DDL test: type simple, tag CREATE SEQUENCE
 NOTICE:  DDL test: type alter table, tag ALTER TABLE
-NOTICE:    subcommand: ADD COLUMN (and recurse)
+NOTICE:    subcommand: type ADD COLUMN (and recurse) desc column b of table parent
 NOTICE:  DDL test: type simple, tag ALTER SEQUENCE
 ALTER TABLE parent RENAME COLUMN b TO c;
 NOTICE:  DDL test: type simple, tag ALTER TABLE
-ALTER TABLE parent ADD CONSTRAINT a_pos CHECK (a > 0);
+-- Constraint, no recursion
+ALTER TABLE ONLY grandchild ADD CONSTRAINT a_pos CHECK (a > 0);
 NOTICE:  DDL test: type alter table, tag ALTER TABLE
-NOTICE:    subcommand: ADD CONSTRAINT (and recurse)
+NOTICE:    subcommand: type ADD CONSTRAINT desc constraint a_pos on table grandchild
+-- Constraint, with recursion
+ALTER TABLE parent ADD CONSTRAINT a_pos CHECK (a > 0);
+NOTICE:  merging constraint "a_pos" with inherited definition
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type ADD CONSTRAINT (and recurse) desc constraint a_pos on table parent
 CREATE TABLE part (
 	a int
 ) PARTITION BY RANGE (a);
 NOTICE:  DDL test: type simple, tag CREATE TABLE
 CREATE TABLE part1 PARTITION OF part FOR VALUES FROM (1) to (100);
 NOTICE:  DDL test: type simple, tag CREATE TABLE
+CREATE TABLE part2 (a int);
+NOTICE:  DDL test: type simple, tag CREATE TABLE
+ALTER TABLE part ATTACH PARTITION part2 FOR VALUES FROM (101) to (200);
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type ATTACH PARTITION desc table part2
+ALTER TABLE part DETACH PARTITION part2;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type DETACH PARTITION desc table part2
+DROP TABLE part2;
 ALTER TABLE part ADD PRIMARY KEY (a);
 NOTICE:  DDL test: type alter table, tag ALTER TABLE
-NOTICE:    subcommand: SET NOT NULL
-NOTICE:    subcommand: SET NOT NULL
-NOTICE:    subcommand: ADD INDEX
+NOTICE:    subcommand: type SET NOT NULL desc column a of table part
+NOTICE:    subcommand: type SET NOT NULL desc column a of table part1
+NOTICE:    subcommand: type ADD INDEX desc index part_pkey
+ALTER TABLE parent ALTER COLUMN a SET NOT NULL;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type SET NOT NULL desc column a of table parent
+NOTICE:    subcommand: type SET NOT NULL desc column a of table child
+NOTICE:    subcommand: type SET NOT NULL desc column a of table grandchild
+ALTER TABLE parent ALTER COLUMN a DROP NOT NULL;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type DROP NOT NULL desc column a of table parent
+NOTICE:    subcommand: type DROP NOT NULL desc column a of table child
+NOTICE:    subcommand: type DROP NOT NULL desc column a of table grandchild
+ALTER TABLE parent ALTER COLUMN a SET NOT NULL;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type SET NOT NULL desc column a of table parent
+NOTICE:    subcommand: type SET NOT NULL desc column a of table child
+NOTICE:    subcommand: type SET NOT NULL desc column a of table grandchild
+ALTER TABLE parent ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
+NOTICE:  DDL test: type simple, tag CREATE SEQUENCE
+NOTICE:  DDL test: type simple, tag ALTER SEQUENCE
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type ADD IDENTITY desc column a of table parent
+ALTER TABLE parent ALTER COLUMN a SET GENERATED BY DEFAULT;
+NOTICE:  DDL test: type simple, tag ALTER SEQUENCE
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type SET IDENTITY desc column a of table parent
+ALTER TABLE parent ALTER COLUMN a DROP IDENTITY;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type DROP IDENTITY desc column a of table parent
+ALTER TABLE parent ALTER COLUMN a SET STATISTICS 100;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type SET STATS desc column a of table parent
+NOTICE:    subcommand: type SET STATS desc column a of table child
+NOTICE:    subcommand: type SET STATS desc column a of table grandchild
+ALTER TABLE parent ALTER COLUMN a SET STORAGE PLAIN;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type SET STORAGE desc column a of table parent
+NOTICE:    subcommand: type SET STORAGE desc column a of table child
+NOTICE:    subcommand: type SET STORAGE desc column a of table grandchild
+ALTER TABLE parent ENABLE ROW LEVEL SECURITY;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type ENABLE ROW SECURITY desc table parent
+ALTER TABLE parent NO FORCE ROW LEVEL SECURITY;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type NO FORCE ROW SECURITY desc table parent
+ALTER TABLE parent FORCE ROW LEVEL SECURITY;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type FORCE ROW SECURITY desc table parent
+ALTER TABLE parent DISABLE ROW LEVEL SECURITY;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type DISABLE ROW SECURITY desc table parent
+CREATE STATISTICS parent_stat (dependencies) ON a, c FROM parent;
+NOTICE:  DDL test: type simple, tag CREATE STATISTICS
+ALTER TABLE parent ALTER COLUMN c TYPE numeric;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type ALTER COLUMN SET TYPE desc column c of table parent
+NOTICE:    subcommand: type ALTER COLUMN SET TYPE desc column c of table child
+NOTICE:    subcommand: type ALTER COLUMN SET TYPE desc column c of table grandchild
+NOTICE:    subcommand: type (re) ADD STATS desc statistics object parent_stat
+ALTER TABLE parent ALTER COLUMN c SET DEFAULT 0;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type ALTER COLUMN SET DEFAULT desc column c of table parent
+NOTICE:    subcommand: type ALTER COLUMN SET DEFAULT desc column c of table child
+NOTICE:    subcommand: type ALTER COLUMN SET DEFAULT desc column c of table grandchild
+CREATE TABLE tbl (
+	a int generated always as (b::int * 2) stored,
+	b text
+);
+NOTICE:  DDL test: type simple, tag CREATE TABLE
+ALTER TABLE tbl ALTER COLUMN a DROP EXPRESSION;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type DROP EXPRESSION desc column a of table tbl
+ALTER TABLE tbl ALTER COLUMN b SET COMPRESSION pglz;
+NOTICE:  DDL test: type alter table, tag ALTER TABLE
+NOTICE:    subcommand: type SET COMPRESSION desc column b of table tbl
+CREATE TYPE comptype AS (r float8);
+NOTICE:  DDL test: type simple, tag CREATE TYPE
+CREATE DOMAIN dcomptype AS comptype;
+NOTICE:  DDL test: type simple, tag CREATE DOMAIN
+ALTER DOMAIN dcomptype ADD CONSTRAINT c1 check ((value).r > 0);
+NOTICE:  DDL test: type simple, tag ALTER DOMAIN
+ALTER TYPE comptype ALTER ATTRIBUTE r TYPE bigint;
+NOTICE:  DDL test: type alter table, tag ALTER TYPE
+NOTICE:    subcommand: type ALTER COLUMN SET TYPE desc column r of composite type comptype
+NOTICE:    subcommand: type (re) ADD DOMAIN CONSTRAINT desc type dcomptype
diff --git a/src/test/modules/test_ddl_deparse/expected/create_table.out b/src/test/modules/test_ddl_deparse/expected/create_table.out
index 0f2a2c164e..2178ce83e9 100644
--- a/src/test/modules/test_ddl_deparse/expected/create_table.out
+++ b/src/test/modules/test_ddl_deparse/expected/create_table.out
@@ -77,8 +77,8 @@ NOTICE:  DDL test: type simple, tag CREATE TABLE
 NOTICE:  DDL test: type simple, tag CREATE INDEX
 NOTICE:  DDL test: type simple, tag CREATE INDEX
 NOTICE:  DDL test: type alter table, tag ALTER TABLE
-NOTICE:    subcommand: ADD CONSTRAINT (and recurse)
-NOTICE:    subcommand: ADD CONSTRAINT (and recurse)
+NOTICE:    subcommand: type ADD CONSTRAINT (and recurse) desc constraint fkey_table_datatype_id_fkey on table fkey_table
+NOTICE:    subcommand: type ADD CONSTRAINT (and recurse) desc constraint fkey_big_id on table fkey_table
 -- Typed table
 CREATE TABLE employees OF employee_type (
     PRIMARY KEY (name),
@@ -86,7 +86,7 @@ CREATE TABLE employees OF employee_type (
 );
 NOTICE:  DDL test: type simple, tag CREATE TABLE
 NOTICE:  DDL test: type alter table, tag ALTER TABLE
-NOTICE:    subcommand: SET NOT NULL
+NOTICE:    subcommand: type SET NOT NULL desc column name of table employees
 NOTICE:  DDL test: type simple, tag CREATE INDEX
 -- Inheritance
 CREATE TABLE person (
@@ -136,7 +136,7 @@ CREATE TABLE like_fkey_table (
 );
 NOTICE:  DDL test: type simple, tag CREATE TABLE
 NOTICE:  DDL test: type alter table, tag ALTER TABLE
-NOTICE:    subcommand: ALTER COLUMN SET DEFAULT (precooked)
+NOTICE:    subcommand: type ALTER COLUMN SET DEFAULT (precooked) desc column id of table like_fkey_table
 NOTICE:  DDL test: type simple, tag CREATE INDEX
 NOTICE:  DDL test: type simple, tag CREATE INDEX
 -- Volatile table types
diff --git a/src/test/modules/test_ddl_deparse/expected/create_view.out b/src/test/modules/test_ddl_deparse/expected/create_view.out
index 2ae4e2d225..cf5d711f99 100644
--- a/src/test/modules/test_ddl_deparse/expected/create_view.out
+++ b/src/test/modules/test_ddl_deparse/expected/create_view.out
@@ -8,7 +8,7 @@ CREATE OR REPLACE VIEW static_view AS
   SELECT 'bar'::TEXT AS col;
 NOTICE:  DDL test: type simple, tag CREATE VIEW
 NOTICE:  DDL test: type alter table, tag CREATE VIEW
-NOTICE:    subcommand: REPLACE RELOPTIONS
+NOTICE:    subcommand: type REPLACE RELOPTIONS desc view static_view
 CREATE VIEW datatype_view AS
   SELECT * FROM datatype_table;
 NOTICE:  DDL test: type simple, tag CREATE VIEW
diff --git a/src/test/modules/test_ddl_deparse/expected/test_ddl_deparse.out b/src/test/modules/test_ddl_deparse/expected/test_ddl_deparse.out
index 4a5ea9e9ed..fc657ff49b 100644
--- a/src/test/modules/test_ddl_deparse/expected/test_ddl_deparse.out
+++ b/src/test/modules/test_ddl_deparse/expected/test_ddl_deparse.out
@@ -28,9 +28,9 @@ BEGIN
 		-- if alter table, log more
 		IF cmdtype = 'alter table' THEN
 			FOR r2 IN SELECT *
-						FROM unnest(public.get_altertable_subcmdtypes(r.command))
+						FROM public.get_altertable_subcmdinfo(r.command)
 			LOOP
-				RAISE NOTICE '  subcommand: %', r2.unnest;
+				RAISE NOTICE '  subcommand: type % desc %', r2.cmdtype, r2.objdesc;
 			END LOOP;
 		END IF;
 	END LOOP;
diff --git a/src/test/modules/test_ddl_deparse/sql/alter_table.sql b/src/test/modules/test_ddl_deparse/sql/alter_table.sql
index dec53a0640..24a5b9b3bf 100644
--- a/src/test/modules/test_ddl_deparse/sql/alter_table.sql
+++ b/src/test/modules/test_ddl_deparse/sql/alter_table.sql
@@ -2,6 +2,13 @@ CREATE TABLE parent (
 	a int
 );
 
+ALTER TABLE parent SET (fillfactor = 50);
+ALTER TABLE parent RESET (fillfactor);
+
+CREATE INDEX parent_index ON parent(a);
+ALTER TABLE parent CLUSTER ON parent_index;
+DROP INDEX parent_index;
+
 CREATE TABLE child () INHERITS (parent);
 
 CREATE TABLE grandchild () INHERITS (child);
@@ -10,6 +17,9 @@ ALTER TABLE parent ADD COLUMN b serial;
 
 ALTER TABLE parent RENAME COLUMN b TO c;
 
+-- Constraint, no recursion
+ALTER TABLE ONLY grandchild ADD CONSTRAINT a_pos CHECK (a > 0);
+-- Constraint, with recursion
 ALTER TABLE parent ADD CONSTRAINT a_pos CHECK (a > 0);
 
 CREATE TABLE part (
@@ -18,4 +28,48 @@ CREATE TABLE part (
 
 CREATE TABLE part1 PARTITION OF part FOR VALUES FROM (1) to (100);
 
+CREATE TABLE part2 (a int);
+ALTER TABLE part ATTACH PARTITION part2 FOR VALUES FROM (101) to (200);
+ALTER TABLE part DETACH PARTITION part2;
+DROP TABLE part2;
+
 ALTER TABLE part ADD PRIMARY KEY (a);
+
+ALTER TABLE parent ALTER COLUMN a SET NOT NULL;
+ALTER TABLE parent ALTER COLUMN a DROP NOT NULL;
+ALTER TABLE parent ALTER COLUMN a SET NOT NULL;
+
+ALTER TABLE parent ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
+
+ALTER TABLE parent ALTER COLUMN a SET GENERATED BY DEFAULT;
+
+ALTER TABLE parent ALTER COLUMN a DROP IDENTITY;
+
+ALTER TABLE parent ALTER COLUMN a SET STATISTICS 100;
+
+ALTER TABLE parent ALTER COLUMN a SET STORAGE PLAIN;
+
+ALTER TABLE parent ENABLE ROW LEVEL SECURITY;
+ALTER TABLE parent NO FORCE ROW LEVEL SECURITY;
+ALTER TABLE parent FORCE ROW LEVEL SECURITY;
+ALTER TABLE parent DISABLE ROW LEVEL SECURITY;
+
+CREATE STATISTICS parent_stat (dependencies) ON a, c FROM parent;
+
+ALTER TABLE parent ALTER COLUMN c TYPE numeric;
+
+ALTER TABLE parent ALTER COLUMN c SET DEFAULT 0;
+
+CREATE TABLE tbl (
+	a int generated always as (b::int * 2) stored,
+	b text
+);
+
+ALTER TABLE tbl ALTER COLUMN a DROP EXPRESSION;
+
+ALTER TABLE tbl ALTER COLUMN b SET COMPRESSION pglz;
+
+CREATE TYPE comptype AS (r float8);
+CREATE DOMAIN dcomptype AS comptype;
+ALTER DOMAIN dcomptype ADD CONSTRAINT c1 check ((value).r > 0);
+ALTER TYPE comptype ALTER ATTRIBUTE r TYPE bigint;
diff --git a/src/test/modules/test_ddl_deparse/sql/test_ddl_deparse.sql b/src/test/modules/test_ddl_deparse/sql/test_ddl_deparse.sql
index e257a215e4..a4716153df 100644
--- a/src/test/modules/test_ddl_deparse/sql/test_ddl_deparse.sql
+++ b/src/test/modules/test_ddl_deparse/sql/test_ddl_deparse.sql
@@ -29,9 +29,9 @@ BEGIN
 		-- if alter table, log more
 		IF cmdtype = 'alter table' THEN
 			FOR r2 IN SELECT *
-						FROM unnest(public.get_altertable_subcmdtypes(r.command))
+						FROM public.get_altertable_subcmdinfo(r.command)
 			LOOP
-				RAISE NOTICE '  subcommand: %', r2.unnest;
+				RAISE NOTICE '  subcommand: type % desc %', r2.cmdtype, r2.objdesc;
 			END LOOP;
 		END IF;
 	END LOOP;
diff --git a/src/test/modules/test_ddl_deparse/test_ddl_deparse--1.0.sql b/src/test/modules/test_ddl_deparse/test_ddl_deparse--1.0.sql
index 093005ad80..861d843690 100644
--- a/src/test/modules/test_ddl_deparse/test_ddl_deparse--1.0.sql
+++ b/src/test/modules/test_ddl_deparse/test_ddl_deparse--1.0.sql
@@ -11,6 +11,8 @@ CREATE FUNCTION get_command_tag(pg_ddl_command)
   RETURNS text IMMUTABLE STRICT
   AS 'MODULE_PATHNAME' LANGUAGE C;
 
-CREATE FUNCTION get_altertable_subcmdtypes(pg_ddl_command)
-  RETURNS text[] IMMUTABLE STRICT
+CREATE FUNCTION get_altertable_subcmdinfo(IN cmd pg_ddl_command,
+    OUT cmdtype text,
+    OUT objdesc text)
+  RETURNS SETOF record IMMUTABLE STRICT
   AS 'MODULE_PATHNAME' LANGUAGE C;
diff --git a/src/test/modules/test_ddl_deparse/test_ddl_deparse.c b/src/test/modules/test_ddl_deparse/test_ddl_deparse.c
index 9476c3f76e..bdbe05ceeb 100644
--- a/src/test/modules/test_ddl_deparse/test_ddl_deparse.c
+++ b/src/test/modules/test_ddl_deparse/test_ddl_deparse.c
@@ -11,6 +11,8 @@
 #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"
@@ -19,7 +21,7 @@ PG_MODULE_MAGIC;
 
 PG_FUNCTION_INFO_V1(get_command_type);
 PG_FUNCTION_INFO_V1(get_command_tag);
-PG_FUNCTION_INFO_V1(get_altertable_subcmdtypes);
+PG_FUNCTION_INFO_V1(get_altertable_subcmdinfo);
 
 /*
  * Return the textual representation of the struct type used to represent a
@@ -82,20 +84,30 @@ get_command_tag(PG_FUNCTION_ARGS)
  * command.
  */
 Datum
-get_altertable_subcmdtypes(PG_FUNCTION_ARGS)
+get_altertable_subcmdinfo(PG_FUNCTION_ARGS)
 {
 	CollectedCommand *cmd = (CollectedCommand *) PG_GETARG_POINTER(0);
-	ArrayBuildState *astate = NULL;
 	ListCell   *cell;
+	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
 
 	if (cmd->type != SCT_AlterTable)
 		elog(ERROR, "command is not ALTER TABLE");
 
+	SetSingleFuncCall(fcinfo, 0);
+
+	if (list_length(cmd->d.alterTable.subcmds) == 0)
+		elog(ERROR, "empty alter table subcommand list");
+
 	foreach(cell, cmd->d.alterTable.subcmds)
 	{
 		CollectedATSubcmd *sub = lfirst(cell);
 		AlterTableCmd *subcmd = castNode(AlterTableCmd, sub->parsetree);
-		const char *strtype;
+		const char *strtype = "unrecognized";
+		Datum		values[2];
+		bool		nulls[2];
+
+		memset(values, 0, sizeof(values));
+		memset(nulls, 0, sizeof(nulls));
 
 		switch (subcmd->subtype)
 		{
@@ -120,6 +132,9 @@ get_altertable_subcmdtypes(PG_FUNCTION_ARGS)
 			case AT_SetNotNull:
 				strtype = "SET NOT NULL";
 				break;
+			case AT_DropExpression:
+				strtype = "DROP EXPRESSION";
+				break;
 			case AT_CheckNotNull:
 				strtype = "CHECK NOT NULL";
 				break;
@@ -135,6 +150,9 @@ get_altertable_subcmdtypes(PG_FUNCTION_ARGS)
 			case AT_SetStorage:
 				strtype = "SET STORAGE";
 				break;
+			case AT_SetCompression:
+				strtype = "SET COMPRESSION";
+				break;
 			case AT_DropColumn:
 				strtype = "DROP COLUMN";
 				break;
@@ -156,6 +174,9 @@ get_altertable_subcmdtypes(PG_FUNCTION_ARGS)
 			case AT_ReAddConstraint:
 				strtype = "(re) ADD CONSTRAINT";
 				break;
+			case AT_ReAddDomainConstraint:
+				strtype = "(re) ADD DOMAIN CONSTRAINT";
+				break;
 			case AT_AlterConstraint:
 				strtype = "ALTER CONSTRAINT";
 				break;
@@ -201,6 +222,9 @@ get_altertable_subcmdtypes(PG_FUNCTION_ARGS)
 			case AT_DropOids:
 				strtype = "DROP OIDS";
 				break;
+			case AT_SetAccessMethod:
+				strtype = "SET ACCESS METHOD";
+				break;
 			case AT_SetTableSpace:
 				strtype = "SET TABLESPACE";
 				break;
@@ -279,18 +303,41 @@ get_altertable_subcmdtypes(PG_FUNCTION_ARGS)
 			case AT_GenericOptions:
 				strtype = "SET OPTIONS";
 				break;
-			default:
-				strtype = "unrecognized";
+			case AT_DetachPartition:
+				strtype = "DETACH PARTITION";
+				break;
+			case AT_AttachPartition:
+				strtype = "ATTACH PARTITION";
+				break;
+			case AT_DetachPartitionFinalize:
+				strtype = "DETACH PARTITION ... FINALIZE";
+				break;
+			case AT_AddIdentity:
+				strtype = "ADD IDENTITY";
+				break;
+			case AT_SetIdentity:
+				strtype = "SET IDENTITY";
+				break;
+			case AT_DropIdentity:
+				strtype = "DROP IDENTITY";
+				break;
+			case AT_ReAddStatistics:
+				strtype = "(re) ADD STATS";
 				break;
 		}
 
-		astate =
-			accumArrayResult(astate, CStringGetTextDatum(strtype),
-							 false, TEXTOID, CurrentMemoryContext);
+		values[0] = CStringGetTextDatum(strtype);
+		if (OidIsValid(sub->address.objectId))
+		{
+			char	   *objdesc;
+			objdesc = getObjectDescription((const ObjectAddress *) &sub->address, false);
+			values[1] = CStringGetTextDatum(objdesc);
+		}
+		else
+			nulls[1] = true;
+
+		tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
 	}
 
-	if (astate == NULL)
-		elog(ERROR, "empty alter table subcommand list");
-
-	PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate, CurrentMemoryContext));
+	return (Datum) 0;
 }
-- 
2.36.1

Attachment: signature.asc
Description: PGP signature

Reply via email to