Showing index details with \d on psql.
authorBruce Momjian <bruce@momjian.us>
Tue, 5 Mar 2002 02:42:56 +0000 (02:42 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 5 Mar 2002 02:42:56 +0000 (02:42 +0000)
Greg Sabino Mullane

src/bin/psql/describe.c

index e285535c817e5d9117312ea424daa9736a03b717..ef31c5ee906b5489fa2a5bedaa92712b10afd16c 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.42 2001/11/12 15:57:08 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.43 2002/03/05 02:42:56 momjian Exp $
  */
 #include "postgres_fe.h"
 #include "describe.h"
@@ -532,15 +532,23 @@ describeTableDetails(const char *name, bool desc)
    headers[cols] = NULL;
 
 
-   /* Get column info */
-   strcpy(buf, "SELECT a.attname, format_type(a.atttypid, a.atttypmod), a.attnotnull, a.atthasdef, a.attnum");
+   /* Get column info (index requires additional checks) */
+   if (tableinfo.relkind == 'i')
+       strcpy(buf, "SELECT\n  CASE i.indproc WHEN ('-'::regproc) THEN a.attname\n  ELSE SUBSTR(pg_get_indexdef(attrelid),\n  POSITION('(' in pg_get_indexdef(attrelid)))\n  END, ");
+   else
+       strcpy(buf, "SELECT a.attname, ");
+   strcat(buf, "format_type(a.atttypid, a.atttypmod), a.attnotnull, a.atthasdef, a.attnum");
    if (desc)
        strcat(buf, ", col_description(a.attrelid, a.attnum)");
-   strcat(buf, "\nFROM pg_class c, pg_attribute a\n"
-          "WHERE c.relname = '");
+   strcat(buf, "\nFROM pg_class c, pg_attribute a");
+   if (tableinfo.relkind == 'i')
+       strcat(buf, ", pg_index i");
+   strcat(buf, "\nWHERE c.relname = '");
    strncat(buf, name, NAMEDATALEN);
-   strcat(buf, "'\n  AND a.attnum > 0 AND a.attrelid = c.oid\n"
-          "ORDER BY a.attnum");
+   strcat(buf, "'\n  AND a.attnum > 0 AND a.attrelid = c.oid");
+   if (tableinfo.relkind == 'i')
+       strcat(buf, " AND a.attrelid = i.indexrelid");
+   strcat(buf, "\nORDER BY a.attnum");
 
    res = PSQLexec(buf);
    if (!res)
@@ -651,11 +659,11 @@ describeTableDetails(const char *name, bool desc)
    {
        /* Footer information about an index */
        PGresult   *result;
-
-       sprintf(buf, "SELECT i.indisunique, i.indisprimary, a.amname,\n"
-               "       pg_get_expr(i.indpred, i.indrelid) as indpred\n"
-               "FROM pg_index i, pg_class c, pg_am a\n"
-               "WHERE i.indexrelid = c.oid AND c.relname = '%s' AND c.relam = a.oid",
+       sprintf(buf, "SELECT i.indisunique, i.indisprimary, a.amname, c2.relname,\n"
+               "pg_get_expr(i.indpred,i.indrelid)\n"
+               "FROM pg_index i, pg_class c, pg_class c2, pg_am a\n"
+               "WHERE i.indexrelid = c.oid AND c.relname = '%s' AND c.relam = a.oid\n"
+               "AND i.indrelid = c2.oid",
                name);
 
        result = PSQLexec(buf);
@@ -666,27 +674,18 @@ describeTableDetails(const char *name, bool desc)
            char       *indisunique = PQgetvalue(result, 0, 0);
            char       *indisprimary = PQgetvalue(result, 0, 1);
            char       *indamname = PQgetvalue(result, 0, 2);
-           char       *indpred = PQgetvalue(result, 0, 3);
+           char       *indtable = PQgetvalue(result, 0, 3);
+           char       *indpred = PQgetvalue(result, 0, 4);
 
-           footers = xmalloc(3 * sizeof(*footers));
+           footers = xmalloc(2 * sizeof(*footers));
            /* XXX This construction is poorly internationalized. */
-           footers[0] = xmalloc(NAMEDATALEN + 128);
-           snprintf(footers[0], NAMEDATALEN + 128, "%s%s",
+           footers[0] = xmalloc(NAMEDATALEN*4 + 128);
+           snprintf(footers[0], NAMEDATALEN*4 + 128, "%s%s for %s \"%s\"%s%s",
+                    strcmp(indisprimary, "t") == 0 ? _("primary key ") : 
                     strcmp(indisunique, "t") == 0 ? _("unique ") : "",
-                    indamname);
-           if (strcmp(indisprimary, "t") == 0)
-               snprintf(footers[0] + strlen(footers[0]),
-                        NAMEDATALEN + 128 - strlen(footers[0]),
-                        _(" (primary key)"));
-           if (strlen(indpred) > 0)
-           {
-               footers[1] = xmalloc(64 + strlen(indpred));
-               snprintf(footers[1], 64 + strlen(indpred),
-                        _("Index predicate: %s"), indpred);
-               footers[2] = NULL;
-           }
-           else
-               footers[1] = NULL;
+                    indamname, _("table"), indtable, 
+                    strlen(indpred) ? " WHERE " : "",indpred);
+           footers[1] = NULL;
        }
 
        PQclear(result);
@@ -706,12 +705,8 @@ describeTableDetails(const char *name, bool desc)
        PGresult   *result1 = NULL,
                   *result2 = NULL,
                   *result3 = NULL,
-                  *result4 = NULL,
-                  *result5 = NULL,
-                  *result6 = NULL;
+                  *result4 = NULL;
        int         index_count = 0,
-                   primary_count = 0,
-                   unique_count = 0,
                    constr_count = 0,
                    rule_count = 0,
                    trigger_count = 0;
@@ -720,10 +715,12 @@ describeTableDetails(const char *name, bool desc)
        /* count indexes */
        if (!error && tableinfo.hasindex)
        {
-           sprintf(buf, "SELECT c2.relname\n"
+           sprintf(buf, "SELECT c2.relname, i.indisprimary, i.indisunique,\n"
+                   "SUBSTR(pg_get_indexdef(i.indexrelid),\n"
+                   "POSITION('USING ' IN pg_get_indexdef(i.indexrelid))+5)\n"
                    "FROM pg_class c, pg_class c2, pg_index i\n"
                    "WHERE c.relname = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
-                   "AND NOT i.indisunique ORDER BY c2.relname",
+                   "ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname",
                    name);
            result1 = PSQLexec(buf);
            if (!result1)
@@ -732,36 +729,6 @@ describeTableDetails(const char *name, bool desc)
                index_count = PQntuples(result1);
        }
 
-       /* count primary keys */
-       if (!error && tableinfo.hasindex)
-       {
-           sprintf(buf, "SELECT c2.relname\n"
-                   "FROM pg_class c, pg_class c2, pg_index i\n"
-                   "WHERE c.relname = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
-             "AND i.indisprimary AND i.indisunique ORDER BY c2.relname",
-                   name);
-           result5 = PSQLexec(buf);
-           if (!result5)
-               error = true;
-           else
-               primary_count = PQntuples(result5);
-       }
-
-       /* count unique constraints */
-       if (!error && tableinfo.hasindex)
-       {
-           sprintf(buf, "SELECT c2.relname\n"
-                   "FROM pg_class c, pg_class c2, pg_index i\n"
-                   "WHERE c.relname = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
-                   "AND NOT i.indisprimary AND i.indisunique ORDER BY c2.relname",
-                   name);
-           result6 = PSQLexec(buf);
-           if (!result6)
-               error = true;
-           else
-               unique_count = PQntuples(result6);
-       }
-
        /* count table (and column) constraints */
        if (!error && tableinfo.checks)
        {
@@ -806,54 +773,32 @@ describeTableDetails(const char *name, bool desc)
                trigger_count = PQntuples(result4);
        }
 
-       footers = xmalloc((index_count + primary_count + unique_count +
-                          constr_count + rule_count + trigger_count + 1)
+       footers = xmalloc((index_count + constr_count + rule_count + trigger_count + 1)
                          * sizeof(*footers));
 
        /* print indexes */
        for (i = 0; i < index_count; i++)
        {
            char       *s = _("Indexes");
-
+   
            if (i == 0)
                snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result1, i, 0));
            else
                snprintf(buf, sizeof(buf), "%*s  %s", (int) strlen(s), "", PQgetvalue(result1, i, 0));
-           if (i < index_count - 1)
-               strcat(buf, ",");
 
-           footers[count_footers++] = xstrdup(buf);
-       }
+           /* Label as primary key or unique (but not both) */
+           strcat(buf, strcmp(PQgetvalue(result1,i,1),"t") == 0 ? 
+                  _(" primary key") : strcmp(PQgetvalue(result1,i,2),"t") == 0 ? _(" unique") : "");
 
-       /* print primary keys */
-       for (i = 0; i < primary_count; i++)
-       {
-           char       *s = _("Primary key");
+           /* Everything after "USING" is echoed verbatim */
+           strcat(buf, PQgetvalue(result1,i,3));
 
-           if (i == 0)
-               snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result5, i, 0));
-           else
-               snprintf(buf, sizeof(buf), "%*s  %s", (int) strlen(s), "", PQgetvalue(result5, i, 0));
-           if (i < primary_count - 1)
+           if (i < index_count - 1)
                strcat(buf, ",");
 
            footers[count_footers++] = xstrdup(buf);
        }
 
