New \d format:

Example:

test=# \d test
     Table "public.test"
 Column |  Type   | Modifiers
--------+---------+-----------
 a      | integer | not null
Indexes:
    "test_pkey" PRIMARY KEY btree (a)
Check Constraints:
    "$2" CHECK (a > 1)
Foreign Key Constraints:
    "$1" FOREIGN KEY (a) REFERENCES parent(b)
Rules:
    myrule AS ON INSERT TO test DO INSTEAD NOTHING
Triggers:
    "asdf asdf" AFTER INSERT OR DELETE ON test FOR EACH STATEMENT EXECUTE
PROCEDURE update_pg_pwd_and_pg_group(),
    mytrigger AFTER INSERT OR DELETE ON test FOR EACH ROW EXECUTE PROCEDURE
update_pg_pwd_and_pg_group()

I have minimised the double quoting of identifiers as much as I could
easily, and I will submit another patch when I have time to work on it that
will use a 'fmtId' function to determine it exactly.

I think it's a significant improvement in legibility...

Obviously the table example above is slightly degenerate in that not many
tables in production have heaps of (non-constraint) triggers and rules.

Christopher Kings-Lynne
This commit is contained in:
Bruce Momjian 2003-03-27 16:57:39 +00:00
parent 5e8499d995
commit c75d65485d

View File

