From 773e9d003eb01731d3dc1a5de58cf794b9eff925 Mon Sep 17 00:00:00 2001
From: Vigneshwaran C <vignesh21@gmail.com>
Date: Thu, 28 Jul 2022 22:19:00 +0530
Subject: [PATCH v1] Include the dependent extension information for index and
 materialized view in describe command.

Include the dependent extension information for index and materialized
view in describe command.
---
 src/bin/psql/describe.c                | 55 ++++++++++++++++++++++++++
 src/test/regress/expected/indexing.out | 14 +++++++
 src/test/regress/expected/matview.out  | 14 +++++++
 src/test/regress/sql/indexing.sql      |  7 ++++
 src/test/regress/sql/matview.sql       |  6 +++
 5 files changed, 96 insertions(+)

diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 327a69487b..a637f787a3 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -20,6 +20,7 @@
 #include "catalog/pg_cast_d.h"
 #include "catalog/pg_class_d.h"
 #include "catalog/pg_default_acl_d.h"
+#include "catalog/pg_extension_d.h"
 #include "common.h"
 #include "common/logging.h"
 #include "describe.h"
@@ -36,6 +37,8 @@ static bool describeOneTableDetails(const char *schemaname,
 									bool verbose);
 static void add_tablespace_footer(printTableContent *const cont, char relkind,
 								  Oid tablespace, const bool newline);
+static void add_depends_footer(printTableContent *const cont, char relkind,
+							   const char *objid);
 static void add_role_attribute(PQExpBuffer buf, const char *const str);
 static bool listTSParsersVerbose(const char *pattern);
 static bool describeOneTSParser(const char *oid, const char *nspname,
@@ -2350,6 +2353,8 @@ describeOneTableDetails(const char *schemaname,
 		}
 
 		PQclear(result);
+
+		add_depends_footer(&cont, tableinfo.relkind, oid);
 	}
 	/* If you add relkinds here, see also "Finish printing..." stanza below */
 	else if (tableinfo.relkind == RELKIND_RELATION ||
@@ -3499,6 +3504,8 @@ describeOneTableDetails(const char *schemaname,
 			printfPQExpBuffer(&buf, _("Access method: %s"), tableinfo.relam);
 			printTableAddFooter(&cont, buf.data);
 		}
+
+		add_depends_footer(&cont, tableinfo.relkind, oid);
 	}
 
 	/* reloptions, if verbose */
@@ -3531,6 +3538,54 @@ error_return:
 	return retval;
 }
 
