Hi Dag,

The patch adds the command "\dco" to list constraints in psql. This
seems useful to me.

Thank you!

The patch applies cleanly to HEAD, although some hunks have rather large
offsets.

As far as I can tell, the "\dco" command works as documented.

I have however found the following issues with the patch:

* A TAB character has been added to doc/src/sgml/ref/psql-ref.sgml -
   this should be replaced with spaces.

Fixed.


* The call to listConstraints in line src/bin/psql/command.c 794 refers
   to &cmd[2], this should rather be &cmd[3].

* The patch kills the "\dc" command in src/bin/psql/command.c
   This can be fixed by adding the following at line 800:
               else
                                         success =
   listConversions(pattern, show_verbose, show_system);


Oh, you are right! Fixed.

Another comment is that the "\dco" command outputs quite a lot of
information, which only fits in a wide terminal window. Would it be an
idea to only display the columns "Schema" and "Name" by default, and
use "+" to specify inclusion of the columns "Definition" and "Table".
I fixed the output columns as you proposed.

The current status of this patch is:

  - Addressed Dag's comments
  - Not implemented yet:
    - Tab completion
    - Regression test
    - NOT NULL constraint, and so on (based on pg_attribute)

Please find attached new patch.


Thanks,
Tatsuro Yamada




diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index caabb06..125ae3d 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1388,6 +1388,26 @@ testdb=>
 
 
       <varlistentry>
+        <term><literal>\dco[cfptuxS+] [ <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>p</literal> (primary key), <literal>t</literal> (trigger), 
+        <literal>u</literal> (unique), <literal>x</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>
         <term><literal>\dC[+] [ <link linkend="app-psql-patterns"><replaceable 
class="parameter">pattern</replaceable></link> ]</literal></term>
         <listitem>
         <para>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 079f4a1..05ae25e 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -780,7 +780,26 @@ exec_command_d(PsqlScanState scan_state, bool 
active_branch, const char *cmd)
                                success = describeTablespaces(pattern, 
show_verbose);
                                break;
                        case 'c':
-                               success = listConversions(pattern, 
show_verbose, show_system);
+                               if (strncmp(cmd, "dco", 3) == 0) /* Constraint 
*/
+                                       switch (cmd[3])
+                                       {
+                                               case '\0':
+                                               case '+':
+                                               case 'S':
+                                               case 'c':
+                                               case 'f':
+                                               case 'p':
+                                               case 't':
+                                               case 'u':
+                                               case 'x':
+                                                       success = 
listConstraints(&cmd[3], pattern, show_verbose, show_system);
+                                                       break;
+                                               default:
+                                                       status = 
PSQL_CMD_UNKNOWN;
+                                                       break;
+                                       }
+                               else
+                                       success = listConversions(pattern, 
show_verbose, show_system);
                                break;
                        case 'C':
                                success = listCasts(pattern, show_verbose);
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 4dddf08..7acd25a 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -19,6 +19,7 @@
 #include "catalog/pg_attribute_d.h"
 #include "catalog/pg_cast_d.h"
 #include "catalog/pg_class_d.h"
+#include "catalog/pg_constraint_d.h"
 #include "catalog/pg_default_acl_d.h"
 #include "common.h"
 #include "common/logging.h"
@@ -4599,6 +4600,109 @@ listExtendedStats(const char *pattern)
 }
 
 /*
+ * \dco
+ *
+ * Describes constraints
+ *
+ * As with \d, you can specify the kinds of constraints you want:
+ *
+ * c for check
+ * f for foreign key
+ * p for primary key
+ * t for trigger
+ * u for unique
+ * x 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            showPrimary = strchr(contypes, CONSTRAINT_PRIMARY) != 
NULL;
+       bool            showTrigger = strchr(contypes, CONSTRAINT_TRIGGER) != 
NULL;
+       bool            showUnique = strchr(contypes, CONSTRAINT_UNIQUE) != 
NULL;
+       bool            showExclusion = strchr(contypes, CONSTRAINT_EXCLUSION) 
!= NULL;
+       bool            showAllkinds = false;
+       PQExpBufferData buf;
+       PGresult   *res;
+       printQueryOpt myopt = pset.popt;
+
+       /* If contype was not selected, show them all */
+       if (!(showCheck || showForeign || 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"
+                                                 "       
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)");
+
+       if (!showAllkinds)
+       {
+               appendPQExpBufferStr(&buf, "  AND cst.contype in (");
+
+               if (showCheck)
+                       appendPQExpBufferStr(&buf, 
CppAsString2(CONSTRAINT_CHECK) ",");
+               if (showForeign)
+                       appendPQExpBufferStr(&buf, 
CppAsString2(CONSTRAINT_FOREIGN) ",");
+               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.nullPrint = NULL;
+       myopt.title = _("List of constraints");
+       myopt.translate_header = true;
+
+       printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
+
+       PQclear(res);
+       return true;
+}
+
+/*
  * \dC
  *
  * Describes casts.
diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h
index fd60796..0929ff5 100644
--- a/src/bin/psql/describe.h
+++ b/src/bin/psql/describe.h
@@ -76,6 +76,9 @@ extern bool listDomains(const char *pattern, bool verbose, 
bool showSystem);
 /* \dc */
 extern bool listConversions(const char *pattern, bool verbose, bool 
showSystem);
 
+/* \dco */
+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 56afa68..6cfee66 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -231,6 +231,7 @@ slashUsage(unsigned short int pager)
        fprintf(output, _("  \\dAp[+] [AMPTRN [OPFPTRN]]   list support 
functions of operator families\n"));
        fprintf(output, _("  \\db[+]  [PATTERN]      list tablespaces\n"));
        fprintf(output, _("  \\dc[S+] [PATTERN]      list conversions\n"));
+       fprintf(output, _("  \\dco[cfptuxS+] [PATTERN] list constraints\n"));
        fprintf(output, _("  \\dC[+]  [PATTERN]      list casts\n"));
        fprintf(output, _("  \\dd[S]  [PATTERN]      show object descriptions 
not displayed elsewhere\n"));
        fprintf(output, _("  \\dD[S+] [PATTERN]      list domains\n"));

Reply via email to