summaryrefslogtreecommitdiff
path: root/src/bin/psql/describe.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/psql/describe.c')
-rw-r--r--src/bin/psql/describe.c833
1 files changed, 361 insertions, 472 deletions
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 97c3a82efeb..cd807230272 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -3,36 +3,27 @@
*
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.170 2008/05/05 01:21:03 adunstan Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.171 2008/05/12 22:59:58 alvherre Exp $
*/
#include "postgres_fe.h"
-#include "describe.h"
-#include "dumputils.h"
+#include <ctype.h>
#include "common.h"
-#include "settings.h"
+#include "describe.h"
+#include "dumputils.h"
+#include "mbprint.h"
#include "print.h"
+#include "settings.h"
#include "variables.h"
-#include <ctype.h>
-
-#ifdef WIN32
-/*
- * mbvalidate() is used in function describeOneTableDetails() to make sure
- * all characters of the cells will be printed to the DOS console in a
- * correct way
- */
-#include "mbprint.h"
-#endif
-
static bool describeOneTableDetails(const char *schemaname,
const char *relationname,
const char *oid,
bool verbose);
-static bool add_tablespace_footer(char relkind, Oid tablespace, char **footers,
- int *count, PQExpBufferData buf, bool newline);
+static void add_tablespace_footer(printTableContent *const cont, char relkind,
+ Oid tablespace, const bool newline);
static bool listTSParsersVerbose(const char *pattern);
static bool describeOneTSParser(const char *oid, const char *nspname,
const char *prsname);
@@ -789,11 +780,11 @@ describeOneTableDetails(const char *schemaname,
PQExpBufferData buf;
PGresult *res = NULL;
printTableOpt myopt = pset.popt.topt;
+ printTableContent cont;
int i;
char *view_def = NULL;
- const char *headers[5];
- char **cells = NULL;
- char **footers = NULL;
+ char *headers[4];
+ char **modifiers = NULL;
char **ptr;
PQExpBufferData title;
PQExpBufferData tmpbuf;
@@ -852,25 +843,6 @@ describeOneTableDetails(const char *schemaname,
atooid(PQgetvalue(res, 0, 6)) : 0;
PQclear(res);
- headers[0] = _("Column");
- headers[1] = _("Type");
- cols = 2;
-
- if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v')
- {
- show_modifiers = true;
- cols++;
- headers[cols - 1] = _("Modifiers");
- }
-
- if (verbose)
- {
- cols++;
- headers[cols - 1] = _("Description");
- }
-
- headers[cols] = NULL;
-
/* Get column info (index requires additional checks) */
printfPQExpBuffer(&buf, "SELECT a.attname,");
appendPQExpBuffer(&buf, "\n pg_catalog.format_type(a.atttypid, a.atttypmod),"
@@ -893,6 +865,26 @@ describeOneTableDetails(const char *schemaname,
goto error_return;
numrows = PQntuples(res);
+ /* Set the number of columns, and their names */
+ cols = 2;
+ headers[0] = "Column";
+ headers[1] = "Type";
+
+ if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v')
+ {
+ show_modifiers = true;
+ headers[cols++] = "Modifiers";
+ modifiers = pg_malloc_zero((numrows + 1) * sizeof(*modifiers));
+ }
+
+ if (verbose)
+ headers[cols++] = "Description";
+
+ printTableInit(&cont, &myopt, title.data, cols, numrows);
+
+ for (i = 0; i < cols; i++)
+ printTableAddHeader(&cont, headers[i], true, 'l');
+
/* Check if table is a view */
if (tableinfo.relkind == 'v')
{
@@ -910,33 +902,20 @@ describeOneTableDetails(const char *schemaname,
}
/* Generate table cells to be printed */
- /* note: initialize all cells[] to NULL in case of error exit */
- cells = pg_malloc_zero((numrows * cols + 1) * sizeof(*cells));
-
for (i = 0; i < numrows; i++)
{
- /* Name */
-#ifdef WIN32
- cells[i * cols + 0] = mbvalidate(PQgetvalue(res, i, 0), myopt.encoding);
-#else
- cells[i * cols + 0] = PQgetvalue(res, i, 0); /* don't free this
- * afterwards */
-#endif
+ /* Column */
+ printTableAddCell(&cont, PQgetvalue(res, i, 0), false);
/* Type */
-#ifdef WIN32
- cells[i * cols + 1] = mbvalidate(PQgetvalue(res, i, 1), myopt.encoding);
-#else
- cells[i * cols + 1] = PQgetvalue(res, i, 1); /* don't free this
- * either */
-#endif
+ printTableAddCell(&cont, PQgetvalue(res, i, 1), false);
/* Extra: not null and default */
if (show_modifiers)
{
resetPQExpBuffer(&tmpbuf);
if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
- appendPQExpBufferStr(&tmpbuf, "not null");
+ appendPQExpBufferStr(&tmpbuf, _("not null"));
/* handle "default" here */
/* (note: above we cut off the 'default' string at 128) */
@@ -944,24 +923,18 @@ describeOneTableDetails(const char *schemaname,
{
if (tmpbuf.len > 0)
appendPQExpBufferStr(&tmpbuf, " ");
- appendPQExpBuffer(&tmpbuf, "default %s",
+ /* translator: default values of column definitions */
+ appendPQExpBuffer(&tmpbuf, _("default %s"),
PQgetvalue(res, i, 2));
}
-#ifdef WIN32
- cells[i * cols + 2] = pg_strdup(mbvalidate(tmpbuf.data, myopt.encoding));
-#else
- cells[i * cols + 2] = pg_strdup(tmpbuf.data);
-#endif
+ modifiers[i] = pg_strdup(tmpbuf.data);
+ printTableAddCell(&cont, modifiers[i], false);
}
/* Description */
if (verbose)
-#ifdef WIN32
- cells[i * cols + cols - 1] = mbvalidate(PQgetvalue(res, i, 5), myopt.encoding);
-#else
- cells[i * cols + cols - 1] = PQgetvalue(res, i, 5);
-#endif
+ printTableAddCell(&cont, PQgetvalue(res, i, 5), false);
}
/* Make title */
@@ -997,7 +970,8 @@ describeOneTableDetails(const char *schemaname,
schemaname, relationname);
break;
default:
- printfPQExpBuffer(&title, _("?%c? \"%s.%s\""),
+ /* untranslated unknown relkind */
+ printfPQExpBuffer(&title, "?%c? \"%s.%s\"",
tableinfo.relkind, schemaname, relationname);
break;
}
@@ -1033,7 +1007,6 @@ describeOneTableDetails(const char *schemaname,
char *indamname = PQgetvalue(result, 0, 4);
char *indtable = PQgetvalue(result, 0, 5);
char *indpred = PQgetvalue(result, 0, 6);
- int count_footers = 0;
if (strcmp(indisprimary, "t") == 0)
printfPQExpBuffer(&tmpbuf, _("primary key, "));
@@ -1056,11 +1029,9 @@ describeOneTableDetails(const char *schemaname,
if (strcmp(indisvalid, "t") != 0)
appendPQExpBuffer(&tmpbuf, _(", invalid"));
- footers = pg_malloc_zero(4 * sizeof(*footers));
- footers[count_footers++] = pg_strdup(tmpbuf.data);
- add_tablespace_footer(tableinfo.relkind, tableinfo.tablespace,
- footers, &count_footers, tmpbuf, true);
- footers[count_footers] = NULL;
+ printTableAddFooter(&cont, tmpbuf.data);
+ add_tablespace_footer(&cont, tableinfo.relkind,
+ tableinfo.tablespace, true);
}
@@ -1069,10 +1040,12 @@ describeOneTableDetails(const char *schemaname,
else if (view_def)
{
PGresult *result = NULL;
- int rule_count = 0;
- int count_footers = 0;
- /* count rules other than the view rule */
+ /* Footer information about a view */
+ printTableAddFooter(&cont, _("View definition:"));
+ printTableAddFooter(&cont, view_def);
+
+ /* print rules */
if (tableinfo.hasrules)
{
printfPQExpBuffer(&buf,
@@ -1083,60 +1056,32 @@ describeOneTableDetails(const char *schemaname,
result = PSQLexec(buf.data, false);
if (!result)
goto error_return;
- else
- rule_count = PQntuples(result);
- }
- /* Footer information about a view */
- footers = pg_malloc_zero((rule_count + 3) * sizeof(*footers));
- footers[count_footers] = pg_malloc(64 + strlen(view_def));
- snprintf(footers[count_footers], 64 + strlen(view_def),
- _("View definition:\n%s"), view_def);
- count_footers++;
-
- /* print rules */
- if (rule_count > 0)
- {
- printfPQExpBuffer(&buf, _("Rules:"));
- footers[count_footers++] = pg_strdup(buf.data);
- for (i = 0; i < rule_count; i++)
+ if (PQntuples(result) > 0)
{
- const char *ruledef;
-
- /* Everything after "CREATE RULE" is echoed verbatim */
- ruledef = PQgetvalue(result, i, 1);
- ruledef += 12;
+ printTableAddFooter(&cont, _("Rules:"));
+ for (i = 0; i < PQntuples(result); i++)
+ {
+ const char *ruledef;
- printfPQExpBuffer(&buf, " %s", ruledef);
+ /* Everything after "CREATE RULE" is echoed verbatim */
+ ruledef = PQgetvalue(result, i, 1);
+ ruledef += 12;
- footers[count_footers++] = pg_strdup(buf.data);
+ printfPQExpBuffer(&buf, " %s", ruledef);
+ printTableAddFooter(&cont, buf.data);
+ }
}
PQclear(result);
}
-
- footers[count_footers] = NULL;
-
}
else if (tableinfo.relkind == 'r')
{
/* Footer information about a table */
- PGresult *result1 = NULL,
- *result2 = NULL,
- *result3 = NULL,
- *result4 = NULL,
- *result5 = NULL,
- *result6 = NULL,
- *result7 = NULL;
- int check_count = 0,
- index_count = 0,
- foreignkey_count = 0,
- rule_count = 0,
- trigger_count = 0,
- referencedby_count = 0,
- inherits_count = 0;
- int count_footers = 0;
-
- /* count indexes */
+ PGresult *result = NULL;
+ int tuples = 0;
+
+ /* print indexes */
if (tableinfo.hasindex)
{
printfPQExpBuffer(&buf,
@@ -1146,14 +1091,57 @@ describeOneTableDetails(const char *schemaname,
"WHERE c.oid = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
"ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname",
oid);
- result1 = PSQLexec(buf.data, false);
- if (!result1)
+ result = PSQLexec(buf.data, false);
+ if (!result)
goto error_return;
else
- index_count = PQntuples(result1);
+ tuples = PQntuples(result);
+
+ if (tuples > 0)
+ {
+ printTableAddFooter(&cont, _("Indexes:"));
+ for (i = 0; i < tuples; i++)
+ {
+ const char *indexdef;
+ const char *usingpos;
+
+ /* untranslated index name */
+ printfPQExpBuffer(&buf, " \"%s\"",
+ PQgetvalue(result, i, 0));
+
+ /* Label as primary key or unique (but not both) */
+ appendPQExpBuffer(&buf,
+ strcmp(PQgetvalue(result, i, 1), "t") == 0
+ ? " PRIMARY KEY," :
+ (strcmp(PQgetvalue(result, i, 2), "t") == 0
+ ? " UNIQUE,"
+ : ""));
+ /* Everything after "USING" is echoed verbatim */
+ indexdef = PQgetvalue(result, i, 5);
+ usingpos = strstr(indexdef, " USING ");
+ if (usingpos)
+ indexdef = usingpos + 7;
+
+ appendPQExpBuffer(&buf, " %s", indexdef);
+
+ if (strcmp(PQgetvalue(result, i, 3), "t") == 0)
+ appendPQExpBuffer(&buf, " CLUSTER");
+
+ if (strcmp(PQgetvalue(result, i, 4), "t") != 0)
+ appendPQExpBuffer(&buf, " INVALID");
+
+ printTableAddFooter(&cont, buf.data);
+
+ /* Print tablespace of the index on the same line */
+ add_tablespace_footer(&cont, 'i',
+ atooid(PQgetvalue(result, i, 6)),
+ false);
+ }
+ }
+ PQclear(result);
}
- /* count table (and column) check constraints */
+ /* print table (and column) check constraints */
if (tableinfo.checks)
{
printfPQExpBuffer(&buf,
@@ -1162,72 +1150,29 @@ describeOneTableDetails(const char *schemaname,
"FROM pg_catalog.pg_constraint r\n"
"WHERE r.conrelid = '%s' AND r.contype = 'c' ORDER BY 1",
oid);
- result2 = PSQLexec(buf.data, false);
- if (!result2)
- {
- PQclear(result1);
+ result = PSQLexec(buf.data, false);
+ if (!result)
goto error_return;
- }
else
- check_count = PQntuples(result2);
- }
+ tuples = PQntuples(result);
- /* count rules */
- if (tableinfo.hasrules)
- {
- if (pset.sversion < 80300)
+ if (tuples > 0)
{
- printfPQExpBuffer(&buf,
- "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
- "'O'::char AS ev_enabled\n"
- "FROM pg_catalog.pg_rewrite r\n"
- "WHERE r.ev_class = '%s' ORDER BY 1",
- oid);
- }
- else
- {
- printfPQExpBuffer(&buf,
- "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
- "ev_enabled\n"
- "FROM pg_catalog.pg_rewrite r\n"
- "WHERE r.ev_class = '%s' ORDER BY 1",
- oid);
- }
- result3 = PSQLexec(buf.data, false);
- if (!result3)
- {
- PQclear(result1);
- PQclear(result2);
- goto error_return;
- }
- else
- rule_count = PQntuples(result3);
- }
+ printTableAddFooter(&cont, _("Check constraints:"));
+ for (i = 0; i < tuples; i++)
+ {
+ /* untranslated contraint name and def */
+ printfPQExpBuffer(&buf, " \"%s\" %s",
+ PQgetvalue(result, i, 0),
+ PQgetvalue(result, i, 1));
- /* count triggers (but ignore foreign-key triggers) */
- if (tableinfo.triggers)
- {
- printfPQExpBuffer(&buf,
- "SELECT t.tgname, pg_catalog.pg_get_triggerdef(t.oid), "
- "t.tgenabled\n"
- "FROM pg_catalog.pg_trigger t\n"
- "WHERE t.tgrelid = '%s' "
- "AND t.tgconstraint = 0\n"
- "ORDER BY 1",
- oid);
- result4 = PSQLexec(buf.data, false);
- if (!result4)
- {
- PQclear(result1);
- PQclear(result2);
- PQclear(result3);
- goto error_return;
+ printTableAddFooter(&cont, buf.data);
+ }
}
- else
- trigger_count = PQntuples(result4);
+ PQclear(result);
}
- /* count foreign-key constraints (there are none if no triggers) */
+ /* print foreign-key constraints (there are none if no triggers) */
if (tableinfo.triggers)
{
printfPQExpBuffer(&buf,
@@ -1236,20 +1181,29 @@ describeOneTableDetails(const char *schemaname,
"FROM pg_catalog.pg_constraint r\n"
"WHERE r.conrelid = '%s' AND r.contype = 'f' ORDER BY 1",
oid);
- result5 = PSQLexec(buf.data, false);
- if (!result5)
- {
- PQclear(result1);
- PQclear(result2);
- PQclear(result3);
- PQclear(result4);
+ result = PSQLexec(buf.data, false);
+ if (!result)
goto error_return;
- }
else
- foreignkey_count = PQntuples(result5);
+ tuples = PQntuples(result);
+
+ if (tuples > 0)
+ {
+ printTableAddFooter(&cont, _("Foreign-key constraints:"));
+ for (i = 0; i < tuples; i++)
+ {
+ /* untranslated constraint name and def */
+ printfPQExpBuffer(&buf, " \"%s\" %s",
+ PQgetvalue(result, i, 0),
+ PQgetvalue(result, i, 1));
+
+ printTableAddFooter(&cont, buf.data);
+ }
+ }
+ PQclear(result);
}
- /* count incoming foreign-key references (none if no triggers) */
+ /* print incoming foreign-key references (none if no triggers) */
if (tableinfo.triggers)
{
printfPQExpBuffer(&buf,
@@ -1258,303 +1212,247 @@ describeOneTableDetails(const char *schemaname,
"FROM pg_catalog.pg_constraint c\n"
"WHERE c.confrelid = '%s' AND c.contype = 'f' ORDER BY 1",
oid);
- result6 = PSQLexec(buf.data, false);
- if (!result6)
- {
- PQclear(result1);
- PQclear(result2);
- PQclear(result3);
- PQclear(result4);
- PQclear(result5);
+ result = PSQLexec(buf.data, false);
+ if (!result)
goto error_return;
- }
else
- referencedby_count = PQntuples(result6);
- }
+ tuples = PQntuples(result);
- /* count inherited tables */
- printfPQExpBuffer(&buf, "SELECT c.oid::pg_catalog.regclass FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i WHERE c.oid=i.inhparent AND i.inhrelid = '%s' ORDER BY inhseqno", oid);
-
- result7 = PSQLexec(buf.data, false);
- if (!result7)
- {
- PQclear(result1);
- PQclear(result2);
- PQclear(result3);
- PQclear(result4);
- PQclear(result5);
- PQclear(result6);
- goto error_return;
- }
- else
- inherits_count = PQntuples(result7);
-
- footers = pg_malloc_zero((index_count + check_count + rule_count + trigger_count + foreignkey_count + referencedby_count + inherits_count + 8 + 1) * sizeof(*footers));
-
- /* print indexes */
- if (index_count > 0)
- {
- printfPQExpBuffer(&buf, _("Indexes:"));
- footers[count_footers++] = pg_strdup(buf.data);
- for (i = 0; i < index_count; i++)
+ if (tuples > 0)
{
- const char *indexdef;
- const char *usingpos;
- PQExpBufferData tmpbuf;
-
- /* Output index 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, 5);
- usingpos = strstr(indexdef, " USING ");
- if (usingpos)
- indexdef = usingpos + 7;
-
- appendPQExpBuffer(&buf, " %s", indexdef);
-
- if (strcmp(PQgetvalue(result1, i, 3), "t") == 0)
- appendPQExpBuffer(&buf, " CLUSTER");
-
- if (strcmp(PQgetvalue(result1, i, 4), "t") != 0)
- appendPQExpBuffer(&buf, " INVALID");
-
- /* Print tablespace of the index on the same line */
- count_footers += 1;
- initPQExpBuffer(&tmpbuf);
- if (add_tablespace_footer('i',
- atooid(PQgetvalue(result1, i, 6)),
- footers, &count_footers, tmpbuf, false))
+ printTableAddFooter(&cont, _("Referenced by:"));
+ for (i = 0; i < tuples; i++)
{
- appendPQExpBuffer(&buf, ", ");
- appendPQExpBuffer(&buf, tmpbuf.data);
-
- count_footers -= 2;
+ /* translator: the first %s is a FK name, the following are
+ * a table name and the FK definition */
+ printfPQExpBuffer(&buf, _(" \"%s\" IN %s %s"),
+ PQgetvalue(result, i, 0),
+ PQgetvalue(result, i, 1),
+ PQgetvalue(result, i, 2));
+
+ printTableAddFooter(&cont, buf.data);
}
- else
- count_footers -= 1;
- termPQExpBuffer(&tmpbuf);
-
- footers[count_footers++] = pg_strdup(buf.data);
- }
- }
-
- /* print check constraints */
- if (check_count > 0)
- {
- printfPQExpBuffer(&buf, _("Check constraints:"));
- footers[count_footers++] = pg_strdup(buf.data);
- for (i = 0; i < check_count; i++)
- {
- printfPQExpBuffer(&buf, _(" \"%s\" %s"),
- PQgetvalue(result2, i, 0),
- PQgetvalue(result2, i, 1));
-
- footers[count_footers++] = pg_strdup(buf.data);
}
+ PQclear(result);
}
- /* print foreign key constraints */
- if (foreignkey_count > 0)
+ /* print rules */
+ if (tableinfo.hasrules)
{
- printfPQExpBuffer(&buf, _("Foreign-key constraints:"));
- footers[count_footers++] = pg_strdup(buf.data);
- for (i = 0; i < foreignkey_count; i++)
+ if (pset.sversion < 80300)
{
- printfPQExpBuffer(&buf, _(" \"%s\" %s"),
- PQgetvalue(result5, i, 0),
- PQgetvalue(result5, i, 1));
-
- footers[count_footers++] = pg_strdup(buf.data);
+ printfPQExpBuffer(&buf,
+ "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
+ "'O'::char AS ev_enabled\n"
+ "FROM pg_catalog.pg_rewrite r\n"
+ "WHERE r.ev_class = '%s' ORDER BY 1",
+ oid);
}
- }
-
- /* print incoming foreign-key constraints */
- if (referencedby_count > 0)
- {
- printfPQExpBuffer(&buf, _("Referenced by:"));
- footers[count_footers++] = pg_strdup(buf.data);
- for (i = 0; i < referencedby_count; i++)
+ else
{
- printfPQExpBuffer(&buf, _(" \"%s\" IN %s %s"),
- PQgetvalue(result6, i, 0),
- PQgetvalue(result6, i, 1),
- PQgetvalue(result6, i, 2));
-
- footers[count_footers++] = pg_strdup(buf.data);
+ printfPQExpBuffer(&buf,
+ "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
+ "ev_enabled\n"
+ "FROM pg_catalog.pg_rewrite r\n"
+ "WHERE r.ev_class = '%s' ORDER BY 1",
+ oid);
}
- }
-
- /* print rules */
- if (rule_count > 0)
- {
- bool have_heading;
- int category;
+ result = PSQLexec(buf.data, false);
+ if (!result)
+ goto error_return;
+ else
+ tuples = PQntuples(result);
- for (category = 0; category < 4; category++)
+ if (tuples > 0)
{
- have_heading = false;
+ bool have_heading;
+ int category;
- for (i = 0; i < rule_count; i++)
+ for (category = 0; category < 4; category++)
{
- const char *ruledef;
- bool list_rule = false;
+ have_heading = false;
- switch (category)
+ for (i = 0; i < tuples; i++)
{
- case 0:
- if (*PQgetvalue(result3, i, 2) == 'O')
- list_rule = true;
- break;
- case 1:
- if (*PQgetvalue(result3, i, 2) == 'D')
- list_rule = true;
- break;
- case 2:
- if (*PQgetvalue(result3, i, 2) == 'A')
- list_rule = true;
- break;
- case 3:
- if (*PQgetvalue(result3, i, 2) == 'R')
- list_rule = true;
- break;
- }
- if (!list_rule)
- continue;
+ const char *ruledef;
+ bool list_rule = false;
- if (!have_heading)
- {
switch (category)
{
case 0:
- printfPQExpBuffer(&buf, _("Rules:"));
+ if (*PQgetvalue(result, i, 2) == 'O')
+ list_rule = true;
break;
case 1:
- printfPQExpBuffer(&buf, _("Disabled rules:"));
+ if (*PQgetvalue(result, i, 2) == 'D')
+ list_rule = true;
break;
case 2:
- printfPQExpBuffer(&buf, _("Rules firing always:"));
+ if (*PQgetvalue(result, i, 2) == 'A')
+ list_rule = true;
break;
case 3:
- printfPQExpBuffer(&buf, _("Rules firing on replica only:"));
+ if (*PQgetvalue(result, i, 2) == 'R')
+ list_rule = true;
break;
}
- footers[count_footers++] = pg_strdup(buf.data);
- have_heading = true;
- }
+ if (!list_rule)
+ continue;
- /* Everything after "CREATE RULE" is echoed verbatim */
- ruledef = PQgetvalue(result3, i, 1);
- ruledef += 12;
- printfPQExpBuffer(&buf, " %s", ruledef);
- footers[count_footers++] = pg_strdup(buf.data);
+ if (!have_heading)
+ {
+ switch (category)
+ {
+ case 0:
+ printfPQExpBuffer(&buf, _("Rules:"));
+ break;
+ case 1:
+ printfPQExpBuffer(&buf, _("Disabled rules:"));
+ break;
+ case 2:
+ printfPQExpBuffer(&buf, _("Rules firing always:"));
+ break;
+ case 3:
+ printfPQExpBuffer(&buf, _("Rules firing on replica only:"));
+ break;
+ }
+ printTableAddFooter(&cont, buf.data);
+ have_heading = true;
+ }
+
+ /* Everything after "CREATE RULE" is echoed verbatim */
+ ruledef = PQgetvalue(result, i, 1);
+ ruledef += 12;
+ printfPQExpBuffer(&buf, " %s", ruledef);
+ printTableAddFooter(&cont, buf.data);
+ }
}
}
+ PQclear(result);
}
- /* print triggers */
- if (trigger_count > 0)
+ /* print triggers (but ignore foreign-key triggers) */
+ if (tableinfo.triggers)
{
- bool have_heading;
- int category;
-
- /*
- * split the output into 4 different categories. Enabled triggers,
- * disabled triggers and the two special ALWAYS and REPLICA
- * configurations.
- */
- for (category = 0; category < 4; category++)
+ printfPQExpBuffer(&buf,
+ "SELECT t.tgname, pg_catalog.pg_get_triggerdef(t.oid), "
+ "t.tgenabled\n"
+ "FROM pg_catalog.pg_trigger t\n"
+ "WHERE t.tgrelid = '%s' "
+ "AND t.tgconstraint = 0\n"
+ "ORDER BY 1",
+ oid);
+ result = PSQLexec(buf.data, false);
+ if (!result)
+ goto error_return;
+ else
+ tuples = PQntuples(result);
+
+ if (tuples > 0)
{
- have_heading = false;
- for (i = 0; i < trigger_count; i++)
+ bool have_heading;
+ int category;
+
+ /*
+ * split the output into 4 different categories. Enabled triggers,
+ * disabled triggers and the two special ALWAYS and REPLICA
+ * configurations.
+ */
+ for (category = 0; category < 4; category++)
{
- bool list_trigger;
- const char *tgdef;
- const char *usingpos;
- const char *tgenabled;
-
- /* Check if this trigger falls into the current category */
- tgenabled = PQgetvalue(result4, i, 2);
- list_trigger = false;
- switch (category)
- {
- case 0:
- if (*tgenabled == 'O' || *tgenabled == 't')
- list_trigger = true;
- break;
- case 1:
- if (*tgenabled == 'D' || *tgenabled == 'f')
- list_trigger = true;
- break;
- case 2:
- if (*tgenabled == 'A')
- list_trigger = true;
- break;
- case 3:
- if (*tgenabled == 'R')
- list_trigger = true;
- break;
- }
- if (list_trigger == false)
- continue;
-
- /* Print the category heading once */
- if (have_heading == false)
+ have_heading = false;
+ for (i = 0; i < tuples; i++)
{
+ bool list_trigger;
+ const char *tgdef;
+ const char *usingpos;
+ const char *tgenabled;
+
+ /* Check if this trigger falls into the current category */
+ tgenabled = PQgetvalue(result, i, 2);
+ list_trigger = false;
switch (category)
{
case 0:
- printfPQExpBuffer(&buf, _("Triggers:"));
+ if (*tgenabled == 'O' || *tgenabled == 't')
+ list_trigger = true;
break;
case 1:
- printfPQExpBuffer(&buf, _("Disabled triggers:"));
+ if (*tgenabled == 'D' || *tgenabled == 'f')
+ list_trigger = true;
break;
case 2:
- printfPQExpBuffer(&buf, _("Triggers firing always:"));
+ if (*tgenabled == 'A')
+ list_trigger = true;
break;
case 3:
- printfPQExpBuffer(&buf, _("Triggers firing on replica only:"));
+ if (*tgenabled == 'R')
+ list_trigger = true;
break;
+ }
+ if (list_trigger == false)
+ continue;
+ /* Print the category heading once */
+ if (have_heading == false)
+ {
+ switch (category)
+ {
+ case 0:
+ printfPQExpBuffer(&buf, _("Triggers:"));
+ break;
+ case 1:
+ printfPQExpBuffer(&buf, _("Disabled triggers:"));
+ break;
+ case 2:
+ printfPQExpBuffer(&buf, _("Triggers firing always:"));
+ break;
+ case 3:
+ printfPQExpBuffer(&buf, _("Triggers firing on replica only:"));
+ break;
+
+ }
+ printTableAddFooter(&cont, buf.data);
+ have_heading = true;
}
- footers[count_footers++] = pg_strdup(buf.data);
- have_heading = true;
- }
- /* Everything after "TRIGGER" is echoed verbatim */
- tgdef = PQgetvalue(result4, i, 1);
- usingpos = strstr(tgdef, " TRIGGER ");
- if (usingpos)
- tgdef = usingpos + 9;
+ /* Everything after "TRIGGER" is echoed verbatim */
+ tgdef = PQgetvalue(result, i, 1);
+ usingpos = strstr(tgdef, " TRIGGER ");
+ if (usingpos)
+ tgdef = usingpos + 9;
- printfPQExpBuffer(&buf, " %s", tgdef);
- footers[count_footers++] = pg_strdup(buf.data);
+ printfPQExpBuffer(&buf, " %s", tgdef);
+ printTableAddFooter(&cont, buf.data);
+ }
}
}
+ PQclear(result);
}
- /* print inherits */
- for (i = 0; i < inherits_count; i++)
+ /* print inherited tables */
+ printfPQExpBuffer(&buf, "SELECT c.oid::pg_catalog.regclass FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i WHERE c.oid=i.inhparent AND i.inhrelid = '%s' ORDER BY inhseqno", oid);
+
+ result = PSQLexec(buf.data, false);
+ if (!result)
+ goto error_return;
+ else
+ tuples = PQntuples(result);
+
+ for (i = 0; i < tuples; i++)
{
const char *s = _("Inherits");
if (i == 0)
- printfPQExpBuffer(&buf, "%s: %s", s, PQgetvalue(result7, i, 0));
+ printfPQExpBuffer(&buf, "%s: %s", s, PQgetvalue(result, i, 0));
else
- printfPQExpBuffer(&buf, "%*s %s", (int) strlen(s), "", PQgetvalue(result7, i, 0));
- if (i < inherits_count - 1)
+ printfPQExpBuffer(&buf, "%*s %s", (int) strlen(s), "", PQgetvalue(result, i, 0));
+ if (i < tuples - 1)
appendPQExpBuffer(&buf, ",");
- footers[count_footers++] = pg_strdup(buf.data);
+ printTableAddFooter(&cont, buf.data);
}
+ PQclear(result);
if (verbose)
{
@@ -1562,51 +1460,31 @@ describeOneTableDetails(const char *schemaname,
printfPQExpBuffer(&buf, "%s: %s", s,
(tableinfo.hasoids ? _("yes") : _("no")));
- footers[count_footers++] = pg_strdup(buf.data);
+ printTableAddFooter(&cont, buf.data);
}
- add_tablespace_footer(tableinfo.relkind, tableinfo.tablespace,
- footers, &count_footers, buf, true);
- /* end of list marker */
- footers[count_footers] = NULL;
-
- PQclear(result1);
- PQclear(result2);
- PQclear(result3);
- PQclear(result4);
- PQclear(result5);
- PQclear(result6);
- PQclear(result7);
+ add_tablespace_footer(&cont, tableinfo.relkind, tableinfo.tablespace,
+ true);
}
- printTable(title.data, headers,
- (const char **) cells, (const char **) footers,
- "llll", &myopt, pset.queryFout, pset.logfile);
+ printTable(&cont, pset.queryFout, pset.logfile);
+ printTableCleanup(&cont);
retval = true;
error_return:
/* clean up */
+ printTableCleanup(&cont);
termPQExpBuffer(&buf);
termPQExpBuffer(&title);
termPQExpBuffer(&tmpbuf);
- if (cells)
- {
- for (i = 0; i < numrows; i++)
- {
- if (show_modifiers)
- free(cells[i * cols + 2]);
- }
- free(cells);
- }
-
- if (footers)
+ if (show_modifiers)
{
- for (ptr = footers; *ptr; ptr++)
+ for (ptr = modifiers; *ptr; ptr++)
free(*ptr);
- free(footers);
+ free(modifiers);
}
if (view_def)
@@ -1618,14 +1496,14 @@ error_return:
return retval;
}
-
/*
- * Return true if the relation uses non default tablespace;
- * otherwise return false
+ * 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
+ * footer.
*/
-static bool
-add_tablespace_footer(char relkind, Oid tablespace, char **footers,
- int *count, PQExpBufferData buf, bool newline)
+static void
+add_tablespace_footer(printTableContent *const cont, char relkind,
+ Oid tablespace, const bool newline)
{
/* relkinds for which we support tablespaces */
if (relkind == 'r' || relkind == 'i')
@@ -1636,29 +1514,40 @@ add_tablespace_footer(char relkind, Oid tablespace, char **footers,
*/
if (tablespace != 0)
{
- PGresult *result1 = NULL;
+ PGresult *result = NULL;
+ PQExpBufferData buf;
+ initPQExpBuffer(&buf);
printfPQExpBuffer(&buf, "SELECT spcname FROM pg_tablespace \n"
"WHERE oid = '%u';", tablespace);
- result1 = PSQLexec(buf.data, false);
- if (!result1)
- return false;
+ result = PSQLexec(buf.data, false);
+ if (!result)
+ return;
/* Should always be the case, but.... */
- if (PQntuples(result1) > 0)
+ if (PQntuples(result) > 0)
{
- printfPQExpBuffer(&buf,
- newline ? _("Tablespace: \"%s\"") : _("tablespace \"%s\""),
- PQgetvalue(result1, 0, 0));
-
- footers[(*count)++] = pg_strdup(buf.data);
+ if (newline)
+ {
+ /* Add the tablespace as a new footer */
+ printfPQExpBuffer(&buf, _("Tablespace: \"%s\""),
+ PQgetvalue(result, 0, 0));
+ printTableAddFooter(cont, buf.data);
+ }
+ else
+ {
+ /* Append the tablespace to the latest footer */
+ printfPQExpBuffer(&buf, "%s", cont->footer->data);
+ /* translator: before this string there's an index
+ * description like '"foo_pkey" PRIMARY KEY, btree (a)' */
+ appendPQExpBuffer(&buf, _(", tablespace \"%s\""),
+ PQgetvalue(result, 0, 0));
+ printTableSetFooter(cont, buf.data);
+ }
}
- PQclear(result1);
-
- return true;
+ PQclear(result);
+ termPQExpBuffer(&buf);
}
}
-
- return false;
}
/*