-       /* print unique constraints */
-       for (i = 0; i < unique_count; i++)
-       {
-           char       *s = _("Unique keys");
-
-           if (i == 0)
-               snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result6, i, 0));
-           else
-               snprintf(buf, sizeof(buf), "%*s  %s", (int) strlen(s), "", PQgetvalue(result6, i, 0));
-           if (i < unique_count - 1)
-               strcat(buf, ",");
-
-           footers[count_footers++] = xstrdup(buf);
-       }
 
        /* print constraints */
        for (i = 0; i < constr_count; i++)
@@ -906,8 +851,6 @@ describeTableDetails(const char *name, bool desc)
        PQclear(result2);
        PQclear(result3);
        PQclear(result4);
-       PQclear(result5);
-       PQclear(result6);
    }
 
    if (!error)
@@ -1031,9 +974,19 @@ listTables(const char *infotype, const char *name, bool desc)
        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
                 ",\n  obj_description(c.oid, 'pg_class') as \"%s\"",
                 _("Description"));
-   strcat(buf,
-    "\nFROM pg_class c LEFT JOIN pg_user u ON c.relowner = u.usesysid\n"
-          "WHERE c.relkind IN (");
+    if (showIndexes) {
+       snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+                ",\n c2.relname as \"%s\"",
+                _("Table"));
+       strcat(buf, "\nFROM pg_class c, pg_class c2, pg_index i, pg_user u\n"
+              "WHERE c.relowner = u.usesysid\n"
+              "AND i.indrelid = c2.oid AND i.indexrelid = c.oid\n");
+   }
+   else {
+       strcat(buf, "\nFROM pg_class c, pg_user u\n"
+              "WHERE c.relowner = u.usesysid\n");
+   }
+   strcat(buf, "AND c.relkind IN (");
    if (showTables)
        strcat(buf, "'r',");
    if (showViews)