@ -3,7 +3,7 @@
* *
* Copyright 2000-2002 by PostgreSQL Global Development Group * Copyright 2000-2002 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.75 2003/02/24 03:54:06 tgl Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.76 2003/03/27 16:57:39 momjian Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "describe.h" #include "describe.h"
@ -975,7 +975,7 @@ describeOneTableDetails(const char *schemaname,
if (tableinfo.hasrules) if (tableinfo.hasrules)
{ {
printfPQExpBuffer(&buf, printfPQExpBuffer(&buf,
"SELECT r.rulename\n" "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid))\n"
"FROM pg_catalog.pg_rewrite r\n" "FROM pg_catalog.pg_rewrite r\n"
"WHERE r.ev_class = '%s'", "WHERE r.ev_class = '%s'",
oid); oid);
@ -990,7 +990,7 @@ describeOneTableDetails(const char *schemaname,
if (tableinfo.triggers) if (tableinfo.triggers)
{ {
printfPQExpBuffer(&buf, printfPQExpBuffer(&buf,
"SELECT t.tgname\n" "SELECT t.tgname, pg_catalog.pg_get_triggerdef(t.oid)\n"
"FROM pg_catalog.pg_trigger t\n" "FROM pg_catalog.pg_trigger t\n"
"WHERE t.tgrelid = '%s' " "WHERE t.tgrelid = '%s' "
"and (not tgisconstraint " "and (not tgisconstraint "
@ -1022,113 +1022,120 @@ describeOneTableDetails(const char *schemaname,
foreignkey_count = PQntuples(result5); foreignkey_count = PQntuples(result5);
} }
footers = xmalloczero((index_count + check_count + rule_count + trigger_count + foreignkey_count + 1) footers = xmalloczero((index_count + check_count + rule_count + trigger_count + foreignkey_count + 6)
* sizeof(*footers)); * sizeof(*footers));
/* print indexes */ /* print indexes */
for (i = 0; i < index_count; i++) if (index_count > 0) {
{ printfPQExpBuffer(&buf, _("Indexes:"));
char *s = _("Indexes");
const char *indexdef;
const char *usingpos;
if (i == 0)
printfPQExpBuffer(&buf, "%s: %s", s,
PQgetvalue(result1, i, 0));
else
printfPQExpBuffer(&buf, "%*s %s", (int) strlen(s), "",
PQgetvalue(result1, i, 0));
/* Label as primary key or unique (but not both) */
appendPQExpBuffer(&buf,
strcmp(PQgetvalue(result1, i, 1), "t") == 0
? _(" primary key") :
(strcmp(PQgetvalue(result1, i, 2), "t") == 0
? _(" unique")
: ""));
/* Everything after "USING" is echoed verbatim */
indexdef = PQgetvalue(result1, i, 3);
usingpos = strstr(indexdef, " USING ");
if (usingpos)
indexdef = usingpos + 7;
appendPQExpBuffer(&buf, " %s", indexdef);
if (i < index_count - 1)
appendPQExpBuffer(&buf, ",");
footers[count_footers++] = xstrdup(buf.data); footers[count_footers++] = xstrdup(buf.data);
for (i = 0; i < index_count; i++)
{
const char *indexdef;
const char *usingpos;
/* Output index/constraint name */
printfPQExpBuffer(&buf, " \"%s\"",
PQgetvalue(result1, i, 0));
/* Label as primary key or unique (but not both) */
appendPQExpBuffer(&buf,
strcmp(PQgetvalue(result1, i, 1), "t") == 0
? _(" PRIMARY KEY") :
(strcmp(PQgetvalue(result1, i, 2), "t") == 0
? _(" UNIQUE")
: ""));
/* Everything after "USING" is echoed verbatim */
indexdef = PQgetvalue(result1, i, 3);
usingpos = strstr(indexdef, " USING ");
if (usingpos)
indexdef = usingpos + 7;
appendPQExpBuffer(&buf, " %s", indexdef);
if (i < index_count - 1)
appendPQExpBuffer(&buf, ",");
footers[count_footers++] = xstrdup(buf.data);
}
} }
/* print check constraints */ /* print check constraints */
for (i = 0; i < check_count; i++) if (check_count > 0) {
{ printfPQExpBuffer(&buf, _("Check Constraints:"));
char *s = _("Check constraints");
if (i == 0)
printfPQExpBuffer(&buf, _("%s: \"%s\" %s"),
s,
PQgetvalue(result2, i, 1),
PQgetvalue(result2, i, 0));
else
printfPQExpBuffer(&buf, _("%*s \"%s\" %s"),
(int) strlen(s), "",
PQgetvalue(result2, i, 1),
PQgetvalue(result2, i, 0));
footers[count_footers++] = xstrdup(buf.data); footers[count_footers++] = xstrdup(buf.data);
for (i = 0; i < check_count; i++)
{
printfPQExpBuffer(&buf, _(" \"%s\" CHECK %s"),
PQgetvalue(result2, i, 1),
PQgetvalue(result2, i, 0));
if (i < check_count - 1)
appendPQExpBuffer(&buf, ",");
footers[count_footers++] = xstrdup(buf.data);
}
} }
/* print foreign key constraints */ /* print foreign key constraints */
for (i = 0; i < foreignkey_count; i++) if (foreignkey_count > 0) {
{ printfPQExpBuffer(&buf, _("Foreign Key Constraints:"));
char *s = _("Foreign Key constraints");
if (i == 0)
printfPQExpBuffer(&buf, _("%s: %s %s"),
s,
PQgetvalue(result5, i, 0),
PQgetvalue(result5, i, 1));
else
printfPQExpBuffer(&buf, _("%*s %s %s"),
(int) strlen(s), "",
PQgetvalue(result5, i, 0),
PQgetvalue(result5, i, 1));
if (i < foreignkey_count - 1)
appendPQExpBuffer(&buf, ",");
footers[count_footers++] = xstrdup(buf.data); footers[count_footers++] = xstrdup(buf.data);
for (i = 0; i < foreignkey_count; i++)
{
printfPQExpBuffer(&buf, _(" \"%s\" %s"),
PQgetvalue(result5, i, 0),
PQgetvalue(result5, i, 1));
if (i < foreignkey_count - 1)
appendPQExpBuffer(&buf, ",");
footers[count_footers++] = xstrdup(buf.data);
}
} }
/* print rules */ /* print rules */
for (i = 0; i < rule_count; i++) if (rule_count > 0) {
{ printfPQExpBuffer(&buf, _("Rules:"));
char *s = _("Rules");
if (i == 0)
printfPQExpBuffer(&buf, "%s: %s", s, PQgetvalue(result3, i, 0));
else
printfPQExpBuffer(&buf, "%*s %s", (int) strlen(s), "", PQgetvalue(result3, i, 0));
if (i < rule_count - 1)
appendPQExpBuffer(&buf, ",");
footers[count_footers++] = xstrdup(buf.data); footers[count_footers++] = xstrdup(buf.data);
for (i = 0; i < rule_count; i++)
{
const char *ruledef;
/* Everything after "CREATE RULE" is echoed verbatim */
ruledef = PQgetvalue(result3, i, 1);
ruledef += 12;
printfPQExpBuffer(&buf, " %s", ruledef);
if (i < rule_count - 1)
appendPQExpBuffer(&buf, ",");
footers[count_footers++] = xstrdup(buf.data);
}
} }
/* print triggers */ /* print triggers */
for (i = 0; i < trigger_count; i++) if (trigger_count > 0) {
{ printfPQExpBuffer(&buf, _("Triggers:"));
char *s = _("Triggers");
if (i == 0)
printfPQExpBuffer(&buf, "%s: %s", s, PQgetvalue(result4, i, 0));
else
printfPQExpBuffer(&buf, "%*s %s", (int) strlen(s), "", PQgetvalue(result4, i, 0));
if (i < trigger_count - 1)
appendPQExpBuffer(&buf, ",");
footers[count_footers++] = xstrdup(buf.data); footers[count_footers++] = xstrdup(buf.data);
for (i = 0; i < trigger_count; i++)
{
const char *tgdef;
const char *usingpos;
/* Everything after "TRIGGER" is echoed verbatim */
tgdef = PQgetvalue(result4, i, 1);
usingpos = strstr(tgdef, " TRIGGER ");
if (usingpos)
tgdef = usingpos + 9;
printfPQExpBuffer(&buf, " %s", tgdef);
if (i < trigger_count - 1)
appendPQExpBuffer(&buf, ",");
footers[count_footers++] = xstrdup(buf.data);
}
} }
/* end of list marker */ /* end of list marker */