From 6843227173a153f6a95e6f1f114cc65e308e8ab2 Mon Sep 17 00:00:00 2001
From: Tatsuro Yamada <yamatattsu@gmail.com>
Date: Sat, 25 Oct 2025 11:11:40 +0900
Subject: [PATCH] Add list constraints meta-command \dcs on psql

\dco shows all kind of constraints by using pg_constraint.
You can filter constraints by appending c/f/n/p/u/e to \dcs.
For example \dcsc will show only check constraints.

This patch also includes:
  - document
  - regression test
  - tab completion
---
 doc/src/sgml/ref/psql-ref.sgml     |  20 ++-
 src/bin/psql/command.c             |  19 ++
 src/bin/psql/describe.c            | 117 +++++++++++++
 src/bin/psql/describe.h            |   4 +
 src/bin/psql/help.c                |   2 +
 src/bin/psql/tab-complete.in.c     |   4 +-
 src/test/regress/expected/psql.out | 271 +++++++++++++++++++++++++++++
 src/test/regress/sql/psql.sql      |  64 +++++++
 8 files changed, 499 insertions(+), 2 deletions(-)

diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 1a339600bc4..fd3bc6c7956 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1548,6 +1548,25 @@ SELECT $1 \parse stmt1
         </listitem>
       </varlistentry>
 