+/*
+ * Add a depend extensions to a footer.
+ */
+static void
+add_depends_footer(printTableContent *const cont, char relkind,
+				   const char *objid)
+{
+	/* relkinds for which we support depends */
+	if (relkind == RELKIND_MATVIEW || relkind == RELKIND_INDEX)
+	{
+		PGresult   *result = NULL;
+		PQExpBufferData buf;
+		int			tuples = 0;
+		int			i;
+
+		initPQExpBuffer(&buf);
+
+		/* Get the depend extensions for the object */
+		printfPQExpBuffer(&buf,
+						  "SELECT e.extname FROM pg_depend d \n"
+						  " LEFT JOIN pg_catalog.pg_extension e \n"
+						  " ON (oid = d.refobjid) WHERE d.objid = '%s' AND d.refclassid = '%d'",
+						  objid, ExtensionRelationId);
+		result = PSQLexec(buf.data);
+		if (!result)
+		{
+			termPQExpBuffer(&buf);
+			return;
+		}
+		else
+			tuples = PQntuples(result);
+
+		if (tuples > 0)
+		{
+			printTableAddFooter(cont, _("Depends:"));
+			for (i = 0; i < tuples; i++)
+			{
+				/* untranslated extension name */
+				printfPQExpBuffer(&buf, "    \"%s\"", PQgetvalue(result, i, 0));
+				printTableAddFooter(cont, buf.data);
+			}
+		}
+
+		PQclear(result);
+		termPQExpBuffer(&buf);
+	}
+}
+
 /*
  * Add a tablespace description to a footer.  If 'newline' is true, it is added
  * in a new line; otherwise it's appended to the current value of the last
diff --git a/src/test/regress/expected/indexing.out b/src/test/regress/expected/indexing.out
index 193f780191..13f9982180 100644
--- a/src/test/regress/expected/indexing.out
+++ b/src/test/regress/expected/indexing.out
@@ -1296,6 +1296,20 @@ ERROR:  cannot drop inherited constraint "parted_uniq_detach_test1_a_key" of rel
 alter table parted_uniq_detach_test detach partition parted_uniq_detach_test1;
 alter table parted_uniq_detach_test1 drop constraint parted_uniq_detach_test1_a_key;
 drop table parted_uniq_detach_test, parted_uniq_detach_test1;
+-- check that the index is marked as dependent on extension
+create table tbl_idx_depends(a int);
+create index idx_depends on tbl_idx_depends(a);
+alter index idx_depends depends on extension plpgsql;
+\d+ idx_depends
+                  Index "public.idx_depends"
+ Column |  Type   | Key? | Definition | Storage | Stats target 
+--------+---------+------+------------+---------+--------------
+ a      | integer | yes  | a          | plain   | 
+btree, for table "public.tbl_idx_depends"
+Depends:
+    "plpgsql"
+
+drop table tbl_idx_depends;
 -- check that dropping a column takes with it any partitioned indexes
 -- depending on it.
 create table parted_index_col_drop(a int, b int, c int)
diff --git a/src/test/regress/expected/matview.out b/src/test/regress/expected/matview.out
index c109d97635..5a031dbb5d 100644
--- a/src/test/regress/expected/matview.out
+++ b/src/test/regress/expected/matview.out
@@ -676,3 +676,17 @@ NOTICE:  relation "matview_ine_tab" already exists, skipping
 (0 rows)
 
 DROP MATERIALIZED VIEW matview_ine_tab;
+-- check that the materialized view is marked as dependent on extension
+CREATE MATERIALIZED VIEW matview_depends AS SELECT 1;
+ALTER MATERIALIZED VIEW matview_depends DEPENDS ON EXTENSION plpgsql;
+\d+ matview_depends
+                         Materialized view "public.matview_depends"
+  Column  |  Type   | Collation | Nullable | Default | Storage | Stats target | Description 
+----------+---------+-----------+----------+---------+---------+--------------+-------------
+ ?column? | integer |           |          |         | plain   |              | 
+View definition:
+ SELECT 1 AS "?column?";
+Depends:
+    "plpgsql"
+
+DROP MATERIALIZED VIEW matview_depends;
diff --git a/src/test/regress/sql/indexing.sql b/src/test/regress/sql/indexing.sql
index 42f398b67c..e8afab1571 100644
--- a/src/test/regress/sql/indexing.sql
+++ b/src/test/regress/sql/indexing.sql
@@ -727,6 +727,13 @@ alter table parted_uniq_detach_test detach partition parted_uniq_detach_test1;
 alter table parted_uniq_detach_test1 drop constraint parted_uniq_detach_test1_a_key;
 drop table parted_uniq_detach_test, parted_uniq_detach_test1;
 
+-- check that the index is marked as dependent on extension
+create table tbl_idx_depends(a int);
+create index idx_depends on tbl_idx_depends(a);
+alter index idx_depends depends on extension plpgsql;
+\d+ idx_depends
+drop table tbl_idx_depends;
+
 -- check that dropping a column takes with it any partitioned indexes
 -- depending on it.
 create table parted_index_col_drop(a int, b int, c int)
diff --git a/src/test/regress/sql/matview.sql b/src/test/regress/sql/matview.sql
index 68b9ccfd45..54f78b6168 100644
--- a/src/test/regress/sql/matview.sql
+++ b/src/test/regress/sql/matview.sql
@@ -295,3 +295,9 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
   CREATE MATERIALIZED VIEW IF NOT EXISTS matview_ine_tab AS
     SELECT 1 / 0 WITH NO DATA; -- ok
 DROP MATERIALIZED VIEW matview_ine_tab;
+
+-- check that the materialized view is marked as dependent on extension
+CREATE MATERIALIZED VIEW matview_depends AS SELECT 1;
+ALTER MATERIALIZED VIEW matview_depends DEPENDS ON EXTENSION plpgsql;
+\d+ matview_depends
+DROP MATERIALIZED VIEW matview_depends;
-- 
2.32.0