+      <varlistentry id="app-psql-meta-command-dcs">
+        <term><literal>\dcs[cfnptue][Sx+] [ <link linkend="app-psql-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
+        <listitem>
+        <para>
+        Lists constraints.
+        If <replaceable class="parameter">pattern</replaceable>
+        is specified, only entries whose name matches the pattern are listed.
+        The modifiers <literal>c</literal> (check), <literal>f</literal> (foreign key),
+        <literal>n</literal> (not-null), <literal>p</literal> (primary key),
+        <literal>t</literal> (trigger), <literal>u</literal> (unique),
+        <literal>e</literal> (exclusion) can be appended to the command,
+        filtering the kind of constraints to list.
+        By default, only user-created constraints are shown; supply the
+        <literal>S</literal> modifier to include system objects.
+        If <literal>+</literal> is appended to the command name, each object
+        is listed with its associated description.
+        </para>
+        </listitem>
+      </varlistentry>
 
       <varlistentry id="app-psql-meta-command-dc-uc">
         <term><literal>\dC[x+] [ <link linkend="app-psql-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
@@ -1566,7 +1585,6 @@ SELECT $1 \parse stmt1
         </listitem>
       </varlistentry>
 
-
       <varlistentry id="app-psql-meta-command-dd-lc">
         <term><literal>\dd[Sx] [ <link linkend="app-psql-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
         <listitem>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index cc602087db2..05ce809090e 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -1103,6 +1103,25 @@ exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
 					success = describeConfigurationParameters(pattern,
 															  show_verbose,
 															  show_system);
+				else if (strncmp(cmd, "dcs", 3) == 0) /* Constraint */
+					switch (cmd[3])
+					{
+						case '\0':
+						case '+':
+						case 'S':
+						case 'c':
+						case 'f':
+						case 'n':
+						case 'p':
+						case 't':
+						case 'u':
+						case 'e':
+							success = listConstraints(&cmd[3], pattern, show_verbose, show_system);
+							break;
+						default:
+							status = PSQL_CMD_UNKNOWN;
+							break;
+					}
 				else
 					success = listConversions(pattern,
 											  show_verbose,
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 36f24502842..6da6a0e4055 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -4980,6 +4980,123 @@ listExtendedStats(const char *pattern)
 	return true;
 }
 
+/*
+ * \dcs
+ * Describes constraints
+ *
+ * As with \d, you can specify the kinds of constraints you want:
+ *
+ * c for check
+ * f for foreign key
+ * n for not null
+ * p for primary key
+ * t for trigger
+ * u for unique
+ * e for exclusion
+ *
+ * and you can mix and match these in any order.
+ */
+bool
+listConstraints(const char *contypes, const char *pattern, bool verbose, bool showSystem)
+{
+	bool		showCheck = strchr(contypes, CONSTRAINT_CHECK) != NULL;
+	bool		showForeign = strchr(contypes, CONSTRAINT_FOREIGN) != NULL;
+	bool		showNotnull = strchr(contypes, CONSTRAINT_NOTNULL) != NULL;
+	bool		showPrimary = strchr(contypes, CONSTRAINT_PRIMARY) != NULL;
+	bool		showTrigger = strchr(contypes, CONSTRAINT_TRIGGER) != NULL;
+	bool		showUnique = strchr(contypes, CONSTRAINT_UNIQUE) != NULL;
+	bool		showExclusion = strchr(contypes, 'e') != NULL;
+	bool		showAllkinds = false;
+	PQExpBufferData buf;
+	PGresult   *res;
+	printQueryOpt myopt = pset.popt;
+
+	if (pset.sversion < 180000)
+	{
+		char		sverbuf[32];
+
+		pg_log_error("The server (version %s) does not support this meta-command on psql.",
+					 formatPGVersionNumber(pset.sversion, false,
+										   sverbuf, sizeof(sverbuf)));
+		return true;
+	}
+
+	/* If contypes were not selected, show them all */
+	if (!(showCheck || showForeign || showNotnull || showPrimary || showTrigger || showUnique || showExclusion))
+		showAllkinds = true;
+
+	initPQExpBuffer(&buf);
+	printfPQExpBuffer(&buf,
+					  "SELECT n.nspname AS \"%s\", \n"
+					  "       cst.conname AS \"%s\" ",
+					  gettext_noop("Schema"),
+					  gettext_noop("Name")
+					 );
+
+	if (verbose)
+		appendPQExpBuffer(&buf,
+						  ",\n       pg_catalog.pg_get_constraintdef(cst.oid) AS \"%s\", \n"
+						  "       cst.conrelid::pg_catalog.regclass AS \"%s\" ",
+						  gettext_noop("Definition"),
+						  gettext_noop("Table")
+						 );
+
+	appendPQExpBufferStr(&buf,
+						 "\nFROM pg_catalog.pg_constraint cst \n"
+						 "     JOIN pg_catalog.pg_namespace n ON n.oid = cst.connamespace \n"
+						);
+
+	if (!showSystem && !pattern)
+		appendPQExpBufferStr(&buf,
+							 "WHERE n.nspname <> 'pg_catalog' \n"
+							 "  AND n.nspname <> 'information_schema' \n");
+
+	processSQLNamePattern(pset.db, &buf,
+						  pattern,
+						  !showSystem && !pattern, false,
+						  "n.nspname", "cst.conname",
+						  NULL, "pg_catalog.pg_table_is_visible(cst.conrelid)",
+						  NULL, NULL);
+
+	if (!showAllkinds)
+	{
+		appendPQExpBufferStr(&buf, "  AND cst.contype in (");
+
+		if (showCheck)
+			appendPQExpBufferStr(&buf, CppAsString2(CONSTRAINT_CHECK) ",");
+		if (showForeign)
+			appendPQExpBufferStr(&buf, CppAsString2(CONSTRAINT_FOREIGN) ",");
+		if (showNotnull)
+			appendPQExpBufferStr(&buf, CppAsString2(CONSTRAINT_NOTNULL) ",");
+		if (showPrimary)
+			appendPQExpBufferStr(&buf, CppAsString2(CONSTRAINT_PRIMARY) ",");
+		if (showTrigger)
+			appendPQExpBufferStr(&buf, CppAsString2(CONSTRAINT_TRIGGER) ",");
+		if (showUnique)
+			appendPQExpBufferStr(&buf, CppAsString2(CONSTRAINT_UNIQUE) ",");
+		if (showExclusion)
+			appendPQExpBufferStr(&buf, CppAsString2(CONSTRAINT_EXCLUSION) ",");
+
+		appendPQExpBufferStr(&buf, " ''");	/* dummy */
+		appendPQExpBufferStr(&buf, ")\n");
+	}
+
+	appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
+	if (!res)
+		return false;
+
+	myopt.title = _("List of constraints");
+	myopt.translate_header = true;
+
+	printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+	PQclear(res);
+	return true;
+}
+
 /*
  * \dC
  *
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index 18ecaa60949..c389a9e38d5 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -83,6 +83,10 @@ extern bool listConversions(const char *pattern, bool verbose, bool showSystem);
 extern bool describeConfigurationParameters(const char *pattern, bool verbose,
 											bool showSystem);
 
+/* \dcs */
+extern bool listConstraints(const char *contypes, const char *pattern, bool verbose,
+							bool showSystem);
+
 /* \dC */
 extern bool listCasts(const char *pattern, bool verbose);
 
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index ed00c36695e..d8a23d2c6fd 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -230,6 +230,8 @@ slashUsage(unsigned short int pager)
 	HELP0("  \\db[x+]  [PATTERN]     list tablespaces\n");
 	HELP0("  \\dc[Sx+] [PATTERN]     list conversions\n");
 	HELP0("  \\dconfig[x+] [PATTERN] list configuration parameters\n");
+	HELP0("  \\dcs[cfnptue] [Sx+] [PATTERN] list [only check/foreign key/not-null/primary key\n"
+		  "                             /constraint trigger/unique key/exclusion] constraints\n");
 	HELP0("  \\dC[x+]  [PATTERN]     list casts\n");
 	HELP0("  \\dd[Sx]  [PATTERN]     show object descriptions not displayed elsewhere\n");
 	HELP0("  \\dD[Sx+] [PATTERN]     list domains\n");
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 36ea6a4d557..877e89beca5 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -1913,7 +1913,7 @@ psql_completion(const char *text, int start, int end)
 		"\\connect", "\\conninfo", "\\C", "\\cd", "\\close_prepared", "\\copy",
 		"\\copyright", "\\crosstabview",
 		"\\d", "\\da", "\\dA", "\\dAc", "\\dAf", "\\dAo", "\\dAp",
-		"\\db", "\\dc", "\\dconfig", "\\dC", "\\dd", "\\ddp", "\\dD",
+		"\\db", "\\dc", "\\dconfig", "\\dcs", "\\dC", "\\dd", "\\ddp", "\\dD",
 		"\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
 		"\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
 		"\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\dP", "\\dPi", "\\dPt",
@@ -5353,6 +5353,8 @@ match_previous_words(int pattern_id,
 		COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
 	else if (TailMatchesCS("\\dconfig*"))
 		COMPLETE_WITH_QUERY_VERBATIM(Query_for_list_of_show_vars);
+	else if (TailMatchesCS("\\dcs*"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema);
 	else if (TailMatchesCS("\\dD*"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
 	else if (TailMatchesCS("\\des*"))
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index fa8984ffe0d..ee6379851c8 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -5356,6 +5356,277 @@ List of configuration parameters
 (1 row)
 
 reset work_mem;
+-- check \dco
+CREATE TABLE con_c (
+    primary_col SERIAL PRIMARY KEY
+);
+CREATE TABLE con_p (
+    primary_col SERIAL PRIMARY KEY,
+    notnull_col TEXT NOT NULL,
+    check_col INT CHECK (check_col >= 0),
+    foreign_col INT REFERENCES con_c(primary_col),
+    unique_col TEXT UNIQUE,
+    exclusion_col INT,
+    CONSTRAINT con_p_exclusion EXCLUDE USING btree (exclusion_col WITH =)
+);
+CREATE OR REPLACE FUNCTION trigger_hoge() RETURNS TRIGGER AS $$
+  BEGIN
+    RETURN NULL;
+  END;
+  $$ LANGUAGE PLPGSQL;
+CREATE CONSTRAINT TRIGGER con_p_trigger AFTER INSERT ON con_p
+  FOR EACH ROW EXECUTE PROCEDURE trigger_hoge();
+\dcs con_*
+         List of constraints
+ Schema |            Name            
+--------+----------------------------
+ public | con_c_pkey
+ public | con_c_primary_col_not_null
+ public | con_p_check_col_check
+ public | con_p_exclusion
+ public | con_p_foreign_col_fkey
+ public | con_p_notnull_col_not_null
+ public | con_p_pkey
+ public | con_p_primary_col_not_null
+ public | con_p_trigger
+ public | con_p_unique_col_key
+(10 rows)
+
+\dcscfnptue con_*
+         List of constraints
+ Schema |            Name            
+--------+----------------------------
+ public | con_c_pkey
+ public | con_c_primary_col_not_null
+ public | con_p_check_col_check
+ public | con_p_exclusion
+ public | con_p_foreign_col_fkey
+ public | con_p_notnull_col_not_null
+ public | con_p_pkey
+ public | con_p_primary_col_not_null
+ public | con_p_trigger
+ public | con_p_unique_col_key
+(10 rows)
+
+\dcs+ con_*
+                                          List of constraints
+ Schema |            Name            |                       Definition                        | Table 
+--------+----------------------------+---------------------------------------------------------+-------
+ public | con_c_pkey                 | PRIMARY KEY (primary_col)                               | con_c
+ public | con_c_primary_col_not_null | NOT NULL primary_col                                    | con_c
+ public | con_p_check_col_check      | CHECK ((check_col >= 0))                                | con_p
+ public | con_p_exclusion            | EXCLUDE USING btree (exclusion_col WITH =)              | con_p
+ public | con_p_foreign_col_fkey     | FOREIGN KEY (foreign_col) REFERENCES con_c(primary_col) | con_p
+ public | con_p_notnull_col_not_null | NOT NULL notnull_col                                    | con_p
+ public | con_p_pkey                 | PRIMARY KEY (primary_col)                               | con_p
+ public | con_p_primary_col_not_null | NOT NULL primary_col                                    | con_p
+ public | con_p_trigger              | TRIGGER                                                 | con_p
+ public | con_p_unique_col_key       | UNIQUE (unique_col)                                     | con_p
+(10 rows)
+
+\dcscfnptue+ con_*
+                                          List of constraints
+ Schema |            Name            |                       Definition                        | Table 
+--------+----------------------------+---------------------------------------------------------+-------
+ public | con_c_pkey                 | PRIMARY KEY (primary_col)                               | con_c
+ public | con_c_primary_col_not_null | NOT NULL primary_col                                    | con_c
+ public | con_p_check_col_check      | CHECK ((check_col >= 0))                                | con_p
+ public | con_p_exclusion            | EXCLUDE USING btree (exclusion_col WITH =)              | con_p
+ public | con_p_foreign_col_fkey     | FOREIGN KEY (foreign_col) REFERENCES con_c(primary_col) | con_p
+ public | con_p_notnull_col_not_null | NOT NULL notnull_col                                    | con_p
+ public | con_p_pkey                 | PRIMARY KEY (primary_col)                               | con_p
+ public | con_p_primary_col_not_null | NOT NULL primary_col                                    | con_p
+ public | con_p_trigger              | TRIGGER                                                 | con_p
+ public | con_p_unique_col_key       | UNIQUE (unique_col)                                     | con_p
+(10 rows)
+
+\dcsc con_*
+      List of constraints
+ Schema |         Name          
+--------+-----------------------
+ public | con_p_check_col_check
+(1 row)
+
+\dcsc+ con_*
+                        List of constraints
+ Schema |         Name          |        Definition        | Table 
+--------+-----------------------+--------------------------+-------
+ public | con_p_check_col_check | CHECK ((check_col >= 0)) | con_p
+(1 row)
+
+\dcsf con_*
+       List of constraints
+ Schema |          Name          
+--------+------------------------
+ public | con_p_foreign_col_fkey
+(1 row)
+
+\dcsf+ con_*
+                                        List of constraints
+ Schema |          Name          |                       Definition                        | Table 
+--------+------------------------+---------------------------------------------------------+-------
+ public | con_p_foreign_col_fkey | FOREIGN KEY (foreign_col) REFERENCES con_c(primary_col) | con_p
+(1 row)
+
+\dcsn con_*
+         List of constraints
+ Schema |            Name            
+--------+----------------------------
+ public | con_c_primary_col_not_null
+ public | con_p_notnull_col_not_null
+ public | con_p_primary_col_not_null
+(3 rows)
+
+\dcsn+ con_*
+                        List of constraints
+ Schema |            Name            |      Definition      | Table 
+--------+----------------------------+----------------------+-------
+ public | con_c_primary_col_not_null | NOT NULL primary_col | con_c
+ public | con_p_notnull_col_not_null | NOT NULL notnull_col | con_p
+ public | con_p_primary_col_not_null | NOT NULL primary_col | con_p
+(3 rows)
+
+\dcsp con_*
+ List of constraints
+ Schema |    Name    
+--------+------------
+ public | con_c_pkey
+ public | con_p_pkey
+(2 rows)
+
+\dcsp+ con_*
+                   List of constraints
+ Schema |    Name    |        Definition         | Table 
+--------+------------+---------------------------+-------
+ public | con_c_pkey | PRIMARY KEY (primary_col) | con_c
+ public | con_p_pkey | PRIMARY KEY (primary_col) | con_p
+(2 rows)
+
+\dcst con_*
+  List of constraints
+ Schema |     Name      
+--------+---------------
+ public | con_p_trigger
+(1 row)
+
+\dcst+ con_*
+             List of constraints
+ Schema |     Name      | Definition | Table 
+--------+---------------+------------+-------
+ public | con_p_trigger | TRIGGER    | con_p
+(1 row)
+
+\dcsu con_*
+      List of constraints
+ Schema |         Name         
+--------+----------------------
+ public | con_p_unique_col_key
+(1 row)
+
+\dcsu+ con_*
+                     List of constraints
+ Schema |         Name         |     Definition      | Table 
+--------+----------------------+---------------------+-------
+ public | con_p_unique_col_key | UNIQUE (unique_col) | con_p
+(1 row)
+
+\dcse con_*
+   List of constraints
+ Schema |      Name       
+--------+-----------------
+ public | con_p_exclusion
+(1 row)
+
+\dcse+ con_*
+                              List of constraints
+ Schema |      Name       |                 Definition                 | Table 
+--------+-----------------+--------------------------------------------+-------
+ public | con_p_exclusion | EXCLUDE USING btree (exclusion_col WITH =) | con_p
+(1 row)
+
+\dcsS pg_constraint*
+                    List of constraints
+   Schema   |                     Name                      
+------------+-----------------------------------------------
+ pg_catalog | pg_constraint_conrelid_contypid_conname_index
+ pg_catalog | pg_constraint_oid_index
+ pg_catalog | pg_constraint_oid_not_null
+(3 rows)
+
+\dcsScfnpue pg_constraint*
+                    List of constraints
+   Schema   |                     Name                      
+------------+-----------------------------------------------
+ pg_catalog | pg_constraint_conrelid_contypid_conname_index
+ pg_catalog | pg_constraint_oid_index
+ pg_catalog | pg_constraint_oid_not_null
+(3 rows)
+
+\dcsS+ pg_constraint*
+                                                List of constraints
+   Schema   |                     Name                      |              Definition              |     Table     
+------------+-----------------------------------------------+--------------------------------------+---------------
+ pg_catalog | pg_constraint_conrelid_contypid_conname_index | UNIQUE (conrelid, contypid, conname) | pg_constraint
+ pg_catalog | pg_constraint_oid_index                       | PRIMARY KEY (oid)                    | pg_constraint
+ pg_catalog | pg_constraint_oid_not_null                    | NOT NULL oid                         | pg_constraint
+(3 rows)
+
+\dcsScfnpue+ pg_constraint*
+                                                List of constraints
+   Schema   |                     Name                      |              Definition              |     Table     
+------------+-----------------------------------------------+--------------------------------------+---------------
+ pg_catalog | pg_constraint_conrelid_contypid_conname_index | UNIQUE (conrelid, contypid, conname) | pg_constraint
+ pg_catalog | pg_constraint_oid_index                       | PRIMARY KEY (oid)                    | pg_constraint
+ pg_catalog | pg_constraint_oid_not_null                    | NOT NULL oid                         | pg_constraint
+(3 rows)
+
+-- test with search_path
+CREATE SCHEMA con_schema;
+CREATE TABLE con_schema.con_schema_test (
+    primary_col SERIAL PRIMARY KEY
+);
+SET SEARCH_PATH TO public, con_schema;
+\dcs con_*
+                List of constraints
+   Schema   |                 Name                 
+------------+--------------------------------------
+ con_schema | con_schema_test_pkey
+ con_schema | con_schema_test_primary_col_not_null
+ public     | con_c_pkey
+ public     | con_c_primary_col_not_null
+ public     | con_p_check_col_check
+ public     | con_p_exclusion
+ public     | con_p_foreign_col_fkey
+ public     | con_p_notnull_col_not_null
+ public     | con_p_pkey
+ public     | con_p_primary_col_not_null
+ public     | con_p_trigger
+ public     | con_p_unique_col_key
+(12 rows)
+
+SET SEARCH_PATH TO public;
+\dcs con_*
+         List of constraints
+ Schema |            Name            
+--------+----------------------------
+ public | con_c_pkey
+ public | con_c_primary_col_not_null
+ public | con_p_check_col_check
+ public | con_p_exclusion
+ public | con_p_foreign_col_fkey
+ public | con_p_notnull_col_not_null
+ public | con_p_pkey
+ public | con_p_primary_col_not_null
+ public | con_p_trigger
+ public | con_p_unique_col_key
+(10 rows)
+
+RESET search_path;
+-- clean up
+DROP SCHEMA con_schema CASCADE;
+NOTICE:  drop cascades to table con_schema.con_schema_test
+DROP TABLE con_p, con_c CASCADE;
+DROP FUNCTION trigger_hoge;
 -- check \df, \do with argument specifications
 \df *sqrt
                              List of functions
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index f064e4f5456..5f5adc9615e 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -1331,6 +1331,70 @@ set work_mem = 10240;
 \dconfig+ work*
 reset work_mem;
 
+-- check \dco
+CREATE TABLE con_c (
+    primary_col SERIAL PRIMARY KEY
+);
+
+CREATE TABLE con_p (
+    primary_col SERIAL PRIMARY KEY,
+    notnull_col TEXT NOT NULL,
+    check_col INT CHECK (check_col >= 0),
+    foreign_col INT REFERENCES con_c(primary_col),
+    unique_col TEXT UNIQUE,
+    exclusion_col INT,
+    CONSTRAINT con_p_exclusion EXCLUDE USING btree (exclusion_col WITH =)
+);
+
+CREATE OR REPLACE FUNCTION trigger_hoge() RETURNS TRIGGER AS $$
+  BEGIN
+    RETURN NULL;
+  END;
+  $$ LANGUAGE PLPGSQL;
+
+CREATE CONSTRAINT TRIGGER con_p_trigger AFTER INSERT ON con_p
+  FOR EACH ROW EXECUTE PROCEDURE trigger_hoge();
+
+\dcs con_*
+\dcscfnptue con_*
+\dcs+ con_*
+\dcscfnptue+ con_*
+\dcsc con_*
+\dcsc+ con_*
+\dcsf con_*
+\dcsf+ con_*
+\dcsn con_*
+\dcsn+ con_*
+\dcsp con_*
+\dcsp+ con_*
+\dcst con_*
+\dcst+ con_*
+\dcsu con_*
+\dcsu+ con_*
+\dcse con_*
+\dcse+ con_*
+\dcsS pg_constraint*
+\dcsScfnpue pg_constraint*
+\dcsS+ pg_constraint*
+\dcsScfnpue+ pg_constraint*
+
+-- test with search_path
+CREATE SCHEMA con_schema;
+CREATE TABLE con_schema.con_schema_test (
+    primary_col SERIAL PRIMARY KEY
+);
+
+SET SEARCH_PATH TO public, con_schema;
+\dcs con_*
+SET SEARCH_PATH TO public;
+\dcs con_*
+RESET search_path;
+
+-- clean up
+DROP SCHEMA con_schema CASCADE;
+DROP TABLE con_p, con_c CASCADE;
+DROP FUNCTION trigger_hoge;
+
 -- check \df, \do with argument specifications
 \df *sqrt
 \df *sqrt num*
-- 
2.43.5

