PostgreSQL Source Code  git master
describe.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include "catalog/pg_attribute_d.h"
#include "catalog/pg_class_d.h"
#include "catalog/pg_default_acl_d.h"
#include "fe_utils/string_utils.h"
#include "common.h"
#include "describe.h"
#include "fe_utils/mbprint.h"
#include "fe_utils/print.h"
#include "settings.h"
#include "variables.h"
Include dependency graph for describe.c:

Go to the source code of this file.

Functions

static bool describeOneTableDetails (const char *schemaname, const char *relationname, const char *oid, bool verbose)
 
static void add_tablespace_footer (printTableContent *const cont, char relkind, Oid tablespace, const bool newline)
 
static void add_role_attribute (PQExpBuffer buf, const char *const str)
 
static bool listTSParsersVerbose (const char *pattern)
 
static bool describeOneTSParser (const char *oid, const char *nspname, const char *prsname)
 
static bool listTSConfigsVerbose (const char *pattern)
 
static bool describeOneTSConfig (const char *oid, const char *nspname, const char *cfgname, const char *pnspname, const char *prsname)
 
static void printACLColumn (PQExpBuffer buf, const char *colname)
 
static bool listOneExtensionContents (const char *extname, const char *oid)
 
bool describeAggregates (const char *pattern, bool verbose, bool showSystem)
 
bool describeAccessMethods (const char *pattern, bool verbose)
 
bool describeTablespaces (const char *pattern, bool verbose)
 
bool describeFunctions (const char *functypes, const char *pattern, bool verbose, bool showSystem)
 
bool describeTypes (const char *pattern, bool verbose, bool showSystem)
 
bool describeOperators (const char *pattern, bool verbose, bool showSystem)
 
bool listAllDbs (const char *pattern, bool verbose)
 
bool permissionsList (const char *pattern)
 
bool listDefaultACLs (const char *pattern)
 
bool objectDescription (const char *pattern, bool showSystem)
 
bool describeTableDetails (const char *pattern, bool verbose, bool showSystem)
 
bool describeRoles (const char *pattern, bool verbose, bool showSystem)
 
bool listDbRoleSettings (const char *pattern, const char *pattern2)
 
bool listTables (const char *tabtypes, const char *pattern, bool verbose, bool showSystem)
 
bool listLanguages (const char *pattern, bool verbose, bool showSystem)
 
bool listDomains (const char *pattern, bool verbose, bool showSystem)
 
bool listConversions (const char *pattern, bool verbose, bool showSystem)
 
bool listEventTriggers (const char *pattern, bool verbose)
 
bool listCasts (const char *pattern, bool verbose)
 
bool listCollations (const char *pattern, bool verbose, bool showSystem)
 
bool listSchemas (const char *pattern, bool verbose, bool showSystem)
 
bool listTSParsers (const char *pattern, bool verbose)
 
bool listTSDictionaries (const char *pattern, bool verbose)
 
bool listTSTemplates (const char *pattern, bool verbose)
 
bool listTSConfigs (const char *pattern, bool verbose)
 
bool listForeignDataWrappers (const char *pattern, bool verbose)
 
bool listForeignServers (const char *pattern, bool verbose)
 
bool listUserMappings (const char *pattern, bool verbose)
 
bool listForeignTables (const char *pattern, bool verbose)
 
bool listExtensions (const char *pattern)
 
bool listExtensionContents (const char *pattern)
 
bool listPublications (const char *pattern)
 
bool describePublications (const char *pattern)
 
bool describeSubscriptions (const char *pattern, bool verbose)
 

Function Documentation

◆ add_role_attribute()

static void add_role_attribute ( PQExpBuffer  buf,
const char *const  str 
)
static

Definition at line 3316 of file describe.c.

References appendPQExpBufferStr(), and PQExpBufferData::len.

Referenced by describeRoles().

3317 {
3318  if (buf->len > 0)
3319  appendPQExpBufferStr(buf, ", ");
3320 
3321  appendPQExpBufferStr(buf, str);
3322 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385

◆ add_tablespace_footer()

static void add_tablespace_footer ( printTableContent *const  cont,
char  relkind,
Oid  tablespace,
const bool  newline 
)
static

Definition at line 3093 of file describe.c.

References _, appendPQExpBuffer(), buf, PQExpBufferData::data, printTableFooter::data, printTableContent::footer, initPQExpBuffer(), PQclear(), PQgetvalue(), PQntuples(), printfPQExpBuffer(), printTableAddFooter(), printTableSetFooter(), PSQLexec(), and termPQExpBuffer().

Referenced by describeOneTableDetails().

3095 {
3096  /* relkinds for which we support tablespaces */
3097  if (relkind == RELKIND_RELATION ||
3098  relkind == RELKIND_MATVIEW ||
3099  relkind == RELKIND_INDEX ||
3100  relkind == RELKIND_PARTITIONED_TABLE)
3101  {
3102  /*
3103  * We ignore the database default tablespace so that users not using
3104  * tablespaces don't need to know about them. This case also covers
3105  * pre-8.0 servers, for which tablespace will always be 0.
3106  */
3107  if (tablespace != 0)
3108  {
3109  PGresult *result = NULL;
3111 
3112  initPQExpBuffer(&buf);
3113  printfPQExpBuffer(&buf,
3114  "SELECT spcname FROM pg_catalog.pg_tablespace\n"
3115  "WHERE oid = '%u';", tablespace);
3116  result = PSQLexec(buf.data);
3117  if (!result)
3118  {
3119  termPQExpBuffer(&buf);
3120  return;
3121  }
3122  /* Should always be the case, but.... */
3123  if (PQntuples(result) > 0)
3124  {
3125  if (newline)
3126  {
3127  /* Add the tablespace as a new footer */
3128  printfPQExpBuffer(&buf, _("Tablespace: \"%s\""),
3129  PQgetvalue(result, 0, 0));
3130  printTableAddFooter(cont, buf.data);
3131  }
3132  else
3133  {
3134  /* Append the tablespace to the latest footer */
3135  printfPQExpBuffer(&buf, "%s", cont->footer->data);
3136 
3137  /*-------
3138  translator: before this string there's an index description like
3139  '"foo_pkey" PRIMARY KEY, btree (a)' */
3140  appendPQExpBuffer(&buf, _(", tablespace \"%s\""),
3141  PQgetvalue(result, 0, 0));
3142  printTableSetFooter(cont, buf.data);
3143  }
3144  }
3145  PQclear(result);
3146  termPQExpBuffer(&buf);
3147  }
3148  }
3149 }
void printTableSetFooter(printTableContent *const content, const char *footer)
Definition: print.c:3083
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
static chr newline(void)
Definition: regc_lex.c:1138
char relkind
Definition: pg_class.h:51
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
char * tablespace
Definition: pgbench.c:156
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition: print.c:3058
printTableFooter * footer
Definition: print.h:157
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * data
Definition: print.h:135
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ describeAccessMethods()

bool describeAccessMethods ( const char *  pattern,
bool  verbose 
)

Definition at line 148 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, psql_error(), PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by exec_command_d().

149 {
151  PGresult *res;
152  printQueryOpt myopt = pset.popt;
153  static const bool translate_columns[] = {false, true, false, false};
154 
155  if (pset.sversion < 90600)
156  {
157  char sverbuf[32];
158 
159  psql_error("The server (version %s) does not support access methods.\n",
161  sverbuf, sizeof(sverbuf)));
162  return true;
163  }
164 
165  initPQExpBuffer(&buf);
166 
167  printfPQExpBuffer(&buf,
168  "SELECT amname AS \"%s\",\n"
169  " CASE amtype"
170  " WHEN 'i' THEN '%s'"
171  " END AS \"%s\"",
172  gettext_noop("Name"),
173  gettext_noop("Index"),
174  gettext_noop("Type"));
175 
176  if (verbose)
177  {
178  appendPQExpBuffer(&buf,
179  ",\n amhandler AS \"%s\",\n"
180  " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"",
181  gettext_noop("Handler"),
182  gettext_noop("Description"));
183  }
184 
186  "\nFROM pg_catalog.pg_am\n");
187 
188  processSQLNamePattern(pset.db, &buf, pattern, false, false,
189  NULL, "amname", NULL,
190  NULL);
191 
192  appendPQExpBufferStr(&buf, "ORDER BY 1;");
193 
194  res = PSQLexec(buf.data);
195  termPQExpBuffer(&buf);
196  if (!res)
197  return false;
198 
199  myopt.nullPrint = NULL;
200  myopt.title = _("List of access methods");
201  myopt.translate_header = true;
202  myopt.translate_columns = translate_columns;
203  myopt.n_translate_columns = lengthof(translate_columns);
204 
205  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
206 
207  PQclear(res);
208  return true;
209 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
#define lengthof(array)
Definition: c.h:629
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
static int verbose
Definition: pg_basebackup.c:88
void psql_error(const char *fmt,...)
Definition: common.c:221
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:172
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
const bool * translate_columns
Definition: print.h:170
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:182
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ describeAggregates()

bool describeAggregates ( const char *  pattern,
bool  verbose,
bool  showSystem 
)

Definition at line 62 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, and printQueryOpt::translate_header.

Referenced by exec_command_d().

63 {
65  PGresult *res;
66  printQueryOpt myopt = pset.popt;
67 
68  initPQExpBuffer(&buf);
69 
70  printfPQExpBuffer(&buf,
71  "SELECT n.nspname as \"%s\",\n"
72  " p.proname AS \"%s\",\n"
73  " pg_catalog.format_type(p.prorettype, NULL) AS \"%s\",\n",
74  gettext_noop("Schema"),
75  gettext_noop("Name"),
76  gettext_noop("Result data type"));
77 
78  if (pset.sversion >= 80400)
79  appendPQExpBuffer(&buf,
80  " CASE WHEN p.pronargs = 0\n"
81  " THEN CAST('*' AS pg_catalog.text)\n"
82  " ELSE pg_catalog.pg_get_function_arguments(p.oid)\n"
83  " END AS \"%s\",\n",
84  gettext_noop("Argument data types"));
85  else if (pset.sversion >= 80200)
86  appendPQExpBuffer(&buf,
87  " CASE WHEN p.pronargs = 0\n"
88  " THEN CAST('*' AS pg_catalog.text)\n"
89  " ELSE\n"
90  " pg_catalog.array_to_string(ARRAY(\n"
91  " SELECT\n"
92  " pg_catalog.format_type(p.proargtypes[s.i], NULL)\n"
93  " FROM\n"
94  " pg_catalog.generate_series(0, pg_catalog.array_upper(p.proargtypes, 1)) AS s(i)\n"
95  " ), ', ')\n"
96  " END AS \"%s\",\n",
97  gettext_noop("Argument data types"));
98  else
99  appendPQExpBuffer(&buf,
100  " pg_catalog.format_type(p.proargtypes[0], NULL) AS \"%s\",\n",
101  gettext_noop("Argument data types"));
102 
103  if (pset.sversion >= 110000)
104  appendPQExpBuffer(&buf,
105  " pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"\n"
106  "FROM pg_catalog.pg_proc p\n"
107  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"
108  "WHERE p.prokind = 'a'\n",
109  gettext_noop("Description"));
110  else
111  appendPQExpBuffer(&buf,
112  " pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"\n"
113  "FROM pg_catalog.pg_proc p\n"
114  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"
115  "WHERE p.proisagg\n",
116  gettext_noop("Description"));
117 
118  if (!showSystem && !pattern)
119  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
120  " AND n.nspname <> 'information_schema'\n");
121 
122  processSQLNamePattern(pset.db, &buf, pattern, true, false,
123  "n.nspname", "p.proname", NULL,
124  "pg_catalog.pg_function_is_visible(p.oid)");
125 
126  appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
127 
128  res = PSQLexec(buf.data);
129  termPQExpBuffer(&buf);
130  if (!res)
131  return false;
132 
133  myopt.nullPrint = NULL;
134  myopt.title = _("List of aggregate functions");
135  myopt.translate_header = true;
136 
137  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
138 
139  PQclear(res);
140  return true;
141 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ describeFunctions()

bool describeFunctions ( const char *  functypes,
const char *  pattern,
bool  verbose,
bool  showSystem 
)

Definition at line 311 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, psql_error(), PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by exec_command_d().

312 {
313  bool showAggregate = strchr(functypes, 'a') != NULL;
314  bool showNormal = strchr(functypes, 'n') != NULL;
315  bool showTrigger = strchr(functypes, 't') != NULL;
316  bool showWindow = strchr(functypes, 'w') != NULL;
317  bool have_where;
319  PGresult *res;
320  printQueryOpt myopt = pset.popt;
321  static const bool translate_columns[] = {false, false, false, false, true, true, true, false, true, false, false, false, false};
322 
323  /* No "Parallel" column before 9.6 */
324  static const bool translate_columns_pre_96[] = {false, false, false, false, true, true, false, true, false, false, false, false};
325 
326  if (strlen(functypes) != strspn(functypes, "antwS+"))
327  {
328  psql_error("\\df only takes [antwS+] as options\n");
329  return true;
330  }
331 
332  if (showWindow && pset.sversion < 80400)
333  {
334  char sverbuf[32];
335 
336  psql_error("\\df does not take a \"w\" option with server version %s\n",
338  sverbuf, sizeof(sverbuf)));
339  return true;
340  }
341 
342  if (!showAggregate && !showNormal && !showTrigger && !showWindow)
343  {
344  showAggregate = showNormal = showTrigger = true;
345  if (pset.sversion >= 80400)
346  showWindow = true;
347  }
348 
349  initPQExpBuffer(&buf);
350 
351  printfPQExpBuffer(&buf,
352  "SELECT n.nspname as \"%s\",\n"
353  " p.proname as \"%s\",\n",
354  gettext_noop("Schema"),
355  gettext_noop("Name"));
356 
357  if (pset.sversion >= 110000)
358  appendPQExpBuffer(&buf,
359  " pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n"
360  " pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n"
361  " CASE p.prokind\n"
362  " WHEN 'a' THEN '%s'\n"
363  " WHEN 'w' THEN '%s'\n"
364  " WHEN 'p' THEN '%s'\n"
365  " ELSE '%s'\n"
366  " END as \"%s\"",
367  gettext_noop("Result data type"),
368  gettext_noop("Argument data types"),
369  /* translator: "agg" is short for "aggregate" */
370  gettext_noop("agg"),
371  gettext_noop("window"),
372  gettext_noop("proc"),
373  gettext_noop("func"),
374  gettext_noop("Type"));
375  else if (pset.sversion >= 80400)
376  appendPQExpBuffer(&buf,
377  " pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n"
378  " pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n"
379  " CASE\n"
380  " WHEN p.proisagg THEN '%s'\n"
381  " WHEN p.proiswindow THEN '%s'\n"
382  " WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN '%s'\n"
383  " ELSE '%s'\n"
384  " END as \"%s\"",
385  gettext_noop("Result data type"),
386  gettext_noop("Argument data types"),
387  /* translator: "agg" is short for "aggregate" */
388  gettext_noop("agg"),
389  gettext_noop("window"),
390  gettext_noop("trigger"),
391  gettext_noop("func"),
392  gettext_noop("Type"));
393  else if (pset.sversion >= 80100)
394  appendPQExpBuffer(&buf,
395  " CASE WHEN p.proretset THEN 'SETOF ' ELSE '' END ||\n"
396  " pg_catalog.format_type(p.prorettype, NULL) as \"%s\",\n"
397  " CASE WHEN proallargtypes IS NOT NULL THEN\n"
398  " pg_catalog.array_to_string(ARRAY(\n"
399  " SELECT\n"
400  " CASE\n"
401  " WHEN p.proargmodes[s.i] = 'i' THEN ''\n"
402  " WHEN p.proargmodes[s.i] = 'o' THEN 'OUT '\n"
403  " WHEN p.proargmodes[s.i] = 'b' THEN 'INOUT '\n"
404  " WHEN p.proargmodes[s.i] = 'v' THEN 'VARIADIC '\n"
405  " END ||\n"
406  " CASE\n"
407  " WHEN COALESCE(p.proargnames[s.i], '') = '' THEN ''\n"
408  " ELSE p.proargnames[s.i] || ' '\n"
409  " END ||\n"
410  " pg_catalog.format_type(p.proallargtypes[s.i], NULL)\n"
411  " FROM\n"
412  " pg_catalog.generate_series(1, pg_catalog.array_upper(p.proallargtypes, 1)) AS s(i)\n"
413  " ), ', ')\n"
414  " ELSE\n"
415  " pg_catalog.array_to_string(ARRAY(\n"
416  " SELECT\n"
417  " CASE\n"
418  " WHEN COALESCE(p.proargnames[s.i+1], '') = '' THEN ''\n"
419  " ELSE p.proargnames[s.i+1] || ' '\n"
420  " END ||\n"
421  " pg_catalog.format_type(p.proargtypes[s.i], NULL)\n"
422  " FROM\n"
423  " pg_catalog.generate_series(0, pg_catalog.array_upper(p.proargtypes, 1)) AS s(i)\n"
424  " ), ', ')\n"
425  " END AS \"%s\",\n"
426  " CASE\n"
427  " WHEN p.proisagg THEN '%s'\n"
428  " WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN '%s'\n"
429  " ELSE '%s'\n"
430  " END AS \"%s\"",
431  gettext_noop("Result data type"),
432  gettext_noop("Argument data types"),
433  /* translator: "agg" is short for "aggregate" */
434  gettext_noop("agg"),
435  gettext_noop("trigger"),
436  gettext_noop("func"),
437  gettext_noop("Type"));
438  else
439  appendPQExpBuffer(&buf,
440  " CASE WHEN p.proretset THEN 'SETOF ' ELSE '' END ||\n"
441  " pg_catalog.format_type(p.prorettype, NULL) as \"%s\",\n"
442  " pg_catalog.oidvectortypes(p.proargtypes) as \"%s\",\n"
443  " CASE\n"
444  " WHEN p.proisagg THEN '%s'\n"
445  " WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN '%s'\n"
446  " ELSE '%s'\n"
447  " END AS \"%s\"",
448  gettext_noop("Result data type"),
449  gettext_noop("Argument data types"),
450  /* translator: "agg" is short for "aggregate" */
451  gettext_noop("agg"),
452  gettext_noop("trigger"),
453  gettext_noop("func"),
454  gettext_noop("Type"));
455 
456  if (verbose)
457  {
458  appendPQExpBuffer(&buf,
459  ",\n CASE\n"
460  " WHEN p.provolatile = 'i' THEN '%s'\n"
461  " WHEN p.provolatile = 's' THEN '%s'\n"
462  " WHEN p.provolatile = 'v' THEN '%s'\n"
463  " END as \"%s\"",
464  gettext_noop("immutable"),
465  gettext_noop("stable"),
466  gettext_noop("volatile"),
467  gettext_noop("Volatility"));
468  if (pset.sversion >= 90600)
469  appendPQExpBuffer(&buf,
470  ",\n CASE\n"
471  " WHEN p.proparallel = 'r' THEN '%s'\n"
472  " WHEN p.proparallel = 's' THEN '%s'\n"
473  " WHEN p.proparallel = 'u' THEN '%s'\n"
474  " END as \"%s\"",
475  gettext_noop("restricted"),
476  gettext_noop("safe"),
477  gettext_noop("unsafe"),
478  gettext_noop("Parallel"));
479  appendPQExpBuffer(&buf,
480  ",\n pg_catalog.pg_get_userbyid(p.proowner) as \"%s\""
481  ",\n CASE WHEN prosecdef THEN '%s' ELSE '%s' END AS \"%s\"",
482  gettext_noop("Owner"),
483  gettext_noop("definer"),
484  gettext_noop("invoker"),
485  gettext_noop("Security"));
486  appendPQExpBufferStr(&buf, ",\n ");
487  printACLColumn(&buf, "p.proacl");
488  appendPQExpBuffer(&buf,
489  ",\n l.lanname as \"%s\""
490  ",\n p.prosrc as \"%s\""
491  ",\n pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"",
492  gettext_noop("Language"),
493  gettext_noop("Source code"),
494  gettext_noop("Description"));
495  }
496 
498  "\nFROM pg_catalog.pg_proc p"
499  "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n");
500 
501  if (verbose)
503  " LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang\n");
504 
505  have_where = false;
506 
507  /* filter by function type, if requested */
508  if (showNormal && showAggregate && showTrigger && showWindow)
509  /* Do nothing */ ;
510  else if (showNormal)
511  {
512  if (!showAggregate)
513  {
514  if (have_where)
515  appendPQExpBufferStr(&buf, " AND ");
516  else
517  {
518  appendPQExpBufferStr(&buf, "WHERE ");
519  have_where = true;
520  }
521  if (pset.sversion >= 110000)
522  appendPQExpBufferStr(&buf, "p.prokind <> 'a'\n");
523  else
524  appendPQExpBufferStr(&buf, "NOT p.proisagg\n");
525  }
526  if (!showTrigger)
527  {
528  if (have_where)
529  appendPQExpBufferStr(&buf, " AND ");
530  else
531  {
532  appendPQExpBufferStr(&buf, "WHERE ");
533  have_where = true;
534  }
535  appendPQExpBufferStr(&buf, "p.prorettype <> 'pg_catalog.trigger'::pg_catalog.regtype\n");
536  }
537  if (!showWindow && pset.sversion >= 80400)
538  {
539  if (have_where)
540  appendPQExpBufferStr(&buf, " AND ");
541  else
542  {
543  appendPQExpBufferStr(&buf, "WHERE ");
544  have_where = true;
545  }
546  if (pset.sversion >= 110000)
547  appendPQExpBufferStr(&buf, "p.prokind <> 'w'\n");
548  else
549  appendPQExpBufferStr(&buf, "NOT p.proiswindow\n");
550  }
551  }
552  else
553  {
554  bool needs_or = false;
555 
556  appendPQExpBufferStr(&buf, "WHERE (\n ");
557  have_where = true;
558  /* Note: at least one of these must be true ... */
559  if (showAggregate)
560  {
561  if (pset.sversion >= 110000)
562  appendPQExpBufferStr(&buf, "p.prokind = 'a'\n");
563  else
564  appendPQExpBufferStr(&buf, "p.proisagg\n");
565  needs_or = true;
566  }
567  if (showTrigger)
568  {
569  if (needs_or)
570  appendPQExpBufferStr(&buf, " OR ");
572  "p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype\n");
573  needs_or = true;
574  }
575  if (showWindow)
576  {
577  if (needs_or)
578  appendPQExpBufferStr(&buf, " OR ");
579  if (pset.sversion >= 110000)
580  appendPQExpBufferStr(&buf, "p.prokind = 'w'\n");
581  else
582  appendPQExpBufferStr(&buf, "p.proiswindow\n");
583  needs_or = true;
584  }
585  appendPQExpBufferStr(&buf, " )\n");
586  }
587 
588  processSQLNamePattern(pset.db, &buf, pattern, have_where, false,
589  "n.nspname", "p.proname", NULL,
590  "pg_catalog.pg_function_is_visible(p.oid)");
591 
592  if (!showSystem && !pattern)
593  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
594  " AND n.nspname <> 'information_schema'\n");
595 
596  appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
597 
598  res = PSQLexec(buf.data);
599  termPQExpBuffer(&buf);
600  if (!res)
601  return false;
602 
603  myopt.nullPrint = NULL;
604  myopt.title = _("List of functions");
605  myopt.translate_header = true;
606  if (pset.sversion >= 90600)
607  {
608  myopt.translate_columns = translate_columns;
609  myopt.n_translate_columns = lengthof(translate_columns);
610  }
611  else
612  {
613  myopt.translate_columns = translate_columns_pre_96;
614  myopt.n_translate_columns = lengthof(translate_columns_pre_96);
615  }
616 
617  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
618 
619  PQclear(res);
620  return true;
621 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
#define lengthof(array)
Definition: c.h:629
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
static int verbose
Definition: pg_basebackup.c:88
void psql_error(const char *fmt,...)
Definition: common.c:221
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:172
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
const bool * translate_columns
Definition: print.h:170
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition: describe.c:5493
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:182
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ describeOneTableDetails()

static bool describeOneTableDetails ( const char *  schemaname,
const char *  relationname,
const char *  oid,
bool  verbose 
)
static

Definition at line 1408 of file describe.c.

References _, add_tablespace_footer(), appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), atooid, buf, CppAsString2, PQExpBufferData::data, printTableOpt::default_footer, _psqlSettings::encoding, printTableOpt::expanded, fmtId(), printQueryOpt::footers, free, gettext_noop, i, initPQExpBuffer(), _psqlSettings::logfile, pg_strdup(), pg_wcswidth(), _psqlSettings::popt, PQclear(), PQgetisnull(), PQgetvalue(), PQnfields(), PQntuples(), printfPQExpBuffer(), printQuery(), printTable(), printTableAddCell(), printTableAddFooter(), printTableAddHeader(), printTableCleanup(), printTableInit(), pset, psprintf(), psql_error(), PSQLexec(), _psqlSettings::queryFout, _psqlSettings::quiet, relkind, reloftype, relpersistence, relreplident, resetPQExpBuffer(), _psqlSettings::sversion, tablespace, termPQExpBuffer(), printQueryOpt::title, tmpbuf, printQueryOpt::topt, and printQueryOpt::translate_header.

Referenced by describeTableDetails().

1412 {
1414  PGresult *res = NULL;
1415  printTableOpt myopt = pset.popt.topt;
1416  printTableContent cont;
1417  bool printTableInitialized = false;
1418  int i;
1419  char *view_def = NULL;
1420  char *headers[11];
1421  PQExpBufferData title;
1423  int cols;
1424  int numrows = 0;
1425  struct
1426  {
1427  int16 checks;
1428  char relkind;
1429  bool hasindex;
1430  bool hasrules;
1431  bool hastriggers;
1432  bool rowsecurity;
1433  bool forcerowsecurity;
1434  bool hasoids;
1435  Oid tablespace;
1436  char *reloptions;
1437  char *reloftype;
1438  char relpersistence;
1439  char relreplident;
1440  } tableinfo;
1441  bool show_column_details = false;
1442  bool retval;
1443 
1444  retval = false;
1445 
1446  myopt.default_footer = false;
1447  /* This output looks confusing in expanded mode. */
1448  myopt.expanded = false;
1449 
1450  initPQExpBuffer(&buf);
1451  initPQExpBuffer(&title);
1452  initPQExpBuffer(&tmpbuf);
1453 
1454  /* Get general table info */
1455  if (pset.sversion >= 90500)
1456  {
1457  printfPQExpBuffer(&buf,
1458  "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
1459  "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
1460  "c.relhasoids, %s, c.reltablespace, "
1461  "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
1462  "c.relpersistence, c.relreplident\n"
1463  "FROM pg_catalog.pg_class c\n "
1464  "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
1465  "WHERE c.oid = '%s';",
1466  (verbose ?
1467  "pg_catalog.array_to_string(c.reloptions || "
1468  "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
1469  : "''"),
1470  oid);
1471  }
1472  else if (pset.sversion >= 90400)
1473  {
1474  printfPQExpBuffer(&buf,
1475  "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
1476  "c.relhastriggers, false, false, c.relhasoids, "
1477  "%s, c.reltablespace, "
1478  "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
1479  "c.relpersistence, c.relreplident\n"
1480  "FROM pg_catalog.pg_class c\n "
1481  "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
1482  "WHERE c.oid = '%s';",
1483  (verbose ?
1484  "pg_catalog.array_to_string(c.reloptions || "
1485  "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
1486  : "''"),
1487  oid);
1488  }
1489  else if (pset.sversion >= 90100)
1490  {
1491  printfPQExpBuffer(&buf,
1492  "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
1493  "c.relhastriggers, false, false, c.relhasoids, "
1494  "%s, c.reltablespace, "
1495  "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
1496  "c.relpersistence\n"
1497  "FROM pg_catalog.pg_class c\n "
1498  "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
1499  "WHERE c.oid = '%s';",
1500  (verbose ?
1501  "pg_catalog.array_to_string(c.reloptions || "
1502  "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
1503  : "''"),
1504  oid);
1505  }
1506  else if (pset.sversion >= 90000)
1507  {
1508  printfPQExpBuffer(&buf,
1509  "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
1510  "c.relhastriggers, false, false, c.relhasoids, "
1511  "%s, c.reltablespace, "
1512  "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END\n"
1513  "FROM pg_catalog.pg_class c\n "
1514  "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
1515  "WHERE c.oid = '%s';",
1516  (verbose ?
1517  "pg_catalog.array_to_string(c.reloptions || "
1518  "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
1519  : "''"),
1520  oid);
1521  }
1522  else if (pset.sversion >= 80400)
1523  {
1524  printfPQExpBuffer(&buf,
1525  "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
1526  "c.relhastriggers, false, false, c.relhasoids, "
1527  "%s, c.reltablespace\n"
1528  "FROM pg_catalog.pg_class c\n "
1529  "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
1530  "WHERE c.oid = '%s';",
1531  (verbose ?
1532  "pg_catalog.array_to_string(c.reloptions || "
1533  "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
1534  : "''"),
1535  oid);
1536  }
1537  else if (pset.sversion >= 80200)
1538  {
1539  printfPQExpBuffer(&buf,
1540  "SELECT relchecks, relkind, relhasindex, relhasrules, "
1541  "reltriggers <> 0, false, false, relhasoids, "
1542  "%s, reltablespace\n"
1543  "FROM pg_catalog.pg_class WHERE oid = '%s';",
1544  (verbose ?
1545  "pg_catalog.array_to_string(reloptions, E', ')" : "''"),
1546  oid);
1547  }
1548  else if (pset.sversion >= 80000)
1549  {
1550  printfPQExpBuffer(&buf,
1551  "SELECT relchecks, relkind, relhasindex, relhasrules, "
1552  "reltriggers <> 0, false, false, relhasoids, "
1553  "'', reltablespace\n"
1554  "FROM pg_catalog.pg_class WHERE oid = '%s';",
1555  oid);
1556  }
1557  else
1558  {
1559  printfPQExpBuffer(&buf,
1560  "SELECT relchecks, relkind, relhasindex, relhasrules, "
1561  "reltriggers <> 0, false, false, relhasoids, "
1562  "'', ''\n"
1563  "FROM pg_catalog.pg_class WHERE oid = '%s';",
1564  oid);
1565  }
1566 
1567  res = PSQLexec(buf.data);
1568  if (!res)
1569  goto error_return;
1570 
1571  /* Did we get anything? */
1572  if (PQntuples(res) == 0)
1573  {
1574  if (!pset.quiet)
1575  psql_error("Did not find any relation with OID %s.\n", oid);
1576  goto error_return;
1577  }
1578 
1579  tableinfo.checks = atoi(PQgetvalue(res, 0, 0));
1580  tableinfo.relkind = *(PQgetvalue(res, 0, 1));
1581  tableinfo.hasindex = strcmp(PQgetvalue(res, 0, 2), "t") == 0;
1582  tableinfo.hasrules = strcmp(PQgetvalue(res, 0, 3), "t") == 0;
1583  tableinfo.hastriggers = strcmp(PQgetvalue(res, 0, 4), "t") == 0;
1584  tableinfo.rowsecurity = strcmp(PQgetvalue(res, 0, 5), "t") == 0;
1585  tableinfo.forcerowsecurity = strcmp(PQgetvalue(res, 0, 6), "t") == 0;
1586  tableinfo.hasoids = strcmp(PQgetvalue(res, 0, 7), "t") == 0;
1587  tableinfo.reloptions = (pset.sversion >= 80200) ?
1588  pg_strdup(PQgetvalue(res, 0, 8)) : NULL;
1589  tableinfo.tablespace = (pset.sversion >= 80000) ?
1590  atooid(PQgetvalue(res, 0, 9)) : 0;
1591  tableinfo.reloftype = (pset.sversion >= 90000 &&
1592  strcmp(PQgetvalue(res, 0, 10), "") != 0) ?
1593  pg_strdup(PQgetvalue(res, 0, 10)) : NULL;
1594  tableinfo.relpersistence = (pset.sversion >= 90100) ?
1595  *(PQgetvalue(res, 0, 11)) : 0;
1596  tableinfo.relreplident = (pset.sversion >= 90400) ?
1597  *(PQgetvalue(res, 0, 12)) : 'd';
1598  PQclear(res);
1599  res = NULL;
1600 
1601  /*
1602  * If it's a sequence, deal with it here separately.
1603  */
1604  if (tableinfo.relkind == RELKIND_SEQUENCE)
1605  {
1606  PGresult *result = NULL;
1607  printQueryOpt myopt = pset.popt;
1608  char *footers[2] = {NULL, NULL};
1609 
1610  if (pset.sversion >= 100000)
1611  {
1612  printfPQExpBuffer(&buf,
1613  "SELECT pg_catalog.format_type(seqtypid, NULL) AS \"%s\",\n"
1614  " seqstart AS \"%s\",\n"
1615  " seqmin AS \"%s\",\n"
1616  " seqmax AS \"%s\",\n"
1617  " seqincrement AS \"%s\",\n"
1618  " CASE WHEN seqcycle THEN '%s' ELSE '%s' END AS \"%s\",\n"
1619  " seqcache AS \"%s\"\n",
1620  gettext_noop("Type"),
1621  gettext_noop("Start"),
1622  gettext_noop("Minimum"),
1623  gettext_noop("Maximum"),
1624  gettext_noop("Increment"),
1625  gettext_noop("yes"),
1626  gettext_noop("no"),
1627  gettext_noop("Cycles?"),
1628  gettext_noop("Cache"));
1629  appendPQExpBuffer(&buf,
1630  "FROM pg_catalog.pg_sequence\n"
1631  "WHERE seqrelid = '%s';",
1632  oid);
1633  }
1634  else
1635  {
1636  printfPQExpBuffer(&buf,
1637  "SELECT 'bigint' AS \"%s\",\n"
1638  " start_value AS \"%s\",\n"
1639  " min_value AS \"%s\",\n"
1640  " max_value AS \"%s\",\n"
1641  " increment_by AS \"%s\",\n"
1642  " CASE WHEN is_cycled THEN '%s' ELSE '%s' END AS \"%s\",\n"
1643  " cache_value AS \"%s\"\n",
1644  gettext_noop("Type"),
1645  gettext_noop("Start"),
1646  gettext_noop("Minimum"),
1647  gettext_noop("Maximum"),
1648  gettext_noop("Increment"),
1649  gettext_noop("yes"),
1650  gettext_noop("no"),
1651  gettext_noop("Cycles?"),
1652  gettext_noop("Cache"));
1653  appendPQExpBuffer(&buf, "FROM %s", fmtId(schemaname));
1654  /* must be separate because fmtId isn't reentrant */
1655  appendPQExpBuffer(&buf, ".%s;", fmtId(relationname));
1656  }
1657 
1658  res = PSQLexec(buf.data);
1659  if (!res)
1660  goto error_return;
1661 
1662  /* Footer information about a sequence */
1663 
1664  /* Get the column that owns this sequence */
1665  printfPQExpBuffer(&buf, "SELECT pg_catalog.quote_ident(nspname) || '.' ||"
1666  "\n pg_catalog.quote_ident(relname) || '.' ||"
1667  "\n pg_catalog.quote_ident(attname),"
1668  "\n d.deptype"
1669  "\nFROM pg_catalog.pg_class c"
1670  "\nINNER JOIN pg_catalog.pg_depend d ON c.oid=d.refobjid"
1671  "\nINNER JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace"
1672  "\nINNER JOIN pg_catalog.pg_attribute a ON ("
1673  "\n a.attrelid=c.oid AND"
1674  "\n a.attnum=d.refobjsubid)"
1675  "\nWHERE d.classid='pg_catalog.pg_class'::pg_catalog.regclass"
1676  "\n AND d.refclassid='pg_catalog.pg_class'::pg_catalog.regclass"
1677  "\n AND d.objid='%s'"
1678  "\n AND d.deptype IN ('a', 'i')",
1679  oid);
1680 
1681  result = PSQLexec(buf.data);
1682 
1683  /*
1684  * If we get no rows back, don't show anything (obviously). We should
1685  * never get more than one row back, but if we do, just ignore it and
1686  * don't print anything.
1687  */
1688  if (!result)
1689  goto error_return;
1690  else if (PQntuples(result) == 1)
1691  {
1692  switch (PQgetvalue(result, 0, 1)[0])
1693  {
1694  case 'a':
1695  footers[0] = psprintf(_("Owned by: %s"),
1696  PQgetvalue(result, 0, 0));
1697  break;
1698  case 'i':
1699  footers[0] = psprintf(_("Sequence for identity column: %s"),
1700  PQgetvalue(result, 0, 0));
1701  break;
1702  }
1703  }
1704  PQclear(result);
1705 
1706  printfPQExpBuffer(&title, _("Sequence \"%s.%s\""),
1707  schemaname, relationname);
1708 
1709  myopt.footers = footers;
1710  myopt.topt.default_footer = false;
1711  myopt.title = title.data;
1712  myopt.translate_header = true;
1713 
1714  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1715 
1716  if (footers[0])
1717  free(footers[0]);
1718 
1719  retval = true;
1720  goto error_return; /* not an error, just return early */
1721  }
1722 
1723  /*
1724  * Get column info
1725  *
1726  * You need to modify value of "firstvcol" which will be defined below if
1727  * you are adding column(s) preceding to verbose-only columns.
1728  */
1729  printfPQExpBuffer(&buf, "SELECT a.attname,");
1730  appendPQExpBufferStr(&buf, "\n pg_catalog.format_type(a.atttypid, a.atttypmod),"
1731  "\n (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)"
1732  "\n FROM pg_catalog.pg_attrdef d"
1733  "\n WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef),"
1734  "\n a.attnotnull, a.attnum,");
1735  if (pset.sversion >= 90100)
1736  appendPQExpBufferStr(&buf, "\n (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type t\n"
1737  " WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation) AS attcollation");
1738  else
1739  appendPQExpBufferStr(&buf, "\n NULL AS attcollation");
1740  if (pset.sversion >= 100000)
1741  appendPQExpBufferStr(&buf, ",\n a.attidentity");
1742  else
1743  appendPQExpBufferStr(&buf, ",\n ''::pg_catalog.char AS attidentity");
1744  if (tableinfo.relkind == RELKIND_INDEX ||
1745  tableinfo.relkind == RELKIND_PARTITIONED_INDEX)
1746  appendPQExpBufferStr(&buf, ",\n pg_catalog.pg_get_indexdef(a.attrelid, a.attnum, TRUE) AS indexdef");
1747  else
1748  appendPQExpBufferStr(&buf, ",\n NULL AS indexdef");
1749  if (tableinfo.relkind == RELKIND_FOREIGN_TABLE && pset.sversion >= 90200)
1750  appendPQExpBufferStr(&buf, ",\n CASE WHEN attfdwoptions IS NULL THEN '' ELSE "
1751  " '(' || pg_catalog.array_to_string(ARRAY(SELECT pg_catalog.quote_ident(option_name) || ' ' || pg_catalog.quote_literal(option_value) FROM "
1752  " pg_catalog.pg_options_to_table(attfdwoptions)), ', ') || ')' END AS attfdwoptions");
1753  else
1754  appendPQExpBufferStr(&buf, ",\n NULL AS attfdwoptions");
1755  if (verbose)
1756  {
1757  appendPQExpBufferStr(&buf, ",\n a.attstorage");
1758  appendPQExpBufferStr(&buf, ",\n CASE WHEN a.attstattarget=-1 THEN NULL ELSE a.attstattarget END AS attstattarget");
1759 
1760  /*
1761  * In 9.0+, we have column comments for: relations, views, composite
1762  * types, and foreign tables (cf. CommentObject() in comment.c).
1763  */
1764  if (tableinfo.relkind == RELKIND_RELATION ||
1765  tableinfo.relkind == RELKIND_VIEW ||
1766  tableinfo.relkind == RELKIND_MATVIEW ||
1767  tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
1768  tableinfo.relkind == RELKIND_COMPOSITE_TYPE ||
1769  tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
1770  appendPQExpBufferStr(&buf, ", pg_catalog.col_description(a.attrelid, a.attnum)");
1771  }
1772 
1773  appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_attribute a");
1774  appendPQExpBuffer(&buf, "\nWHERE a.attrelid = '%s' AND a.attnum > 0 AND NOT a.attisdropped", oid);
1775  appendPQExpBufferStr(&buf, "\nORDER BY a.attnum;");
1776 
1777  res = PSQLexec(buf.data);
1778  if (!res)
1779  goto error_return;
1780  numrows = PQntuples(res);
1781 
1782  /* Make title */
1783  switch (tableinfo.relkind)
1784  {
1785  case RELKIND_RELATION:
1786  if (tableinfo.relpersistence == 'u')
1787  printfPQExpBuffer(&title, _("Unlogged table \"%s.%s\""),
1788  schemaname, relationname);
1789  else
1790  printfPQExpBuffer(&title, _("Table \"%s.%s\""),
1791  schemaname, relationname);
1792  break;
1793  case RELKIND_VIEW:
1794  printfPQExpBuffer(&title, _("View \"%s.%s\""),
1795  schemaname, relationname);
1796  break;
1797  case RELKIND_MATVIEW:
1798  if (tableinfo.relpersistence == 'u')
1799  printfPQExpBuffer(&title, _("Unlogged materialized view \"%s.%s\""),
1800  schemaname, relationname);
1801  else
1802  printfPQExpBuffer(&title, _("Materialized view \"%s.%s\""),
1803  schemaname, relationname);
1804  break;
1805  case RELKIND_INDEX:
1806  case RELKIND_PARTITIONED_INDEX:
1807  if (tableinfo.relpersistence == 'u')
1808  printfPQExpBuffer(&title, _("Unlogged index \"%s.%s\""),
1809  schemaname, relationname);
1810  else
1811  printfPQExpBuffer(&title, _("Index \"%s.%s\""),
1812  schemaname, relationname);
1813  break;
1814  case 's':
1815  /* not used as of 8.2, but keep it for backwards compatibility */
1816  printfPQExpBuffer(&title, _("Special relation \"%s.%s\""),
1817  schemaname, relationname);
1818  break;
1819  case RELKIND_TOASTVALUE:
1820  printfPQExpBuffer(&title, _("TOAST table \"%s.%s\""),
1821  schemaname, relationname);
1822  break;
1823  case RELKIND_COMPOSITE_TYPE:
1824  printfPQExpBuffer(&title, _("Composite type \"%s.%s\""),
1825  schemaname, relationname);
1826  break;
1827  case RELKIND_FOREIGN_TABLE:
1828  printfPQExpBuffer(&title, _("Foreign table \"%s.%s\""),
1829  schemaname, relationname);
1830  break;
1831  case RELKIND_PARTITIONED_TABLE:
1832  if (tableinfo.relpersistence == 'u')
1833  printfPQExpBuffer(&title, _("Unlogged table \"%s.%s\""),
1834  schemaname, relationname);
1835  else
1836  printfPQExpBuffer(&title, _("Table \"%s.%s\""),
1837  schemaname, relationname);
1838  break;
1839  default:
1840  /* untranslated unknown relkind */
1841  printfPQExpBuffer(&title, "?%c? \"%s.%s\"",
1842  tableinfo.relkind, schemaname, relationname);
1843  break;
1844  }
1845 
1846  /* Set the number of columns, and their names */
1847  headers[0] = gettext_noop("Column");
1848  headers[1] = gettext_noop("Type");
1849  cols = 2;
1850 
1851  if (tableinfo.relkind == RELKIND_RELATION ||
1852  tableinfo.relkind == RELKIND_VIEW ||
1853  tableinfo.relkind == RELKIND_MATVIEW ||
1854  tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
1855  tableinfo.relkind == RELKIND_COMPOSITE_TYPE ||
1856  tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
1857  {
1858  headers[cols++] = gettext_noop("Collation");
1859  headers[cols++] = gettext_noop("Nullable");
1860  headers[cols++] = gettext_noop("Default");
1861  show_column_details = true;
1862  }
1863 
1864  if (tableinfo.relkind == RELKIND_INDEX ||
1865  tableinfo.relkind == RELKIND_PARTITIONED_INDEX)
1866  headers[cols++] = gettext_noop("Definition");
1867 
1868  if (tableinfo.relkind == RELKIND_FOREIGN_TABLE && pset.sversion >= 90200)
1869  headers[cols++] = gettext_noop("FDW options");
1870 
1871  if (verbose)
1872  {
1873  headers[cols++] = gettext_noop("Storage");
1874  if (tableinfo.relkind == RELKIND_RELATION ||
1875  tableinfo.relkind == RELKIND_INDEX ||
1876  tableinfo.relkind == RELKIND_PARTITIONED_INDEX ||
1877  tableinfo.relkind == RELKIND_MATVIEW ||
1878  tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
1879  tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
1880  headers[cols++] = gettext_noop("Stats target");
1881  /* Column comments, if the relkind supports this feature. */
1882  if (tableinfo.relkind == RELKIND_RELATION ||
1883  tableinfo.relkind == RELKIND_VIEW ||
1884  tableinfo.relkind == RELKIND_MATVIEW ||
1885  tableinfo.relkind == RELKIND_COMPOSITE_TYPE ||
1886  tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
1887  tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
1888  headers[cols++] = gettext_noop("Description");
1889  }
1890 
1891  printTableInit(&cont, &myopt, title.data, cols, numrows);
1892  printTableInitialized = true;
1893 
1894  for (i = 0; i < cols; i++)
1895  printTableAddHeader(&cont, headers[i], true, 'l');
1896 
1897  /* Get view_def if table is a view or materialized view */
1898  if ((tableinfo.relkind == RELKIND_VIEW ||
1899  tableinfo.relkind == RELKIND_MATVIEW) && verbose)
1900  {
1901  PGresult *result;
1902 
1903  printfPQExpBuffer(&buf,
1904  "SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid, true);",
1905  oid);
1906  result = PSQLexec(buf.data);
1907  if (!result)
1908  goto error_return;
1909 
1910  if (PQntuples(result) > 0)
1911  view_def = pg_strdup(PQgetvalue(result, 0, 0));
1912 
1913  PQclear(result);
1914  }
1915 
1916  /* Generate table cells to be printed */
1917  for (i = 0; i < numrows; i++)
1918  {
1919  /* Column */
1920  printTableAddCell(&cont, PQgetvalue(res, i, 0), false, false);
1921 
1922  /* Type */
1923  printTableAddCell(&cont, PQgetvalue(res, i, 1), false, false);
1924 
1925  /* Collation, Nullable, Default */
1926  if (show_column_details)
1927  {
1928  char *identity;
1929  char *default_str = "";
1930 
1931  printTableAddCell(&cont, PQgetvalue(res, i, 5), false, false);
1932 
1933  printTableAddCell(&cont, strcmp(PQgetvalue(res, i, 3), "t") == 0 ? "not null" : "", false, false);
1934 
1935  identity = PQgetvalue(res, i, 6);
1936 
1937  if (!identity[0])
1938  /* (note: above we cut off the 'default' string at 128) */
1939  default_str = PQgetvalue(res, i, 2);
1940  else if (identity[0] == ATTRIBUTE_IDENTITY_ALWAYS)
1941  default_str = "generated always as identity";
1942  else if (identity[0] == ATTRIBUTE_IDENTITY_BY_DEFAULT)
1943  default_str = "generated by default as identity";
1944 
1945  printTableAddCell(&cont, default_str, false, false);
1946  }
1947 
1948  /* Expression for index column */
1949  if (tableinfo.relkind == RELKIND_INDEX ||
1950  tableinfo.relkind == RELKIND_PARTITIONED_INDEX)
1951  printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false);
1952 
1953  /* FDW options for foreign table column, only for 9.2 or later */
1954  if (tableinfo.relkind == RELKIND_FOREIGN_TABLE && pset.sversion >= 90200)
1955  printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
1956 
1957  /* Storage and Description */
1958  if (verbose)
1959  {
1960  int firstvcol = 9;
1961  char *storage = PQgetvalue(res, i, firstvcol);
1962 
1963  /* these strings are literal in our syntax, so not translated. */
1964  printTableAddCell(&cont, (storage[0] == 'p' ? "plain" :
1965  (storage[0] == 'm' ? "main" :
1966  (storage[0] == 'x' ? "extended" :
1967  (storage[0] == 'e' ? "external" :
1968  "???")))),
1969  false, false);
1970 
1971  /* Statistics target, if the relkind supports this feature */
1972  if (tableinfo.relkind == RELKIND_RELATION ||
1973  tableinfo.relkind == RELKIND_INDEX ||
1974  tableinfo.relkind == RELKIND_PARTITIONED_INDEX ||
1975  tableinfo.relkind == RELKIND_MATVIEW ||
1976  tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
1977  tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
1978  {
1979  printTableAddCell(&cont, PQgetvalue(res, i, firstvcol + 1),
1980  false, false);
1981  }
1982 
1983  /* Column comments, if the relkind supports this feature. */
1984  if (tableinfo.relkind == RELKIND_RELATION ||
1985  tableinfo.relkind == RELKIND_VIEW ||
1986  tableinfo.relkind == RELKIND_MATVIEW ||
1987  tableinfo.relkind == RELKIND_COMPOSITE_TYPE ||
1988  tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
1989  tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
1990  printTableAddCell(&cont, PQgetvalue(res, i, firstvcol + 2),
1991  false, false);
1992  }
1993  }
1994 
1995  /* Make footers */
1996  if (pset.sversion >= 100000)
1997  {
1998  /* Get the partition information */
1999  PGresult *result;
2000  char *parent_name;
2001  char *partdef;
2002  char *partconstraintdef = NULL;
2003 
2004  printfPQExpBuffer(&buf,
2005  "SELECT inhparent::pg_catalog.regclass,\n"
2006  " pg_catalog.pg_get_expr(c.relpartbound, inhrelid)");
2007  /* If verbose, also request the partition constraint definition */
2008  if (verbose)
2009  appendPQExpBuffer(&buf,
2010  ",\n pg_catalog.pg_get_partition_constraintdef(inhrelid)");
2011  appendPQExpBuffer(&buf,
2012  "\nFROM pg_catalog.pg_class c"
2013  " JOIN pg_catalog.pg_inherits i"
2014  " ON c.oid = inhrelid"
2015  "\nWHERE c.oid = '%s' AND c.relispartition;", oid);
2016  result = PSQLexec(buf.data);
2017  if (!result)
2018  goto error_return;
2019 
2020  if (PQntuples(result) > 0)
2021  {
2022  parent_name = PQgetvalue(result, 0, 0);
2023  partdef = PQgetvalue(result, 0, 1);
2024 
2025  if (PQnfields(result) == 3 && !PQgetisnull(result, 0, 2))
2026  partconstraintdef = PQgetvalue(result, 0, 2);
2027 
2028  printfPQExpBuffer(&tmpbuf, _("Partition of: %s %s"), parent_name,
2029  partdef);
2030  printTableAddFooter(&cont, tmpbuf.data);
2031 
2032  if (verbose)
2033  {
2034  /* If there isn't any constraint, show that explicitly */
2035  if (partconstraintdef == NULL || partconstraintdef[0] == '\0')
2036  printfPQExpBuffer(&tmpbuf, _("No partition constraint"));
2037  else
2038  printfPQExpBuffer(&tmpbuf, _("Partition constraint: %s"),
2039  partconstraintdef);
2040  printTableAddFooter(&cont, tmpbuf.data);
2041  }
2042 
2043  PQclear(result);
2044  }
2045  }
2046 
2047  if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
2048  {
2049  /* Get the partition key information */
2050  PGresult *result;
2051  char *partkeydef;
2052 
2053  printfPQExpBuffer(&buf,
2054  "SELECT pg_catalog.pg_get_partkeydef('%s'::pg_catalog.oid);",
2055  oid);
2056  result = PSQLexec(buf.data);
2057  if (!result || PQntuples(result) != 1)
2058  goto error_return;
2059 
2060  partkeydef = PQgetvalue(result, 0, 0);
2061  printfPQExpBuffer(&tmpbuf, _("Partition key: %s"), partkeydef);
2062  printTableAddFooter(&cont, tmpbuf.data);
2063  PQclear(result);
2064  }
2065 
2066  if (tableinfo.relkind == RELKIND_INDEX ||
2067  tableinfo.relkind == RELKIND_PARTITIONED_INDEX)
2068  {
2069  /* Footer information about an index */
2070  PGresult *result;
2071 
2072  printfPQExpBuffer(&buf,
2073  "SELECT i.indisunique, i.indisprimary, i.indisclustered, ");
2074  if (pset.sversion >= 80200)
2075  appendPQExpBufferStr(&buf, "i.indisvalid,\n");
2076  else
2077  appendPQExpBufferStr(&buf, "true AS indisvalid,\n");
2078  if (pset.sversion >= 90000)
2079  appendPQExpBufferStr(&buf,
2080  " (NOT i.indimmediate) AND "
2081  "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
2082  "WHERE conrelid = i.indrelid AND "
2083  "conindid = i.indexrelid AND "
2084  "contype IN ('p','u','x') AND "
2085  "condeferrable) AS condeferrable,\n"
2086  " (NOT i.indimmediate) AND "
2087  "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
2088  "WHERE conrelid = i.indrelid AND "
2089  "conindid = i.indexrelid AND "
2090  "contype IN ('p','u','x') AND "
2091  "condeferred) AS condeferred,\n");
2092  else
2093  appendPQExpBufferStr(&buf,
2094  " false AS condeferrable, false AS condeferred,\n");
2095 
2096  if (pset.sversion >= 90400)
2097  appendPQExpBuffer(&buf, "i.indisreplident,\n");
2098  else
2099  appendPQExpBuffer(&buf, "false AS indisreplident,\n");
2100 
2101  appendPQExpBuffer(&buf, " a.amname, c2.relname, "
2102  "pg_catalog.pg_get_expr(i.indpred, i.indrelid, true)\n"
2103  "FROM pg_catalog.pg_index i, pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_am a\n"
2104  "WHERE i.indexrelid = c.oid AND c.oid = '%s' AND c.relam = a.oid\n"
2105  "AND i.indrelid = c2.oid;",
2106  oid);
2107 
2108  result = PSQLexec(buf.data);
2109  if (!result)
2110  goto error_return;
2111  else if (PQntuples(result) != 1)
2112  {
2113  PQclear(result);
2114  goto error_return;
2115  }
2116  else
2117  {
2118  char *indisunique = PQgetvalue(result, 0, 0);
2119  char *indisprimary = PQgetvalue(result, 0, 1);
2120  char *indisclustered = PQgetvalue(result, 0, 2);
2121  char *indisvalid = PQgetvalue(result, 0, 3);
2122  char *deferrable = PQgetvalue(result, 0, 4);
2123  char *deferred = PQgetvalue(result, 0, 5);
2124  char *indisreplident = PQgetvalue(result, 0, 6);
2125  char *indamname = PQgetvalue(result, 0, 7);
2126  char *indtable = PQgetvalue(result, 0, 8);
2127  char *indpred = PQgetvalue(result, 0, 9);
2128 
2129  if (strcmp(indisprimary, "t") == 0)
2130  printfPQExpBuffer(&tmpbuf, _("primary key, "));
2131  else if (strcmp(indisunique, "t") == 0)
2132  printfPQExpBuffer(&tmpbuf, _("unique, "));
2133  else
2134  resetPQExpBuffer(&tmpbuf);
2135  appendPQExpBuffer(&tmpbuf, "%s, ", indamname);
2136 
2137  /* we assume here that index and table are in same schema */
2138  appendPQExpBuffer(&tmpbuf, _("for table \"%s.%s\""),
2139  schemaname, indtable);
2140 
2141  if (strlen(indpred))
2142  appendPQExpBuffer(&tmpbuf, _(", predicate (%s)"), indpred);
2143 
2144  if (strcmp(indisclustered, "t") == 0)
2145  appendPQExpBufferStr(&tmpbuf, _(", clustered"));
2146 
2147  if (strcmp(indisvalid, "t") != 0)
2148  appendPQExpBufferStr(&tmpbuf, _(", invalid"));
2149 
2150  if (strcmp(deferrable, "t") == 0)
2151  appendPQExpBufferStr(&tmpbuf, _(", deferrable"));
2152 
2153  if (strcmp(deferred, "t") == 0)
2154  appendPQExpBufferStr(&tmpbuf, _(", initially deferred"));
2155 
2156  if (strcmp(indisreplident, "t") == 0)
2157  appendPQExpBuffer(&tmpbuf, _(", replica identity"));
2158 
2159  printTableAddFooter(&cont, tmpbuf.data);
2160  add_tablespace_footer(&cont, tableinfo.relkind,
2161  tableinfo.tablespace, true);
2162  }
2163 
2164  PQclear(result);
2165  }
2166  else if (tableinfo.relkind == RELKIND_RELATION ||
2167  tableinfo.relkind == RELKIND_MATVIEW ||
2168  tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
2169  tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
2170  {
2171  /* Footer information about a table */
2172  PGresult *result = NULL;
2173  int tuples = 0;
2174 
2175  /* print indexes */
2176  if (tableinfo.hasindex)
2177  {
2178  printfPQExpBuffer(&buf,
2179  "SELECT c2.relname, i.indisprimary, i.indisunique, i.indisclustered, ");
2180  if (pset.sversion >= 80200)
2181  appendPQExpBufferStr(&buf, "i.indisvalid, ");
2182  else
2183  appendPQExpBufferStr(&buf, "true as indisvalid, ");
2184  appendPQExpBufferStr(&buf, "pg_catalog.pg_get_indexdef(i.indexrelid, 0, true),\n ");
2185  if (pset.sversion >= 90000)
2186  appendPQExpBufferStr(&buf,
2187  "pg_catalog.pg_get_constraintdef(con.oid, true), "
2188  "contype, condeferrable, condeferred");
2189  else
2190  appendPQExpBufferStr(&buf,
2191  "null AS constraintdef, null AS contype, "
2192  "false AS condeferrable, false AS condeferred");
2193  if (pset.sversion >= 90400)
2194  appendPQExpBufferStr(&buf, ", i.indisreplident");
2195  else
2196  appendPQExpBufferStr(&buf, ", false AS indisreplident");
2197  if (pset.sversion >= 80000)
2198  appendPQExpBufferStr(&buf, ", c2.reltablespace");
2199  appendPQExpBufferStr(&buf,
2200  "\nFROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i\n");
2201  if (pset.sversion >= 90000)
2202  appendPQExpBufferStr(&buf,
2203  " LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN ('p','u','x'))\n");
2204  appendPQExpBuffer(&buf,
2205  "WHERE c.oid = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
2206  "ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname;",
2207  oid);
2208  result = PSQLexec(buf.data);
2209  if (!result)
2210  goto error_return;
2211  else
2212  tuples = PQntuples(result);
2213 
2214  if (tuples > 0)
2215  {
2216  printTableAddFooter(&cont, _("Indexes:"));
2217  for (i = 0; i < tuples; i++)
2218  {
2219  /* untranslated index name */
2220  printfPQExpBuffer(&buf, " \"%s\"",
2221  PQgetvalue(result, i, 0));
2222 
2223  /* If exclusion constraint, print the constraintdef */
2224  if (strcmp(PQgetvalue(result, i, 7), "x") == 0)
2225  {
2226  appendPQExpBuffer(&buf, " %s",
2227  PQgetvalue(result, i, 6));
2228  }
2229  else
2230  {
2231  const char *indexdef;
2232  const char *usingpos;
2233 
2234  /* Label as primary key or unique (but not both) */
2235  if (strcmp(PQgetvalue(result, i, 1), "t") == 0)
2236  appendPQExpBufferStr(&buf, " PRIMARY KEY,");
2237  else if (strcmp(PQgetvalue(result, i, 2), "t") == 0)
2238  {
2239  if (strcmp(PQgetvalue(result, i, 7), "u") == 0)
2240  appendPQExpBufferStr(&buf, " UNIQUE CONSTRAINT,");
2241  else
2242  appendPQExpBufferStr(&buf, " UNIQUE,");
2243  }
2244 
2245  /* Everything after "USING" is echoed verbatim */
2246  indexdef = PQgetvalue(result, i, 5);
2247  usingpos = strstr(indexdef, " USING ");
2248  if (usingpos)
2249  indexdef = usingpos + 7;
2250  appendPQExpBuffer(&buf, " %s", indexdef);
2251 
2252  /* Need these for deferrable PK/UNIQUE indexes */
2253  if (strcmp(PQgetvalue(result, i, 8), "t") == 0)
2254  appendPQExpBufferStr(&buf, " DEFERRABLE");
2255 
2256  if (strcmp(PQgetvalue(result, i, 9), "t") == 0)
2257  appendPQExpBufferStr(&buf, " INITIALLY DEFERRED");
2258  }
2259 
2260  /* Add these for all cases */
2261  if (strcmp(PQgetvalue(result, i, 3), "t") == 0)
2262  appendPQExpBufferStr(&buf, " CLUSTER");
2263 
2264  if (strcmp(PQgetvalue(result, i, 4), "t") != 0)
2265  appendPQExpBufferStr(&buf, " INVALID");
2266 
2267  if (strcmp(PQgetvalue(result, i, 10), "t") == 0)
2268  appendPQExpBuffer(&buf, " REPLICA IDENTITY");
2269 
2270  printTableAddFooter(&cont, buf.data);
2271 
2272  /* Print tablespace of the index on the same line */
2273  if (pset.sversion >= 80000)
2274  add_tablespace_footer(&cont, RELKIND_INDEX,
2275  atooid(PQgetvalue(result, i, 11)),
2276  false);
2277  }
2278  }
2279  PQclear(result);
2280  }
2281 
2282  /* print table (and column) check constraints */
2283  if (tableinfo.checks)
2284  {
2285  printfPQExpBuffer(&buf,
2286  "SELECT r.conname, "
2287  "pg_catalog.pg_get_constraintdef(r.oid, true)\n"
2288  "FROM pg_catalog.pg_constraint r\n"
2289  "WHERE r.conrelid = '%s' AND r.contype = 'c'\n"
2290  "ORDER BY 1;",
2291  oid);
2292  result = PSQLexec(buf.data);
2293  if (!result)
2294  goto error_return;
2295  else
2296  tuples = PQntuples(result);
2297 
2298  if (tuples > 0)
2299  {
2300  printTableAddFooter(&cont, _("Check constraints:"));
2301  for (i = 0; i < tuples; i++)
2302  {
2303  /* untranslated constraint name and def */
2304  printfPQExpBuffer(&buf, " \"%s\" %s",
2305  PQgetvalue(result, i, 0),
2306  PQgetvalue(result, i, 1));
2307 
2308  printTableAddFooter(&cont, buf.data);
2309  }
2310  }
2311  PQclear(result);
2312  }
2313 
2314  /*
2315  * Print foreign-key constraints (there are none if no triggers,
2316  * except if the table is partitioned, in which case the triggers
2317  * appear in the partitions)
2318  */
2319  if (tableinfo.hastriggers ||
2320  tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
2321  {
2322  printfPQExpBuffer(&buf,
2323  "SELECT conname,\n"
2324  " pg_catalog.pg_get_constraintdef(r.oid, true) as condef\n"
2325  "FROM pg_catalog.pg_constraint r\n"
2326  "WHERE r.conrelid = '%s' AND r.contype = 'f' ORDER BY 1;",
2327  oid);
2328  result = PSQLexec(buf.data);
2329  if (!result)
2330  goto error_return;
2331  else
2332  tuples = PQntuples(result);
2333 
2334  if (tuples > 0)
2335  {
2336  printTableAddFooter(&cont, _("Foreign-key constraints:"));
2337  for (i = 0; i < tuples; i++)
2338  {
2339  /* untranslated constraint name and def */
2340  printfPQExpBuffer(&buf, " \"%s\" %s",
2341  PQgetvalue(result, i, 0),
2342  PQgetvalue(result, i, 1));
2343 
2344  printTableAddFooter(&cont, buf.data);
2345  }
2346  }
2347  PQclear(result);
2348  }
2349 
2350  /* print incoming foreign-key references (none if no triggers) */
2351  if (tableinfo.hastriggers)
2352  {
2353  printfPQExpBuffer(&buf,
2354  "SELECT conname, conrelid::pg_catalog.regclass,\n"
2355  " pg_catalog.pg_get_constraintdef(c.oid, true) as condef\n"
2356  "FROM pg_catalog.pg_constraint c\n"
2357  "WHERE c.confrelid = '%s' AND c.contype = 'f' ORDER BY 1;",
2358  oid);
2359  result = PSQLexec(buf.data);
2360  if (!result)
2361  goto error_return;
2362  else
2363  tuples = PQntuples(result);
2364 
2365  if (tuples > 0)
2366  {
2367  printTableAddFooter(&cont, _("Referenced by:"));
2368  for (i = 0; i < tuples; i++)
2369  {
2370  printfPQExpBuffer(&buf, " TABLE \"%s\" CONSTRAINT \"%s\" %s",
2371  PQgetvalue(result, i, 1),
2372  PQgetvalue(result, i, 0),
2373  PQgetvalue(result, i, 2));
2374 
2375  printTableAddFooter(&cont, buf.data);
2376  }
2377  }
2378  PQclear(result);
2379  }
2380 
2381  /* print any row-level policies */
2382  if (pset.sversion >= 90500)
2383  {
2384  printfPQExpBuffer(&buf, "SELECT pol.polname,");
2385  if (pset.sversion >= 100000)
2386  appendPQExpBuffer(&buf,
2387  " pol.polpermissive,\n");
2388  else
2389  appendPQExpBuffer(&buf,
2390  " 't' as polpermissive,\n");
2391  appendPQExpBuffer(&buf,
2392  " CASE WHEN pol.polroles = '{0}' THEN NULL ELSE pg_catalog.array_to_string(array(select rolname from pg_catalog.pg_roles where oid = any (pol.polroles) order by 1),',') END,\n"
2393  " pg_catalog.pg_get_expr(pol.polqual, pol.polrelid),\n"
2394  " pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid),\n"
2395  " CASE pol.polcmd\n"
2396  " WHEN 'r' THEN 'SELECT'\n"
2397  " WHEN 'a' THEN 'INSERT'\n"
2398  " WHEN 'w' THEN 'UPDATE'\n"
2399  " WHEN 'd' THEN 'DELETE'\n"
2400  " END AS cmd\n"
2401  "FROM pg_catalog.pg_policy pol\n"
2402  "WHERE pol.polrelid = '%s' ORDER BY 1;",
2403  oid);
2404 
2405  result = PSQLexec(buf.data);
2406  if (!result)
2407  goto error_return;
2408  else
2409  tuples = PQntuples(result);
2410 
2411  /*
2412  * Handle cases where RLS is enabled and there are policies, or
2413  * there aren't policies, or RLS isn't enabled but there are
2414  * policies
2415  */
2416  if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples > 0)
2417  printTableAddFooter(&cont, _("Policies:"));
2418 
2419  if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples > 0)
2420  printTableAddFooter(&cont, _("Policies (forced row security enabled):"));
2421 
2422  if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples == 0)
2423  printTableAddFooter(&cont, _("Policies (row security enabled): (none)"));
2424 
2425  if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples == 0)
2426  printTableAddFooter(&cont, _("Policies (forced row security enabled): (none)"));
2427 
2428  if (!tableinfo.rowsecurity && tuples > 0)
2429  printTableAddFooter(&cont, _("Policies (row security disabled):"));
2430 
2431  /* Might be an empty set - that's ok */
2432  for (i = 0; i < tuples; i++)
2433  {
2434  printfPQExpBuffer(&buf, " POLICY \"%s\"",
2435  PQgetvalue(result, i, 0));
2436 
2437  if (*(PQgetvalue(result, i, 1)) == 'f')
2438  appendPQExpBuffer(&buf, " AS RESTRICTIVE");
2439 
2440  if (!PQgetisnull(result, i, 5))
2441  appendPQExpBuffer(&buf, " FOR %s",
2442  PQgetvalue(result, i, 5));
2443 
2444  if (!PQgetisnull(result, i, 2))
2445  {
2446  appendPQExpBuffer(&buf, "\n TO %s",
2447  PQgetvalue(result, i, 2));
2448  }
2449 
2450  if (!PQgetisnull(result, i, 3))
2451  appendPQExpBuffer(&buf, "\n USING (%s)",
2452  PQgetvalue(result, i, 3));
2453 
2454  if (!PQgetisnull(result, i, 4))
2455  appendPQExpBuffer(&buf, "\n WITH CHECK (%s)",
2456  PQgetvalue(result, i, 4));
2457 
2458  printTableAddFooter(&cont, buf.data);
2459 
2460  }
2461  PQclear(result);
2462  }
2463 
2464  /* print any extended statistics */
2465  if (pset.sversion >= 100000)
2466  {
2467  printfPQExpBuffer(&buf,
2468  "SELECT oid, "
2469  "stxrelid::pg_catalog.regclass, "
2470  "stxnamespace::pg_catalog.regnamespace AS nsp, "
2471  "stxname,\n"
2472  " (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(attname),', ')\n"
2473  " FROM pg_catalog.unnest(stxkeys) s(attnum)\n"
2474  " JOIN pg_catalog.pg_attribute a ON (stxrelid = a.attrelid AND\n"
2475  " a.attnum = s.attnum AND NOT attisdropped)) AS columns,\n"
2476  " 'd' = any(stxkind) AS ndist_enabled,\n"
2477  " 'f' = any(stxkind) AS deps_enabled\n"
2478  "FROM pg_catalog.pg_statistic_ext stat "
2479  "WHERE stxrelid = '%s'\n"
2480  "ORDER BY 1;",
2481  oid);
2482 
2483  result = PSQLexec(buf.data);
2484  if (!result)
2485  goto error_return;
2486  else
2487  tuples = PQntuples(result);
2488 
2489  if (tuples > 0)
2490  {
2491  printTableAddFooter(&cont, _("Statistics objects:"));
2492 
2493  for (i = 0; i < tuples; i++)
2494  {
2495  bool gotone = false;
2496 
2497  printfPQExpBuffer(&buf, " ");
2498 
2499  /* statistics object name (qualified with namespace) */
2500  appendPQExpBuffer(&buf, "\"%s\".\"%s\" (",
2501  PQgetvalue(result, i, 2),
2502  PQgetvalue(result, i, 3));
2503 
2504  /* options */
2505  if (strcmp(PQgetvalue(result, i, 5), "t") == 0)
2506  {
2507  appendPQExpBufferStr(&buf, "ndistinct");
2508  gotone = true;
2509  }
2510 
2511  if (strcmp(PQgetvalue(result, i, 6), "t") == 0)
2512  {
2513  appendPQExpBuffer(&buf, "%sdependencies", gotone ? ", " : "");
2514  }
2515 
2516  appendPQExpBuffer(&buf, ") ON %s FROM %s",
2517  PQgetvalue(result, i, 4),
2518  PQgetvalue(result, i, 1));
2519 
2520  printTableAddFooter(&cont, buf.data);
2521  }
2522  }
2523  PQclear(result);
2524  }
2525 
2526  /* print rules */
2527  if (tableinfo.hasrules && tableinfo.relkind != RELKIND_MATVIEW)
2528  {
2529  if (pset.sversion >= 80300)
2530  {
2531  printfPQExpBuffer(&buf,
2532  "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
2533  "ev_enabled\n"
2534  "FROM pg_catalog.pg_rewrite r\n"
2535  "WHERE r.ev_class = '%s' ORDER BY 1;",
2536  oid);
2537  }
2538  else
2539  {
2540  printfPQExpBuffer(&buf,
2541  "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
2542  "'O' AS ev_enabled\n"
2543  "FROM pg_catalog.pg_rewrite r\n"
2544  "WHERE r.ev_class = '%s' ORDER BY 1;",
2545  oid);
2546  }
2547  result = PSQLexec(buf.data);
2548  if (!result)
2549  goto error_return;
2550  else
2551  tuples = PQntuples(result);
2552 
2553  if (tuples > 0)
2554  {
2555  bool have_heading;
2556  int category;
2557 
2558  for (category = 0; category < 4; category++)
2559  {
2560  have_heading = false;
2561 
2562  for (i = 0; i < tuples; i++)
2563  {
2564  const char *ruledef;
2565  bool list_rule = false;
2566 
2567  switch (category)
2568  {
2569  case 0:
2570  if (*PQgetvalue(result, i, 2) == 'O')
2571  list_rule = true;
2572  break;
2573  case 1:
2574  if (*PQgetvalue(result, i, 2) == 'D')
2575  list_rule = true;
2576  break;
2577  case 2:
2578  if (*PQgetvalue(result, i, 2) == 'A')
2579  list_rule = true;
2580  break;
2581  case 3:
2582  if (*PQgetvalue(result, i, 2) == 'R')
2583  list_rule = true;
2584  break;
2585  }
2586  if (!list_rule)
2587  continue;
2588 
2589  if (!have_heading)
2590  {
2591  switch (category)
2592  {
2593  case 0:
2594  printfPQExpBuffer(&buf, _("Rules:"));
2595  break;
2596  case 1:
2597  printfPQExpBuffer(&buf, _("Disabled rules:"));
2598  break;
2599  case 2:
2600  printfPQExpBuffer(&buf, _("Rules firing always:"));
2601  break;
2602  case 3:
2603  printfPQExpBuffer(&buf, _("Rules firing on replica only:"));
2604  break;
2605  }
2606  printTableAddFooter(&cont, buf.data);
2607  have_heading = true;
2608  }
2609 
2610  /* Everything after "CREATE RULE" is echoed verbatim */
2611  ruledef = PQgetvalue(result, i, 1);
2612  ruledef += 12;
2613  printfPQExpBuffer(&buf, " %s", ruledef);
2614  printTableAddFooter(&cont, buf.data);
2615  }
2616  }
2617  }
2618  PQclear(result);
2619  }
2620 
2621  /* print any publications */
2622  if (pset.sversion >= 100000)
2623  {
2624  printfPQExpBuffer(&buf,
2625  "SELECT pubname\n"
2626  "FROM pg_catalog.pg_publication p\n"
2627  "JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
2628  "WHERE pr.prrelid = '%s'\n"
2629  "UNION ALL\n"
2630  "SELECT pubname\n"
2631  "FROM pg_catalog.pg_publication p\n"
2632  "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
2633  "ORDER BY 1;",
2634  oid, oid);
2635 
2636  result = PSQLexec(buf.data);
2637  if (!result)
2638  goto error_return;
2639  else
2640  tuples = PQntuples(result);
2641 
2642  if (tuples > 0)
2643  printTableAddFooter(&cont, _("Publications:"));
2644 
2645  /* Might be an empty set - that's ok */
2646  for (i = 0; i < tuples; i++)
2647  {
2648  printfPQExpBuffer(&buf, " \"%s\"",
2649  PQgetvalue(result, i, 0));
2650 
2651  printTableAddFooter(&cont, buf.data);
2652  }
2653  PQclear(result);
2654  }
2655  }
2656 
2657  if (view_def)
2658  {
2659  PGresult *result = NULL;
2660 
2661  /* Footer information about a view */
2662  printTableAddFooter(&cont, _("View definition:"));
2663  printTableAddFooter(&cont, view_def);
2664 
2665  /* print rules */
2666  if (tableinfo.hasrules)
2667  {
2668  printfPQExpBuffer(&buf,
2669  "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true))\n"
2670  "FROM pg_catalog.pg_rewrite r\n"
2671  "WHERE r.ev_class = '%s' AND r.rulename != '_RETURN' ORDER BY 1;",
2672  oid);
2673  result = PSQLexec(buf.data);
2674  if (!result)
2675  goto error_return;
2676 
2677  if (PQntuples(result) > 0)
2678  {
2679  printTableAddFooter(&cont, _("Rules:"));
2680  for (i = 0; i < PQntuples(result); i++)
2681  {
2682  const char *ruledef;
2683 
2684  /* Everything after "CREATE RULE" is echoed verbatim */
2685  ruledef = PQgetvalue(result, i, 1);
2686  ruledef += 12;
2687 
2688  printfPQExpBuffer(&buf, " %s", ruledef);
2689  printTableAddFooter(&cont, buf.data);
2690  }
2691  }
2692  PQclear(result);
2693  }
2694  }
2695 
2696  /*
2697  * Print triggers next, if any (but only user-defined triggers). This
2698  * could apply to either a table or a view.
2699  */
2700  if (tableinfo.hastriggers)
2701  {
2702  PGresult *result;
2703  int tuples;
2704 
2705  printfPQExpBuffer(&buf,
2706  "SELECT t.tgname, "
2707  "pg_catalog.pg_get_triggerdef(t.oid%s), "
2708  "t.tgenabled, %s\n"
2709  "FROM pg_catalog.pg_trigger t\n"
2710  "WHERE t.tgrelid = '%s' AND ",
2711  (pset.sversion >= 90000 ? ", true" : ""),
2712  (pset.sversion >= 90000 ? "t.tgisinternal" :
2713  pset.sversion >= 80300 ?
2714  "t.tgconstraint <> 0 AS tgisinternal" :
2715  "false AS tgisinternal"), oid);
2716  if (pset.sversion >= 90000)
2717  /* display/warn about disabled internal triggers */
2718  appendPQExpBuffer(&buf, "(NOT t.tgisinternal OR (t.tgisinternal AND t.tgenabled = 'D'))");
2719  else if (pset.sversion >= 80300)
2720  appendPQExpBufferStr(&buf, "(t.tgconstraint = 0 OR (t.tgconstraint <> 0 AND t.tgenabled = 'D'))");
2721  else
2722  appendPQExpBufferStr(&buf,
2723  "(NOT tgisconstraint "
2724  " OR NOT EXISTS"
2725  " (SELECT 1 FROM pg_catalog.pg_depend d "
2726  " JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) "
2727  " WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))");
2728  appendPQExpBufferStr(&buf, "\nORDER BY 1;");
2729 
2730  result = PSQLexec(buf.data);
2731  if (!result)
2732  goto error_return;
2733  else
2734  tuples = PQntuples(result);
2735 
2736  if (tuples > 0)
2737  {
2738  bool have_heading;
2739  int category;
2740 
2741  /*
2742  * split the output into 4 different categories. Enabled triggers,
2743  * disabled triggers and the two special ALWAYS and REPLICA
2744  * configurations.
2745  */
2746  for (category = 0; category <= 4; category++)
2747  {
2748  have_heading = false;
2749  for (i = 0; i < tuples; i++)
2750  {
2751  bool list_trigger;
2752  const char *tgdef;
2753  const char *usingpos;
2754  const char *tgenabled;
2755  const char *tgisinternal;
2756 
2757  /*
2758  * Check if this trigger falls into the current category
2759  */
2760  tgenabled = PQgetvalue(result, i, 2);
2761  tgisinternal = PQgetvalue(result, i, 3);
2762  list_trigger = false;
2763  switch (category)
2764  {
2765  case 0:
2766  if (*tgenabled == 'O' || *tgenabled == 't')
2767  list_trigger = true;
2768  break;
2769  case 1:
2770  if ((*tgenabled == 'D' || *tgenabled == 'f') &&
2771  *tgisinternal == 'f')
2772  list_trigger = true;
2773  break;
2774  case 2:
2775  if ((*tgenabled == 'D' || *tgenabled == 'f') &&
2776  *tgisinternal == 't')
2777  list_trigger = true;
2778  break;
2779  case 3:
2780  if (*tgenabled == 'A')
2781  list_trigger = true;
2782  break;
2783  case 4:
2784  if (*tgenabled == 'R')
2785  list_trigger = true;
2786  break;
2787  }
2788  if (list_trigger == false)
2789  continue;
2790 
2791  /* Print the category heading once */
2792  if (have_heading == false)
2793  {
2794  switch (category)
2795  {
2796  case 0:
2797  printfPQExpBuffer(&buf, _("Triggers:"));
2798  break;
2799  case 1:
2800  if (pset.sversion >= 80300)
2801  printfPQExpBuffer(&buf, _("Disabled user triggers:"));
2802  else
2803  printfPQExpBuffer(&buf, _("Disabled triggers:"));
2804  break;
2805  case 2:
2806  printfPQExpBuffer(&buf, _("Disabled internal triggers:"));
2807  break;
2808  case 3:
2809  printfPQExpBuffer(&buf, _("Triggers firing always:"));
2810  break;
2811  case 4:
2812  printfPQExpBuffer(&buf, _("Triggers firing on replica only:"));
2813  break;
2814 
2815  }
2816  printTableAddFooter(&cont, buf.data);
2817  have_heading = true;
2818  }
2819 
2820  /* Everything after "TRIGGER" is echoed verbatim */
2821  tgdef = PQgetvalue(result, i, 1);
2822  usingpos = strstr(tgdef, " TRIGGER ");
2823  if (usingpos)
2824  tgdef = usingpos + 9;
2825 
2826  printfPQExpBuffer(&buf, " %s", tgdef);
2827  printTableAddFooter(&cont, buf.data);
2828  }
2829  }
2830  }
2831  PQclear(result);
2832  }
2833 
2834  /*
2835  * Finish printing the footer information about a table.
2836  */
2837  if (tableinfo.relkind == RELKIND_RELATION ||
2838  tableinfo.relkind == RELKIND_MATVIEW ||
2839  tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
2840  tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
2841  {
2842  PGresult *result;
2843  int tuples;
2844 
2845  /* print foreign server name */
2846  if (tableinfo.relkind == RELKIND_FOREIGN_TABLE)
2847  {
2848  char *ftoptions;
2849 
2850  /* Footer information about foreign table */
2851  printfPQExpBuffer(&buf,
2852  "SELECT s.srvname,\n"
2853  " pg_catalog.array_to_string(ARRAY(\n"
2854  " SELECT pg_catalog.quote_ident(option_name)"
2855  " || ' ' || pg_catalog.quote_literal(option_value)\n"
2856  " FROM pg_catalog.pg_options_to_table(ftoptions)), ', ')\n"
2857  "FROM pg_catalog.pg_foreign_table f,\n"
2858  " pg_catalog.pg_foreign_server s\n"
2859  "WHERE f.ftrelid = '%s' AND s.oid = f.ftserver;",
2860  oid);
2861  result = PSQLexec(buf.data);
2862  if (!result)
2863  goto error_return;
2864  else if (PQntuples(result) != 1)
2865  {
2866  PQclear(result);
2867  goto error_return;
2868  }
2869 
2870  /* Print server name */
2871  printfPQExpBuffer(&buf, _("Server: %s"),
2872  PQgetvalue(result, 0, 0));
2873  printTableAddFooter(&cont, buf.data);
2874 
2875  /* Print per-table FDW options, if any */
2876  ftoptions = PQgetvalue(result, 0, 1);
2877  if (ftoptions && ftoptions[0] != '\0')
2878  {
2879  printfPQExpBuffer(&buf, _("FDW options: (%s)"), ftoptions);
2880  printTableAddFooter(&cont, buf.data);
2881  }
2882  PQclear(result);
2883  }
2884 
2885  /* print inherited tables (exclude, if parent is a partitioned table) */
2886  printfPQExpBuffer(&buf,
2887  "SELECT c.oid::pg_catalog.regclass"
2888  " FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i"
2889  " WHERE c.oid=i.inhparent AND i.inhrelid = '%s'"
2890  " AND c.relkind != " CppAsString2(RELKIND_PARTITIONED_TABLE)
2891  " ORDER BY inhseqno;", oid);
2892 
2893  result = PSQLexec(buf.data);
2894  if (!result)
2895  goto error_return;
2896  else
2897  {
2898  const char *s = _("Inherits");
2899  int sw = pg_wcswidth(s, strlen(s), pset.encoding);
2900 
2901  tuples = PQntuples(result);
2902 
2903  for (i = 0; i < tuples; i++)
2904  {
2905  if (i == 0)
2906  printfPQExpBuffer(&buf, "%s: %s",
2907  s, PQgetvalue(result, i, 0));
2908  else
2909  printfPQExpBuffer(&buf, "%*s %s",
2910  sw, "", PQgetvalue(result, i, 0));
2911  if (i < tuples - 1)
2912  appendPQExpBufferChar(&buf, ',');
2913 
2914  printTableAddFooter(&cont, buf.data);
2915  }
2916 
2917  PQclear(result);
2918  }
2919 
2920  /* print child tables (with additional info if partitions) */
2921  if (pset.sversion >= 100000)
2922  printfPQExpBuffer(&buf,
2923  "SELECT c.oid::pg_catalog.regclass,"
2924  " pg_catalog.pg_get_expr(c.relpartbound, c.oid),"
2925  " c.relkind"
2926  " FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i"
2927  " WHERE c.oid=i.inhrelid AND i.inhparent = '%s'"
2928  " ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT',"
2929  " c.oid::pg_catalog.regclass::pg_catalog.text;", oid);
2930  else if (pset.sversion >= 80300)
2931  printfPQExpBuffer(&buf,
2932  "SELECT c.oid::pg_catalog.regclass"
2933  " FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i"
2934  " WHERE c.oid=i.inhrelid AND i.inhparent = '%s'"
2935  " ORDER BY c.oid::pg_catalog.regclass::pg_catalog.text;", oid);
2936  else
2937  printfPQExpBuffer(&buf,
2938  "SELECT c.oid::pg_catalog.regclass"
2939  " FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i"
2940  " WHERE c.oid=i.inhrelid AND i.inhparent = '%s'"
2941  " ORDER BY c.relname;", oid);
2942 
2943  result = PSQLexec(buf.data);
2944  if (!result)
2945  goto error_return;
2946  else
2947  tuples = PQntuples(result);
2948 
2949  /*
2950  * For a partitioned table with no partitions, always print the number
2951  * of partitions as zero, even when verbose output is expected.
2952  * Otherwise, we will not print "Partitions" section for a partitioned
2953  * table without any partitions.
2954  */
2955  if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE && tuples == 0)
2956  {
2957  printfPQExpBuffer(&buf, _("Number of partitions: %d"), tuples);
2958  printTableAddFooter(&cont, buf.data);
2959  }
2960  else if (!verbose)
2961  {
2962  /* print the number of child tables, if any */
2963  if (tuples > 0)
2964  {
2965  if (tableinfo.relkind != RELKIND_PARTITIONED_TABLE)
2966  printfPQExpBuffer(&buf, _("Number of child tables: %d (Use \\d+ to list them.)"), tuples);
2967  else
2968  printfPQExpBuffer(&buf, _("Number of partitions: %d (Use \\d+ to list them.)"), tuples);
2969  printTableAddFooter(&cont, buf.data);
2970  }
2971  }
2972  else
2973  {
2974  /* display the list of child tables */
2975  const char *ct = (tableinfo.relkind != RELKIND_PARTITIONED_TABLE) ?
2976  _("Child tables") : _("Partitions");
2977  int ctw = pg_wcswidth(ct, strlen(ct), pset.encoding);
2978 
2979  for (i = 0; i < tuples; i++)
2980  {
2981  if (tableinfo.relkind != RELKIND_PARTITIONED_TABLE)
2982  {
2983  if (i == 0)
2984  printfPQExpBuffer(&buf, "%s: %s",
2985  ct, PQgetvalue(result, i, 0));
2986  else
2987  printfPQExpBuffer(&buf, "%*s %s",
2988  ctw, "", PQgetvalue(result, i, 0));
2989  }
2990  else
2991  {
2992  char *partitioned_note;
2993 
2994  if (*PQgetvalue(result, i, 2) == RELKIND_PARTITIONED_TABLE)
2995  partitioned_note = ", PARTITIONED";
2996  else
2997  partitioned_note = "";
2998 
2999  if (i == 0)
3000  printfPQExpBuffer(&buf, "%s: %s %s%s",
3001  ct, PQgetvalue(result, i, 0), PQgetvalue(result, i, 1),
3002  partitioned_note);
3003  else
3004  printfPQExpBuffer(&buf, "%*s %s %s%s",
3005  ctw, "", PQgetvalue(result, i, 0), PQgetvalue(result, i, 1),
3006  partitioned_note);
3007  }
3008  if (i < tuples - 1)
3009  appendPQExpBufferChar(&buf, ',');
3010 
3011  printTableAddFooter(&cont, buf.data);
3012  }
3013  }
3014  PQclear(result);
3015 
3016  /* Table type */
3017  if (tableinfo.reloftype)
3018  {
3019  printfPQExpBuffer(&buf, _("Typed table of type: %s"), tableinfo.reloftype);
3020  printTableAddFooter(&cont, buf.data);
3021  }
3022 
3023  if (verbose &&
3024  (tableinfo.relkind == RELKIND_RELATION ||
3025  tableinfo.relkind == RELKIND_MATVIEW) &&
3026 
3027  /*
3028  * No need to display default values; we already display a REPLICA
3029  * IDENTITY marker on indexes.
3030  */
3031  tableinfo.relreplident != 'i' &&
3032  ((strcmp(schemaname, "pg_catalog") != 0 && tableinfo.relreplident != 'd') ||
3033  (strcmp(schemaname, "pg_catalog") == 0 && tableinfo.relreplident != 'n')))
3034  {
3035  const char *s = _("Replica Identity");
3036 
3037  printfPQExpBuffer(&buf, "%s: %s",
3038  s,
3039  tableinfo.relreplident == 'f' ? "FULL" :
3040  tableinfo.relreplident == 'n' ? "NOTHING" :
3041  "???");
3042 
3043  printTableAddFooter(&cont, buf.data);
3044  }
3045 
3046  /* OIDs, if verbose and not a materialized view */
3047  if (verbose && tableinfo.relkind != RELKIND_MATVIEW && tableinfo.hasoids)
3048  printTableAddFooter(&cont, _("Has OIDs: yes"));
3049 
3050  /* Tablespace info */
3051  add_tablespace_footer(&cont, tableinfo.relkind, tableinfo.tablespace,
3052  true);
3053  }
3054 
3055  /* reloptions, if verbose */
3056  if (verbose &&
3057  tableinfo.reloptions && tableinfo.reloptions[0] != '\0')
3058  {
3059  const char *t = _("Options");
3060 
3061  printfPQExpBuffer(&buf, "%s: %s", t, tableinfo.reloptions);
3062  printTableAddFooter(&cont, buf.data);
3063  }
3064 
3065  printTable(&cont, pset.queryFout, false, pset.logfile);
3066 
3067  retval = true;
3068 
3069 error_return:
3070 
3071  /* clean up */
3072  if (printTableInitialized)
3073  printTableCleanup(&cont);
3074  termPQExpBuffer(&buf);
3075  termPQExpBuffer(&title);
3076  termPQExpBuffer(&tmpbuf);
3077 
3078  if (view_def)
3079  free(view_def);
3080 
3081  if (res)
3082  PQclear(res);
3083 
3084  return retval;
3085 }
signed short int16
Definition: c.h:312
char relreplident
Definition: pg_class.h:68
int PQnfields(const PGresult *res)
Definition: fe-exec.c:2732
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
PsqlSettings pset
Definition: startup.c:33
void printTableCleanup(printTableContent *const content)
Definition: print.c:3101
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
const char * fmtId(const char *rawid)
Definition: string_utils.c:66
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
printTableOpt topt
Definition: print.h:165
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
unsigned int Oid
Definition: postgres_ext.h:31
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
char relkind
Definition: pg_class.h:51
void printTableAddHeader(printTableContent *const content, char *header, const bool translate, const char align)
Definition: print.c:2970
unsigned short int expanded
Definition: print.h:99
char relpersistence
Definition: pg_class.h:50
void printTableAddCell(printTableContent *const content, char *cell, const bool translate, const bool mustfree)
Definition: print.c:3010
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
int pg_wcswidth(const char *pwcs, size_t len, int encoding)
Definition: mbprint.c:177
static char * buf
Definition: pg_test_fsync.c:67
char * tablespace
Definition: pgbench.c:156
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
bool translate_header
Definition: print.h:169
#define atooid(x)
Definition: postgres_ext.h:42
void printTable(const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3190
static int verbose
Definition: pg_basebackup.c:88
#define CppAsString2(x)
Definition: c.h:224
void psql_error(const char *fmt,...)
Definition: common.c:221
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition: print.c:3058
Oid reloftype
Definition: pg_class.h:35
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:396
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
#define free(a)
Definition: header.h:65
char * title
Definition: print.h:167
char ** footers
Definition: print.h:168
bool default_footer
Definition: print.h:110
static void add_tablespace_footer(printTableContent *const cont, char relkind, Oid tablespace, const bool newline)
Definition: describe.c:3093
printQueryOpt popt
Definition: settings.h:91
void printTableInit(printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows)
Definition: print.c:2933
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
static StringInfoData tmpbuf
Definition: walsender.c:163
int i
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
int encoding
Definition: settings.h:83
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3143
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ describeOneTSConfig()

static bool describeOneTSConfig ( const char *  oid,
const char *  nspname,
const char *  cfgname,
const char *  pnspname,
const char *  prsname 
)
static

Definition at line 4644 of file describe.c.

References _, appendPQExpBuffer(), buf, PQExpBufferData::data, printTableOpt::default_footer, printQueryOpt::footers, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::topt, and printQueryOpt::translate_header.

Referenced by listTSConfigsVerbose().

4646 {
4648  title;
4649  PGresult *res;
4650  printQueryOpt myopt = pset.popt;
4651 
4652  initPQExpBuffer(&buf);
4653 
4654  printfPQExpBuffer(&buf,
4655  "SELECT\n"
4656  " ( SELECT t.alias FROM\n"
4657  " pg_catalog.ts_token_type(c.cfgparser) AS t\n"
4658  " WHERE t.tokid = m.maptokentype ) AS \"%s\",\n"
4659  " pg_catalog.btrim(\n"
4660  " ARRAY( SELECT mm.mapdict::pg_catalog.regdictionary\n"
4661  " FROM pg_catalog.pg_ts_config_map AS mm\n"
4662  " WHERE mm.mapcfg = m.mapcfg AND mm.maptokentype = m.maptokentype\n"
4663  " ORDER BY mapcfg, maptokentype, mapseqno\n"
4664  " ) :: pg_catalog.text,\n"
4665  " '{}') AS \"%s\"\n"
4666  "FROM pg_catalog.pg_ts_config AS c, pg_catalog.pg_ts_config_map AS m\n"
4667  "WHERE c.oid = '%s' AND m.mapcfg = c.oid\n"
4668  "GROUP BY m.mapcfg, m.maptokentype, c.cfgparser\n"
4669  "ORDER BY 1;",
4670  gettext_noop("Token"),
4671  gettext_noop("Dictionaries"),
4672  oid);
4673 
4674  res = PSQLexec(buf.data);
4675  termPQExpBuffer(&buf);
4676  if (!res)
4677  return false;
4678 
4679  initPQExpBuffer(&title);
4680 
4681  if (nspname)
4682  appendPQExpBuffer(&title, _("Text search configuration \"%s.%s\""),
4683  nspname, cfgname);
4684  else
4685  appendPQExpBuffer(&title, _("Text search configuration \"%s\""),
4686  cfgname);
4687 
4688  if (pnspname)
4689  appendPQExpBuffer(&title, _("\nParser: \"%s.%s\""),
4690  pnspname, prsname);
4691  else
4692  appendPQExpBuffer(&title, _("\nParser: \"%s\""),
4693  prsname);
4694 
4695  myopt.nullPrint = NULL;
4696  myopt.title = title.data;
4697  myopt.footers = NULL;
4698  myopt.topt.default_footer = false;
4699  myopt.translate_header = true;
4700 
4701  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4702 
4703  termPQExpBuffer(&title);
4704 
4705  PQclear(res);
4706  return true;
4707 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
printTableOpt topt
Definition: print.h:165
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
char ** footers
Definition: print.h:168
bool default_footer
Definition: print.h:110
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ describeOneTSParser()

static bool describeOneTSParser ( const char *  oid,
const char *  nspname,
const char *  prsname 
)
static

Definition at line 4249 of file describe.c.

References _, buf, PQExpBufferData::data, printTableOpt::default_footer, printQueryOpt::footers, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::topt, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by listTSParsersVerbose().

4250 {
4252  PGresult *res;
4253  PQExpBufferData title;
4254  printQueryOpt myopt = pset.popt;
4255  static const bool translate_columns[] = {true, false, false};
4256 
4257  initPQExpBuffer(&buf);
4258 
4259  printfPQExpBuffer(&buf,
4260  "SELECT '%s' AS \"%s\",\n"
4261  " p.prsstart::pg_catalog.regproc AS \"%s\",\n"
4262  " pg_catalog.obj_description(p.prsstart, 'pg_proc') as \"%s\"\n"
4263  " FROM pg_catalog.pg_ts_parser p\n"
4264  " WHERE p.oid = '%s'\n"
4265  "UNION ALL\n"
4266  "SELECT '%s',\n"
4267  " p.prstoken::pg_catalog.regproc,\n"
4268  " pg_catalog.obj_description(p.prstoken, 'pg_proc')\n"
4269  " FROM pg_catalog.pg_ts_parser p\n"
4270  " WHERE p.oid = '%s'\n"
4271  "UNION ALL\n"
4272  "SELECT '%s',\n"
4273  " p.prsend::pg_catalog.regproc,\n"
4274  " pg_catalog.obj_description(p.prsend, 'pg_proc')\n"
4275  " FROM pg_catalog.pg_ts_parser p\n"
4276  " WHERE p.oid = '%s'\n"
4277  "UNION ALL\n"
4278  "SELECT '%s',\n"
4279  " p.prsheadline::pg_catalog.regproc,\n"
4280  " pg_catalog.obj_description(p.prsheadline, 'pg_proc')\n"
4281  " FROM pg_catalog.pg_ts_parser p\n"
4282  " WHERE p.oid = '%s'\n"
4283  "UNION ALL\n"
4284  "SELECT '%s',\n"
4285  " p.prslextype::pg_catalog.regproc,\n"
4286  " pg_catalog.obj_description(p.prslextype, 'pg_proc')\n"
4287  " FROM pg_catalog.pg_ts_parser p\n"
4288  " WHERE p.oid = '%s';",
4289  gettext_noop("Start parse"),
4290  gettext_noop("Method"),
4291  gettext_noop("Function"),
4292  gettext_noop("Description"),
4293  oid,
4294  gettext_noop("Get next token"),
4295  oid,
4296  gettext_noop("End parse"),
4297  oid,
4298  gettext_noop("Get headline"),
4299  oid,
4300  gettext_noop("Get token types"),
4301  oid);
4302 
4303  res = PSQLexec(buf.data);
4304  termPQExpBuffer(&buf);
4305  if (!res)
4306  return false;
4307 
4308  myopt.nullPrint = NULL;
4309  initPQExpBuffer(&title);
4310  if (nspname)
4311  printfPQExpBuffer(&title, _("Text search parser \"%s.%s\""),
4312  nspname, prsname);
4313  else
4314  printfPQExpBuffer(&title, _("Text search parser \"%s\""), prsname);
4315  myopt.title = title.data;
4316  myopt.footers = NULL;
4317  myopt.topt.default_footer = false;
4318  myopt.translate_header = true;
4319  myopt.translate_columns = translate_columns;
4320  myopt.n_translate_columns = lengthof(translate_columns);
4321 
4322  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4323 
4324  PQclear(res);
4325 
4326  initPQExpBuffer(&buf);
4327 
4328  printfPQExpBuffer(&buf,
4329  "SELECT t.alias as \"%s\",\n"
4330  " t.description as \"%s\"\n"
4331  "FROM pg_catalog.ts_token_type( '%s'::pg_catalog.oid ) as t\n"
4332  "ORDER BY 1;",
4333  gettext_noop("Token name"),
4334  gettext_noop("Description"),
4335  oid);
4336 
4337  res = PSQLexec(buf.data);
4338  termPQExpBuffer(&buf);
4339  if (!res)
4340  return false;
4341 
4342  myopt.nullPrint = NULL;
4343  if (nspname)
4344  printfPQExpBuffer(&title, _("Token types for parser \"%s.%s\""),
4345  nspname, prsname);
4346  else
4347  printfPQExpBuffer(&title, _("Token types for parser \"%s\""), prsname);
4348  myopt.title = title.data;
4349  myopt.footers = NULL;
4350  myopt.topt.default_footer = true;
4351  myopt.translate_header = true;
4352  myopt.translate_columns = NULL;
4353  myopt.n_translate_columns = 0;
4354 
4355  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4356 
4357  termPQExpBuffer(&title);
4358  PQclear(res);
4359  return true;
4360 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
printTableOpt topt
Definition: print.h:165
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
#define lengthof(array)
Definition: c.h:629
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
char ** footers
Definition: print.h:168
bool default_footer
Definition: print.h:110
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:172
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
const bool * translate_columns
Definition: print.h:170
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ describeOperators()

bool describeOperators ( const char *  pattern,
bool  verbose,
bool  showSystem 
)

Definition at line 746 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, termPQExpBuffer(), printQueryOpt::title, and printQueryOpt::translate_header.

Referenced by exec_command_d().

747 {
749  PGresult *res;
750  printQueryOpt myopt = pset.popt;
751 
752  initPQExpBuffer(&buf);
753 
754  /*
755  * Note: before Postgres 9.1, we did not assign comments to any built-in
756  * operators, preferring to let the comment on the underlying function
757  * suffice. The coalesce() on the obj_description() calls below supports
758  * this convention by providing a fallback lookup of a comment on the
759  * operator's function. As of 9.1 there is a policy that every built-in
760  * operator should have a comment; so the coalesce() is no longer
761  * necessary so far as built-in operators are concerned. We keep it
762  * anyway, for now, because (1) third-party modules may still be following
763  * the old convention, and (2) we'd need to do it anyway when talking to a
764  * pre-9.1 server.
765  */
766 
767  printfPQExpBuffer(&buf,
768  "SELECT n.nspname as \"%s\",\n"
769  " o.oprname AS \"%s\",\n"
770  " CASE WHEN o.oprkind='l' THEN NULL ELSE pg_catalog.format_type(o.oprleft, NULL) END AS \"%s\",\n"
771  " CASE WHEN o.oprkind='r' THEN NULL ELSE pg_catalog.format_type(o.oprright, NULL) END AS \"%s\",\n"
772  " pg_catalog.format_type(o.oprresult, NULL) AS \"%s\",\n",
773  gettext_noop("Schema"),
774  gettext_noop("Name"),
775  gettext_noop("Left arg type"),
776  gettext_noop("Right arg type"),
777  gettext_noop("Result type"));
778 
779  if (verbose)
780  appendPQExpBuffer(&buf,
781  " o.oprcode AS \"%s\",\n",
782  gettext_noop("Function"));
783 
784  appendPQExpBuffer(&buf,
785  " coalesce(pg_catalog.obj_description(o.oid, 'pg_operator'),\n"
786  " pg_catalog.obj_description(o.oprcode, 'pg_proc')) AS \"%s\"\n"
787  "FROM pg_catalog.pg_operator o\n"
788  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace\n",
789  gettext_noop("Description"));
790 
791  if (!showSystem && !pattern)
792  appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
793  " AND n.nspname <> 'information_schema'\n");
794 
795  processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern, true,
796  "n.nspname", "o.oprname", NULL,
797  "pg_catalog.pg_operator_is_visible(o.oid)");
798 
799  appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3, 4;");
800 
801  res = PSQLexec(buf.data);
802  termPQExpBuffer(&buf);
803  if (!res)
804  return false;
805 
806  myopt.nullPrint = NULL;
807  myopt.title = _("List of operators");
808  myopt.translate_header = true;
809 
810  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
811 
812  PQclear(res);
813  return true;
814 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
static int verbose
Definition: pg_basebackup.c:88
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ describePublications()

bool describePublications ( const char *  pattern)

Definition at line 5261 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, formatPGVersionNumber(), gettext_noop, i, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), PQgetvalue(), PQntuples(), printfPQExpBuffer(), printTable(), printTableAddCell(), printTableAddFooter(), printTableAddHeader(), printTableCleanup(), printTableInit(), processSQLNamePattern(), pset, psql_error(), PSQLexec(), _psqlSettings::queryFout, _psqlSettings::quiet, _psqlSettings::sversion, termPQExpBuffer(), and printQueryOpt::topt.

Referenced by exec_command_d().

5262 {
5264  int i;
5265  PGresult *res;
5266  bool has_pubtruncate;
5267 
5268  if (pset.sversion < 100000)
5269  {
5270  char sverbuf[32];
5271 
5272  psql_error("The server (version %s) does not support publications.\n",
5274  sverbuf, sizeof(sverbuf)));
5275  return true;
5276  }
5277 
5278  has_pubtruncate = (pset.sversion >= 110000);
5279 
5280  initPQExpBuffer(&buf);
5281 
5282  printfPQExpBuffer(&buf,
5283  "SELECT oid, pubname,\n"
5284  " pg_catalog.pg_get_userbyid(pubowner) AS owner,\n"
5285  " puballtables, pubinsert, pubupdate, pubdelete");
5286  if (has_pubtruncate)
5287  appendPQExpBuffer(&buf,
5288  ", pubtruncate");
5289  appendPQExpBuffer(&buf,
5290  "\nFROM pg_catalog.pg_publication\n");
5291 
5292  processSQLNamePattern(pset.db, &buf, pattern, false, false,
5293  NULL, "pubname", NULL,
5294  NULL);
5295 
5296  appendPQExpBufferStr(&buf, "ORDER BY 2;");
5297 
5298  res = PSQLexec(buf.data);
5299  if (!res)
5300  {
5301  termPQExpBuffer(&buf);
5302  return false;
5303  }
5304 
5305  if (PQntuples(res) == 0)
5306  {
5307  if (!pset.quiet)
5308  {
5309  if (pattern)
5310  psql_error("Did not find any publication named \"%s\".\n",
5311  pattern);
5312  else
5313  psql_error("Did not find any publications.\n");
5314  }
5315 
5316  termPQExpBuffer(&buf);
5317  PQclear(res);
5318  return false;
5319  }
5320 
5321  for (i = 0; i < PQntuples(res); i++)
5322  {
5323  const char align = 'l';
5324  int ncols = 5;
5325  int nrows = 1;
5326  int tables = 0;
5327  PGresult *tabres;
5328  char *pubid = PQgetvalue(res, i, 0);
5329  char *pubname = PQgetvalue(res, i, 1);
5330  bool puballtables = strcmp(PQgetvalue(res, i, 3), "t") == 0;
5331  int j;
5332  PQExpBufferData title;
5333  printTableOpt myopt = pset.popt.topt;
5334  printTableContent cont;
5335 
5336  if (has_pubtruncate)
5337  ncols++;
5338 
5339  initPQExpBuffer(&title);
5340  printfPQExpBuffer(&title, _("Publication %s"), pubname);
5341  printTableInit(&cont, &myopt, title.data, ncols, nrows);
5342 
5343  printTableAddHeader(&cont, gettext_noop("Owner"), true, align);
5344  printTableAddHeader(&cont, gettext_noop("All tables"), true, align);
5345  printTableAddHeader(&cont, gettext_noop("Inserts"), true, align);
5346  printTableAddHeader(&cont, gettext_noop("Updates"), true, align);
5347  printTableAddHeader(&cont, gettext_noop("Deletes"), true, align);
5348  if (has_pubtruncate)
5349  printTableAddHeader(&cont, gettext_noop("Truncates"), true, align);
5350 
5351  printTableAddCell(&cont, PQgetvalue(res, i, 2), false, false);
5352  printTableAddCell(&cont, PQgetvalue(res, i, 3), false, false);
5353  printTableAddCell(&cont, PQgetvalue(res, i, 4), false, false);
5354  printTableAddCell(&cont, PQgetvalue(res, i, 5), false, false);
5355  printTableAddCell(&cont, PQgetvalue(res, i, 6), false, false);
5356  if (has_pubtruncate)
5357  printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false);
5358 
5359  if (!puballtables)
5360  {
5361  printfPQExpBuffer(&buf,
5362  "SELECT n.nspname, c.relname\n"
5363  "FROM pg_catalog.pg_class c,\n"
5364  " pg_catalog.pg_namespace n,\n"
5365  " pg_catalog.pg_publication_rel pr\n"
5366  "WHERE c.relnamespace = n.oid\n"
5367  " AND c.oid = pr.prrelid\n"
5368  " AND pr.prpubid = '%s'\n"
5369  "ORDER BY 1,2", pubid);
5370 
5371  tabres = PSQLexec(buf.data);
5372  if (!tabres)
5373  {
5374  printTableCleanup(&cont);
5375  PQclear(res);
5376  termPQExpBuffer(&buf);
5377  termPQExpBuffer(&title);
5378  return false;
5379  }
5380  else
5381  tables = PQntuples(tabres);
5382 
5383  if (tables > 0)
5384  printTableAddFooter(&cont, _("Tables:"));
5385 
5386  for (j = 0; j < tables; j++)
5387  {
5388  printfPQExpBuffer(&buf, " \"%s.%s\"",
5389  PQgetvalue(tabres, j, 0),
5390  PQgetvalue(tabres, j, 1));
5391 
5392  printTableAddFooter(&cont, buf.data);
5393  }
5394  PQclear(tabres);
5395  }
5396 
5397  printTable(&cont, pset.queryFout, false, pset.logfile);
5398  printTableCleanup(&cont);
5399 
5400  termPQExpBuffer(&title);
5401  }
5402 
5403  termPQExpBuffer(&buf);
5404  PQclear(res);
5405 
5406  return true;
5407 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
PsqlSettings pset
Definition: startup.c:33
void printTableCleanup(printTableContent *const content)
Definition: print.c:3101
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
printTableOpt topt
Definition: print.h:165
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
void printTableAddHeader(printTableContent *const content, char *header, const bool translate, const char align)
Definition: print.c:2970
void printTableAddCell(printTableContent *const content, char *cell, const bool translate, const bool mustfree)
Definition: print.c:3010
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
void printTable(const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3190
void psql_error(const char *fmt,...)
Definition: common.c:221
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition: print.c:3058
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
printQueryOpt popt
Definition: settings.h:91
void printTableInit(printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows)
Definition: print.c:2933
int i
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:182
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ describeRoles()

bool describeRoles ( const char *  pattern,
bool  verbose,
bool  showSystem 
)

Definition at line 3157 of file describe.c.

References _, add_role_attribute(), appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), buf, conns, PQExpBufferData::data, _psqlSettings::db, printTableOpt::default_footer, free, gettext_noop, i, initPQExpBuffer(), PQExpBufferData::len, _psqlSettings::logfile, ngettext, pg_malloc0(), pg_strdup(), _psqlSettings::popt, PQclear(), PQgetvalue(), PQntuples(), printfPQExpBuffer(), printTable(), printTableAddCell(), printTableAddHeader(), printTableCleanup(), printTableInit(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, resetPQExpBuffer(), _psqlSettings::sversion, termPQExpBuffer(), and printQueryOpt::topt.

Referenced by exec_command_d().

3158 {
3160  PGresult *res;
3161  printTableContent cont;
3162  printTableOpt myopt = pset.popt.topt;
3163  int ncols = 3;
3164  int nrows = 0;
3165  int i;
3166  int conns;
3167  const char align = 'l';
3168  char **attr;
3169 
3170  myopt.default_footer = false;
3171 
3172  initPQExpBuffer(&buf);
3173 
3174  if (pset.sversion >= 80100)
3175  {
3176  printfPQExpBuffer(&buf,
3177  "SELECT r.rolname, r.rolsuper, r.rolinherit,\n"
3178  " r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,\n"
3179  " r.rolconnlimit, r.rolvaliduntil,\n"
3180  " ARRAY(SELECT b.rolname\n"
3181  " FROM pg_catalog.pg_auth_members m\n"
3182  " JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)\n"
3183  " WHERE m.member = r.oid) as memberof");
3184 
3185  if (verbose && pset.sversion >= 80200)
3186  {
3187  appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
3188  ncols++;
3189  }
3190  if (pset.sversion >= 90100)
3191  {
3192  appendPQExpBufferStr(&buf, "\n, r.rolreplication");
3193  }
3194 
3195  if (pset.sversion >= 90500)
3196  {
3197  appendPQExpBufferStr(&buf, "\n, r.rolbypassrls");
3198  }
3199 
3200  appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_roles r\n");
3201 
3202  if (!showSystem && !pattern)
3203  appendPQExpBufferStr(&buf, "WHERE r.rolname !~ '^pg_'\n");
3204 
3205  processSQLNamePattern(pset.db, &buf, pattern, false, false,
3206  NULL, "r.rolname", NULL, NULL);
3207  }
3208  else
3209  {
3210  printfPQExpBuffer(&buf,
3211  "SELECT u.usename AS rolname,\n"
3212  " u.usesuper AS rolsuper,\n"
3213  " true AS rolinherit, false AS rolcreaterole,\n"
3214  " u.usecreatedb AS rolcreatedb, true AS rolcanlogin,\n"
3215  " -1 AS rolconnlimit,"
3216  " u.valuntil as rolvaliduntil,\n"
3217  " ARRAY(SELECT g.groname FROM pg_catalog.pg_group g WHERE u.usesysid = ANY(g.grolist)) as memberof"
3218  "\nFROM pg_catalog.pg_user u\n");
3219 
3220  processSQLNamePattern(pset.db, &buf, pattern, false, false,
3221  NULL, "u.usename", NULL, NULL);
3222  }
3223 
3224  appendPQExpBufferStr(&buf, "ORDER BY 1;");
3225 
3226  res = PSQLexec(buf.data);
3227  if (!res)
3228  return false;
3229 
3230  nrows = PQntuples(res);
3231  attr = pg_malloc0((nrows + 1) * sizeof(*attr));
3232 
3233  printTableInit(&cont, &myopt, _("List of roles"), ncols, nrows);
3234 
3235  printTableAddHeader(&cont, gettext_noop("Role name"), true, align);
3236  printTableAddHeader(&cont, gettext_noop("Attributes"), true, align);
3237  printTableAddHeader(&cont, gettext_noop("Member of"), true, align);
3238 
3239  if (verbose && pset.sversion >= 80200)
3240  printTableAddHeader(&cont, gettext_noop("Description"), true, align);
3241 
3242  for (i = 0; i < nrows; i++)
3243  {
3244  printTableAddCell(&cont, PQgetvalue(res, i, 0), false, false);
3245 
3246  resetPQExpBuffer(&buf);
3247  if (strcmp(PQgetvalue(res, i, 1), "t") == 0)
3248  add_role_attribute(&buf, _("Superuser"));
3249 
3250  if (strcmp(PQgetvalue(res, i, 2), "t") != 0)
3251  add_role_attribute(&buf, _("No inheritance"));
3252 
3253  if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
3254  add_role_attribute(&buf, _("Create role"));
3255 
3256  if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
3257  add_role_attribute(&buf, _("Create DB"));
3258 
3259  if (strcmp(PQgetvalue(res, i, 5), "t") != 0)
3260  add_role_attribute(&buf, _("Cannot login"));
3261 
3262  if (pset.sversion >= 90100)
3263  if (strcmp(PQgetvalue(res, i, (verbose ? 10 : 9)), "t") == 0)
3264  add_role_attribute(&buf, _("Replication"));
3265 
3266  if (pset.sversion >= 90500)
3267  if (strcmp(PQgetvalue(res, i, (verbose ? 11 : 10)), "t") == 0)
3268  add_role_attribute(&buf, _("Bypass RLS"));
3269 
3270  conns = atoi(PQgetvalue(res, i, 6));
3271  if (conns >= 0)
3272  {
3273  if (buf.len > 0)
3274  appendPQExpBufferChar(&buf, '\n');
3275 
3276  if (conns == 0)
3277  appendPQExpBufferStr(&buf, _("No connections"));
3278  else
3279  appendPQExpBuffer(&buf, ngettext("%d connection",
3280  "%d connections",
3281  conns),
3282  conns);
3283  }
3284 
3285  if (strcmp(PQgetvalue(res, i, 7), "") != 0)
3286  {
3287  if (buf.len > 0)
3288  appendPQExpBufferChar(&buf, '\n');
3289  appendPQExpBufferStr(&buf, _("Password valid until "));
3290  appendPQExpBufferStr(&buf, PQgetvalue(res, i, 7));
3291  }
3292 
3293  attr[i] = pg_strdup(buf.data);
3294 
3295  printTableAddCell(&cont, attr[i], false, false);
3296 
3297  printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
3298 
3299  if (verbose && pset.sversion >= 80200)
3300  printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
3301  }
3302  termPQExpBuffer(&buf);
3303 
3304  printTable(&cont, pset.queryFout, false, pset.logfile);
3305  printTableCleanup(&cont);
3306 
3307  for (i = 0; i < nrows; i++)
3308  free(attr[i]);
3309  free(attr);
3310 
3311  PQclear(res);
3312  return true;
3313 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
PsqlSettings pset
Definition: startup.c:33
void printTableCleanup(printTableContent *const content)
Definition: print.c:3101
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
printTableOpt topt
Definition: print.h:165
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
static void add_role_attribute(PQExpBuffer buf, const char *const str)
Definition: describe.c:3316
void printTableAddHeader(printTableContent *const content, char *header, const bool translate, const char align)
Definition: print.c:2970
static PGconn ** conns
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
void printTableAddCell(printTableContent *const content, char *cell, const bool translate, const bool mustfree)
Definition: print.c:3010
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void printTable(const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3190
static int verbose
Definition: pg_basebackup.c:88
#define ngettext(s, p, n)
Definition: c.h:1022
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:396
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
#define free(a)
Definition: header.h:65
bool default_footer
Definition: print.h:110
printQueryOpt popt
Definition: settings.h:91
void printTableInit(printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows)
Definition: print.c:2933
int i
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ describeSubscriptions()

bool describeSubscriptions ( const char *  pattern,
bool  verbose 
)

Definition at line 5416 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, psql_error(), PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by exec_command_d().

5417 {
5419  PGresult *res;
5420  printQueryOpt myopt = pset.popt;
5421  static const bool translate_columns[] = {false, false, false, false,
5422  false, false};
5423 
5424  if (pset.sversion < 100000)
5425  {
5426  char sverbuf[32];
5427 
5428  psql_error("The server (version %s) does not support subscriptions.\n",
5430  sverbuf, sizeof(sverbuf)));
5431  return true;
5432  }
5433 
5434  initPQExpBuffer(&buf);
5435 
5436  printfPQExpBuffer(&buf,
5437  "SELECT subname AS \"%s\"\n"
5438  ", pg_catalog.pg_get_userbyid(subowner) AS \"%s\"\n"
5439  ", subenabled AS \"%s\"\n"
5440  ", subpublications AS \"%s\"\n",
5441  gettext_noop("Name"),
5442  gettext_noop("Owner"),
5443  gettext_noop("Enabled"),
5444  gettext_noop("Publication"));
5445 
5446  if (verbose)
5447  {
5448  appendPQExpBuffer(&buf,
5449  ", subsynccommit AS \"%s\"\n"
5450  ", subconninfo AS \"%s\"\n",
5451  gettext_noop("Synchronous commit"),
5452  gettext_noop("Conninfo"));
5453  }
5454 
5455  /* Only display subscriptions in current database. */
5456  appendPQExpBufferStr(&buf,
5457  "FROM pg_catalog.pg_subscription\n"
5458  "WHERE subdbid = (SELECT oid\n"
5459  " FROM pg_catalog.pg_database\n"
5460  " WHERE datname = pg_catalog.current_database())");
5461 
5462  processSQLNamePattern(pset.db, &buf, pattern, true, false,
5463  NULL, "subname", NULL,
5464  NULL);
5465 
5466  appendPQExpBufferStr(&buf, "ORDER BY 1;");
5467 
5468  res = PSQLexec(buf.data);
5469  termPQExpBuffer(&buf);
5470  if (!res)
5471  return false;
5472 
5473  myopt.nullPrint = NULL;
5474  myopt.title = _("List of subscriptions");
5475  myopt.translate_header = true;
5476  myopt.translate_columns = translate_columns;
5477  myopt.n_translate_columns = lengthof(translate_columns);
5478 
5479  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5480 
5481  PQclear(res);
5482  return true;
5483 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
#define lengthof(array)
Definition: c.h:629
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
static int verbose
Definition: pg_basebackup.c:88
void psql_error(const char *fmt,...)
Definition: common.c:221
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:172
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
const bool * translate_columns
Definition: print.h:170
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:182
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ describeTableDetails()

bool describeTableDetails ( const char *  pattern,
bool  verbose,
bool  showSystem 
)

Definition at line 1330 of file describe.c.

References appendPQExpBufferStr(), buf, cancel_pressed, PQExpBufferData::data, _psqlSettings::db, describeOneTableDetails(), i, initPQExpBuffer(), PQclear(), PQgetvalue(), PQntuples(), printfPQExpBuffer(), processSQLNamePattern(), pset, psql_error(), PSQLexec(), _psqlSettings::quiet, and termPQExpBuffer().

Referenced by exec_command_d().

1331 {
1333  PGresult *res;
1334  int i;
1335 
1336  initPQExpBuffer(&buf);
1337 
1338  printfPQExpBuffer(&buf,
1339  "SELECT c.oid,\n"
1340  " n.nspname,\n"
1341  " c.relname\n"
1342  "FROM pg_catalog.pg_class c\n"
1343  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n");
1344 
1345  if (!showSystem && !pattern)
1346  appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
1347  " AND n.nspname <> 'information_schema'\n");
1348 
1349  processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern, false,
1350  "n.nspname", "c.relname", NULL,
1351  "pg_catalog.pg_table_is_visible(c.oid)");
1352 
1353  appendPQExpBufferStr(&buf, "ORDER BY 2, 3;");
1354 
1355  res = PSQLexec(buf.data);
1356  termPQExpBuffer(&buf);
1357  if (!res)
1358  return false;
1359 
1360  if (PQntuples(res) == 0)
1361  {
1362  if (!pset.quiet)
1363  {
1364  if (pattern)
1365  psql_error("Did not find any relation named \"%s\".\n",
1366  pattern);
1367  else
1368  psql_error("Did not find any relations.\n");
1369  }
1370  PQclear(res);
1371  return false;
1372  }
1373 
1374  for (i = 0; i < PQntuples(res); i++)
1375  {
1376  const char *oid;
1377  const char *nspname;
1378  const char *relname;
1379 
1380  oid = PQgetvalue(res, i, 0);
1381  nspname = PQgetvalue(res, i, 1);
1382  relname = PQgetvalue(res, i, 2);
1383 
1384  if (!describeOneTableDetails(nspname, relname, oid, verbose))
1385  {
1386  PQclear(res);
1387  return false;
1388  }
1389  if (cancel_pressed)
1390  {
1391  PQclear(res);
1392  return false;
1393  }
1394  }
1395 
1396  PQclear(res);
1397  return true;
1398 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
PsqlSettings pset
Definition: startup.c:33
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
volatile bool cancel_pressed
Definition: print.c:46
static char * buf
Definition: pg_test_fsync.c:67
static bool describeOneTableDetails(const char *schemaname, const char *relationname, const char *oid, bool verbose)
Definition: describe.c:1408
static int verbose
Definition: pg_basebackup.c:88
void psql_error(const char *fmt,...)
Definition: common.c:221
void PQclear(PGresult *res)
Definition: fe-exec.c:671
int i
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ describeTablespaces()

bool describeTablespaces ( const char *  pattern,
bool  verbose 
)

Definition at line 216 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, psql_error(), PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, and printQueryOpt::translate_header.

Referenced by exec_command_d().

217 {
219  PGresult *res;
220  printQueryOpt myopt = pset.popt;
221 
222  if (pset.sversion < 80000)
223  {
224  char sverbuf[32];
225 
226  psql_error("The server (version %s) does not support tablespaces.\n",
228  sverbuf, sizeof(sverbuf)));
229  return true;
230  }
231 
232  initPQExpBuffer(&buf);
233 
234  if (pset.sversion >= 90200)
235  printfPQExpBuffer(&buf,
236  "SELECT spcname AS \"%s\",\n"
237  " pg_catalog.pg_get_userbyid(spcowner) AS \"%s\",\n"
238  " pg_catalog.pg_tablespace_location(oid) AS \"%s\"",
239  gettext_noop("Name"),
240  gettext_noop("Owner"),
241  gettext_noop("Location"));
242  else
243  printfPQExpBuffer(&buf,
244  "SELECT spcname AS \"%s\",\n"
245  " pg_catalog.pg_get_userbyid(spcowner) AS \"%s\",\n"
246  " spclocation AS \"%s\"",
247  gettext_noop("Name"),
248  gettext_noop("Owner"),
249  gettext_noop("Location"));
250 
251  if (verbose)
252  {
253  appendPQExpBufferStr(&buf, ",\n ");
254  printACLColumn(&buf, "spcacl");
255  }
256 
257  if (verbose && pset.sversion >= 90000)
258  appendPQExpBuffer(&buf,
259  ",\n spcoptions AS \"%s\"",
260  gettext_noop("Options"));
261 
262  if (verbose && pset.sversion >= 90200)
263  appendPQExpBuffer(&buf,
264  ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"",
265  gettext_noop("Size"));
266 
267  if (verbose && pset.sversion >= 80200)
268  appendPQExpBuffer(&buf,
269  ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"",
270  gettext_noop("Description"));
271 
273  "\nFROM pg_catalog.pg_tablespace\n");
274 
275  processSQLNamePattern(pset.db, &buf, pattern, false, false,
276  NULL, "spcname", NULL,
277  NULL);
278 
279  appendPQExpBufferStr(&buf, "ORDER BY 1;");
280 
281  res = PSQLexec(buf.data);
282  termPQExpBuffer(&buf);
283  if (!res)
284  return false;
285 
286  myopt.nullPrint = NULL;
287  myopt.title = _("List of tablespaces");
288  myopt.translate_header = true;
289 
290  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
291 
292  PQclear(res);
293  return true;
294 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
static int verbose
Definition: pg_basebackup.c:88
void psql_error(const char *fmt,...)
Definition: common.c:221
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition: describe.c:5493
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:182
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ describeTypes()

bool describeTypes ( const char *  pattern,
bool  verbose,
bool  showSystem 
)

Definition at line 630 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, PQExpBufferData::data, _psqlSettings::db, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, and printQueryOpt::translate_header.

Referenced by exec_command_d().

631 {
633  PGresult *res;
634  printQueryOpt myopt = pset.popt;
635 
636  initPQExpBuffer(&buf);
637 
638  printfPQExpBuffer(&buf,
639  "SELECT n.nspname as \"%s\",\n"
640  " pg_catalog.format_type(t.oid, NULL) AS \"%s\",\n",
641  gettext_noop("Schema"),
642  gettext_noop("Name"));
643  if (verbose)
644  appendPQExpBuffer(&buf,
645  " t.typname AS \"%s\",\n"
646  " CASE WHEN t.typrelid != 0\n"
647  " THEN CAST('tuple' AS pg_catalog.text)\n"
648  " WHEN t.typlen < 0\n"
649  " THEN CAST('var' AS pg_catalog.text)\n"
650  " ELSE CAST(t.typlen AS pg_catalog.text)\n"
651  " END AS \"%s\",\n",
652  gettext_noop("Internal name"),
653  gettext_noop("Size"));
654  if (verbose && pset.sversion >= 80300)
655  {
657  " pg_catalog.array_to_string(\n"
658  " ARRAY(\n"
659  " SELECT e.enumlabel\n"
660  " FROM pg_catalog.pg_enum e\n"
661  " WHERE e.enumtypid = t.oid\n");
662 
663  if (pset.sversion >= 90100)
665  " ORDER BY e.enumsortorder\n");
666  else
668  " ORDER BY e.oid\n");
669 
670  appendPQExpBuffer(&buf,
671  " ),\n"
672  " E'\\n'\n"
673  " ) AS \"%s\",\n",
674  gettext_noop("Elements"));
675  }
676  if (verbose)
677  {
678  appendPQExpBuffer(&buf,
679  " pg_catalog.pg_get_userbyid(t.typowner) AS \"%s\",\n",
680  gettext_noop("Owner"));
681  }
682  if (verbose && pset.sversion >= 90200)
683  {
684  printACLColumn(&buf, "t.typacl");
685  appendPQExpBufferStr(&buf, ",\n ");
686  }
687 
688  appendPQExpBuffer(&buf,
689  " pg_catalog.obj_description(t.oid, 'pg_type') as \"%s\"\n",
690  gettext_noop("Description"));
691 
692  appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_type t\n"
693  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
694 
695  /*
696  * do not include complex types (typrelid!=0) unless they are standalone
697  * composite types
698  */
699  appendPQExpBufferStr(&buf, "WHERE (t.typrelid = 0 ");
700  appendPQExpBufferStr(&buf, "OR (SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
701  " FROM pg_catalog.pg_class c "
702  "WHERE c.oid = t.typrelid))\n");
703 
704  /*
705  * do not include array types (before 8.3 we have to use the assumption
706  * that their names start with underscore)
707  */
708  if (pset.sversion >= 80300)
709  appendPQExpBufferStr(&buf, " AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n");
710  else
711  appendPQExpBufferStr(&buf, " AND t.typname !~ '^_'\n");
712 
713  if (!showSystem && !pattern)
714  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
715  " AND n.nspname <> 'information_schema'\n");
716 
717  /* Match name pattern against either internal or external name */
718  processSQLNamePattern(pset.db, &buf, pattern, true, false,
719  "n.nspname", "t.typname",
720  "pg_catalog.format_type(t.oid, NULL)",
721  "pg_catalog.pg_type_is_visible(t.oid)");
722 
723  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
724 
725  res = PSQLexec(buf.data);
726  termPQExpBuffer(&buf);
727  if (!res)
728  return false;
729 
730  myopt.nullPrint = NULL;
731  myopt.title = _("List of data types");
732  myopt.translate_header = true;
733 
734  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
735 
736  PQclear(res);
737  return true;
738 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
static int verbose
Definition: pg_basebackup.c:88
#define CppAsString2(x)
Definition: c.h:224
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition: describe.c:5493
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ listAllDbs()

bool listAllDbs ( const char *  pattern,
bool  verbose 
)

Definition at line 823 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, and printQueryOpt::translate_header.

Referenced by exec_command_list(), and main().

824 {
825  PGresult *res;
827  printQueryOpt myopt = pset.popt;
828 
829  initPQExpBuffer(&buf);
830 
831  printfPQExpBuffer(&buf,
832  "SELECT d.datname as \"%s\",\n"
833  " pg_catalog.pg_get_userbyid(d.datdba) as \"%s\",\n"
834  " pg_catalog.pg_encoding_to_char(d.encoding) as \"%s\",\n",
835  gettext_noop("Name"),
836  gettext_noop("Owner"),
837  gettext_noop("Encoding"));
838  if (pset.sversion >= 80400)
839  appendPQExpBuffer(&buf,
840  " d.datcollate as \"%s\",\n"
841  " d.datctype as \"%s\",\n",
842  gettext_noop("Collate"),
843  gettext_noop("Ctype"));
844  appendPQExpBufferStr(&buf, " ");
845  printACLColumn(&buf, "d.datacl");
846  if (verbose && pset.sversion >= 80200)
847  appendPQExpBuffer(&buf,
848  ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n"
849  " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n"
850  " ELSE 'No Access'\n"
851  " END as \"%s\"",
852  gettext_noop("Size"));
853  if (verbose && pset.sversion >= 80000)
854  appendPQExpBuffer(&buf,
855  ",\n t.spcname as \"%s\"",
856  gettext_noop("Tablespace"));
857  if (verbose && pset.sversion >= 80200)
858  appendPQExpBuffer(&buf,
859  ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"",
860  gettext_noop("Description"));
862  "\nFROM pg_catalog.pg_database d\n");
863  if (verbose && pset.sversion >= 80000)
865  " JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
866 
867  if (pattern)
868  processSQLNamePattern(pset.db, &buf, pattern, false, false,
869  NULL, "d.datname", NULL, NULL);
870 
871  appendPQExpBufferStr(&buf, "ORDER BY 1;");
872  res = PSQLexec(buf.data);
873  termPQExpBuffer(&buf);
874  if (!res)
875  return false;
876 
877  myopt.nullPrint = NULL;
878  myopt.title = _("List of databases");
879  myopt.translate_header = true;
880 
881  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
882 
883  PQclear(res);
884  return true;
885 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
static int verbose
Definition: pg_basebackup.c:88
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition: describe.c:5493
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ listCasts()

bool listCasts ( const char *  pattern,
bool  verbose 
)

Definition at line 3881 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by exec_command_d().

3882 {
3884  PGresult *res;
3885  printQueryOpt myopt = pset.popt;
3886  static const bool translate_columns[] = {false, false, false, true, false};
3887 
3888  initPQExpBuffer(&buf);
3889 
3890  /*
3891  * We need a left join to pg_proc for binary casts; the others are just
3892  * paranoia. Also note that we don't attempt to localize '(binary
3893  * coercible)', because there's too much risk of gettext translating a
3894  * function name that happens to match some string in the PO database.
3895  */
3896  printfPQExpBuffer(&buf,
3897  "SELECT pg_catalog.format_type(castsource, NULL) AS \"%s\",\n"
3898  " pg_catalog.format_type(casttarget, NULL) AS \"%s\",\n"
3899  " CASE WHEN castfunc = 0 THEN '(binary coercible)'\n"
3900  " ELSE p.proname\n"
3901  " END as \"%s\",\n"
3902  " CASE WHEN c.castcontext = 'e' THEN '%s'\n"
3903  " WHEN c.castcontext = 'a' THEN '%s'\n"
3904  " ELSE '%s'\n"
3905  " END as \"%s\"",
3906  gettext_noop("Source type"),
3907  gettext_noop("Target type"),
3908  gettext_noop("Function"),
3909  gettext_noop("no"),
3910  gettext_noop("in assignment"),
3911  gettext_noop("yes"),
3912  gettext_noop("Implicit?"));
3913 
3914  if (verbose)
3915  appendPQExpBuffer(&buf,
3916  ",\n d.description AS \"%s\"\n",
3917  gettext_noop("Description"));
3918 
3919  appendPQExpBufferStr(&buf,
3920  "FROM pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p\n"
3921  " ON c.castfunc = p.oid\n"
3922  " LEFT JOIN pg_catalog.pg_type ts\n"
3923  " ON c.castsource = ts.oid\n"
3924  " LEFT JOIN pg_catalog.pg_namespace ns\n"
3925  " ON ns.oid = ts.typnamespace\n"
3926  " LEFT JOIN pg_catalog.pg_type tt\n"
3927  " ON c.casttarget = tt.oid\n"
3928  " LEFT JOIN pg_catalog.pg_namespace nt\n"
3929  " ON nt.oid = tt.typnamespace\n");
3930 
3931  if (verbose)
3932  appendPQExpBufferStr(&buf,
3933  " LEFT JOIN pg_catalog.pg_description d\n"
3934  " ON d.classoid = c.tableoid AND d.objoid = "
3935  "c.oid AND d.objsubid = 0\n");
3936 
3937  appendPQExpBufferStr(&buf, "WHERE ( (true");
3938 
3939  /*
3940  * Match name pattern against either internal or external name of either
3941  * castsource or casttarget
3942  */
3943  processSQLNamePattern(pset.db, &buf, pattern, true, false,
3944  "ns.nspname", "ts.typname",
3945  "pg_catalog.format_type(ts.oid, NULL)",
3946  "pg_catalog.pg_type_is_visible(ts.oid)");
3947 
3948  appendPQExpBufferStr(&buf, ") OR (true");
3949 
3950  processSQLNamePattern(pset.db, &buf, pattern, true, false,
3951  "nt.nspname", "tt.typname",
3952  "pg_catalog.format_type(tt.oid, NULL)",
3953  "pg_catalog.pg_type_is_visible(tt.oid)");
3954 
3955  appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;");
3956 
3957  res = PSQLexec(buf.data);
3958  termPQExpBuffer(&buf);
3959  if (!res)
3960  return false;
3961 
3962  myopt.nullPrint = NULL;
3963  myopt.title = _("List of casts");
3964  myopt.translate_header = true;
3965  myopt.translate_columns = translate_columns;
3966  myopt.n_translate_columns = lengthof(translate_columns);
3967 
3968  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
3969 
3970  PQclear(res);
3971  return true;
3972 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
#define lengthof(array)
Definition: c.h:629
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
static int verbose
Definition: pg_basebackup.c:88
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:172
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
const bool * translate_columns
Definition: print.h:170
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ listCollations()

bool listCollations ( const char *  pattern,
bool  verbose,
bool  showSystem 
)

Definition at line 3980 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, psql_error(), PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by exec_command_d().

3981 {
3983  PGresult *res;
3984  printQueryOpt myopt = pset.popt;
3985  static const bool translate_columns[] = {false, false, false, false, false, false};
3986 
3987  if (pset.sversion < 90100)
3988  {
3989  char sverbuf[32];
3990 
3991  psql_error("The server (version %s) does not support collations.\n",
3993  sverbuf, sizeof(sverbuf)));
3994  return true;
3995  }
3996 
3997  initPQExpBuffer(&buf);
3998 
3999  printfPQExpBuffer(&buf,
4000  "SELECT n.nspname AS \"%s\",\n"
4001  " c.collname AS \"%s\",\n"
4002  " c.collcollate AS \"%s\",\n"
4003  " c.collctype AS \"%s\"",
4004  gettext_noop("Schema"),
4005  gettext_noop("Name"),
4006  gettext_noop("Collate"),
4007  gettext_noop("Ctype"));
4008 
4009  if (pset.sversion >= 100000)
4010  appendPQExpBuffer(&buf,
4011  ",\n CASE c.collprovider WHEN 'd' THEN 'default' WHEN 'c' THEN 'libc' WHEN 'i' THEN 'icu' END AS \"%s\"",
4012  gettext_noop("Provider"));
4013 
4014  if (verbose)
4015  appendPQExpBuffer(&buf,
4016  ",\n pg_catalog.obj_description(c.oid, 'pg_collation') AS \"%s\"",
4017  gettext_noop("Description"));
4018 
4019  appendPQExpBufferStr(&buf,
4020  "\nFROM pg_catalog.pg_collation c, pg_catalog.pg_namespace n\n"
4021  "WHERE n.oid = c.collnamespace\n");
4022 
4023  if (!showSystem && !pattern)
4024  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4025  " AND n.nspname <> 'information_schema'\n");
4026 
4027  /*
4028  * Hide collations that aren't usable in the current database's encoding.
4029  * If you think to change this, note that pg_collation_is_visible rejects
4030  * unusable collations, so you will need to hack name pattern processing
4031  * somehow to avoid inconsistent behavior.
4032  */
4033  appendPQExpBufferStr(&buf, " AND c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))\n");
4034 
4035  processSQLNamePattern(pset.db, &buf, pattern, true, false,
4036  "n.nspname", "c.collname", NULL,
4037  "pg_catalog.pg_collation_is_visible(c.oid)");
4038 
4039  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4040 
4041  res = PSQLexec(buf.data);
4042  termPQExpBuffer(&buf);
4043  if (!res)
4044  return false;
4045 
4046  myopt.nullPrint = NULL;
4047  myopt.title = _("List of collations");
4048  myopt.translate_header = true;
4049  myopt.translate_columns = translate_columns;
4050  myopt.n_translate_columns = lengthof(translate_columns);
4051 
4052  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4053 
4054  PQclear(res);
4055  return true;
4056 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
#define lengthof(array)
Definition: c.h:629
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
static int verbose
Definition: pg_basebackup.c:88
void psql_error(const char *fmt,...)
Definition: common.c:221
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:172
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
const bool * translate_columns
Definition: print.h:170
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:182
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ listConversions()

bool listConversions ( const char *  pattern,
bool  verbose,
bool  showSystem 
)

Definition at line 3739 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by exec_command_d().

3740 {
3742  PGresult *res;
3743  printQueryOpt myopt = pset.popt;
3744  static const bool translate_columns[] =
3745  {false, false, false, false, true, false};
3746 
3747  initPQExpBuffer(&buf);
3748 
3749  printfPQExpBuffer(&buf,
3750  "SELECT n.nspname AS \"%s\",\n"
3751  " c.conname AS \"%s\",\n"
3752  " pg_catalog.pg_encoding_to_char(c.conforencoding) AS \"%s\",\n"
3753  " pg_catalog.pg_encoding_to_char(c.contoencoding) AS \"%s\",\n"
3754  " CASE WHEN c.condefault THEN '%s'\n"
3755  " ELSE '%s' END AS \"%s\"",
3756  gettext_noop("Schema"),
3757  gettext_noop("Name"),
3758  gettext_noop("Source"),
3759  gettext_noop("Destination"),
3760  gettext_noop("yes"), gettext_noop("no"),
3761  gettext_noop("Default?"));
3762 
3763  if (verbose)
3764  appendPQExpBuffer(&buf,
3765  ",\n d.description AS \"%s\"",
3766  gettext_noop("Description"));
3767 
3768  appendPQExpBufferStr(&buf,
3769  "\nFROM pg_catalog.pg_conversion c\n"
3770  " JOIN pg_catalog.pg_namespace n "
3771  "ON n.oid = c.connamespace\n");
3772 
3773  if (verbose)
3774  appendPQExpBufferStr(&buf,
3775  "LEFT JOIN pg_catalog.pg_description d "
3776  "ON d.classoid = c.tableoid\n"
3777  " AND d.objoid = c.oid "
3778  "AND d.objsubid = 0\n");
3779 
3780  appendPQExpBufferStr(&buf, "WHERE true\n");
3781 
3782  if (!showSystem && !pattern)
3783  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
3784  " AND n.nspname <> 'information_schema'\n");
3785 
3786  processSQLNamePattern(pset.db, &buf, pattern, true, false,
3787  "n.nspname", "c.conname", NULL,
3788  "pg_catalog.pg_conversion_is_visible(c.oid)");
3789 
3790  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
3791 
3792  res = PSQLexec(buf.data);
3793  termPQExpBuffer(&buf);
3794  if (!res)
3795  return false;
3796 
3797  myopt.nullPrint = NULL;
3798  myopt.title = _("List of conversions");
3799  myopt.translate_header = true;
3800  myopt.translate_columns = translate_columns;
3801  myopt.n_translate_columns = lengthof(translate_columns);
3802 
3803  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
3804 
3805  PQclear(res);
3806  return true;
3807 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
#define lengthof(array)
Definition: c.h:629
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
static int verbose
Definition: pg_basebackup.c:88
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:172
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
const bool * translate_columns
Definition: print.h:170
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ listDbRoleSettings()

bool listDbRoleSettings ( const char *  pattern,
const char *  pattern2 
)

Definition at line 3328 of file describe.c.

References _, appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), PQntuples(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, psql_error(), PSQLexec(), _psqlSettings::queryFout, _psqlSettings::quiet, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, and printQueryOpt::translate_header.

Referenced by exec_command_d().

3329 {
3331  PGresult *res;
3332  printQueryOpt myopt = pset.popt;
3333  bool havewhere;
3334 
3335  if (pset.sversion < 90000)
3336  {
3337  char sverbuf[32];
3338 
3339  psql_error("The server (version %s) does not support per-database role settings.\n",
3341  sverbuf, sizeof(sverbuf)));
3342  return true;
3343  }
3344 
3345  initPQExpBuffer(&buf);
3346 
3347  printfPQExpBuffer(&buf, "SELECT rolname AS \"%s\", datname AS \"%s\",\n"
3348  "pg_catalog.array_to_string(setconfig, E'\\n') AS \"%s\"\n"
3349  "FROM pg_catalog.pg_db_role_setting s\n"
3350  "LEFT JOIN pg_catalog.pg_database d ON d.oid = setdatabase\n"
3351  "LEFT JOIN pg_catalog.pg_roles r ON r.oid = setrole\n",
3352  gettext_noop("Role"),
3353  gettext_noop("Database"),
3354  gettext_noop("Settings"));
3355  havewhere = processSQLNamePattern(pset.db, &buf, pattern, false, false,
3356  NULL, "r.rolname", NULL, NULL);
3357  processSQLNamePattern(pset.db, &buf, pattern2, havewhere, false,
3358  NULL, "d.datname", NULL, NULL);
3359  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
3360 
3361  res = PSQLexec(buf.data);
3362  termPQExpBuffer(&buf);
3363  if (!res)
3364  return false;
3365 
3366  /*
3367  * Most functions in this file are content to print an empty table when
3368  * there are no matching objects. We intentionally deviate from that
3369  * here, but only in !quiet mode, because of the possibility that the user
3370  * is confused about what the two pattern arguments mean.
3371  */
3372  if (PQntuples(res) == 0 && !pset.quiet)
3373  {
3374  if (pattern && pattern2)
3375  psql_error("Did not find any settings for role \"%s\" and database \"%s\".\n",
3376  pattern, pattern2);
3377  else if (pattern)
3378  psql_error("Did not find any settings for role \"%s\".\n",
3379  pattern);
3380  else
3381  psql_error("Did not find any settings.\n");
3382  }
3383  else
3384  {
3385  myopt.nullPrint = NULL;
3386  myopt.title = _("List of settings");
3387  myopt.translate_header = true;
3388 
3389  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
3390  }
3391 
3392  PQclear(res);
3393  return true;
3394 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
void psql_error(const char *fmt,...)
Definition: common.c:221
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:182
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ listDefaultACLs()

bool listDefaultACLs ( const char *  pattern)

Definition at line 1053 of file describe.c.

References _, appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, psql_error(), PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by exec_command_d().

1054 {
1056  PGresult *res;
1057  printQueryOpt myopt = pset.popt;
1058  static const bool translate_columns[] = {false, false, true, false};
1059 
1060  if (pset.sversion < 90000)
1061  {
1062  char sverbuf[32];
1063 
1064  psql_error("The server (version %s) does not support altering default privileges.\n",
1066  sverbuf, sizeof(sverbuf)));
1067  return true;
1068  }
1069 
1070  initPQExpBuffer(&buf);
1071 
1072  printfPQExpBuffer(&buf,
1073  "SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS \"%s\",\n"
1074  " n.nspname AS \"%s\",\n"
1075  " CASE d.defaclobjtype WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' END AS \"%s\",\n"
1076  " ",
1077  gettext_noop("Owner"),
1078  gettext_noop("Schema"),
1079  DEFACLOBJ_RELATION,
1080  gettext_noop("table"),
1081  DEFACLOBJ_SEQUENCE,
1082  gettext_noop("sequence"),
1083  DEFACLOBJ_FUNCTION,
1084  gettext_noop("function"),
1085  DEFACLOBJ_TYPE,
1086  gettext_noop("type"),
1087  DEFACLOBJ_NAMESPACE,
1088  gettext_noop("schema"),
1089  gettext_noop("Type"));
1090 
1091  printACLColumn(&buf, "d.defaclacl");
1092 
1093  appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_default_acl d\n"
1094  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.defaclnamespace\n");
1095 
1096  processSQLNamePattern(pset.db, &buf, pattern, false, false,
1097  NULL,
1098  "n.nspname",
1099  "pg_catalog.pg_get_userbyid(d.defaclrole)",
1100  NULL);
1101 
1102  appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
1103 
1104  res = PSQLexec(buf.data);
1105  if (!res)
1106  {
1107  termPQExpBuffer(&buf);
1108  return false;
1109  }
1110 
1111  myopt.nullPrint = NULL;
1112  printfPQExpBuffer(&buf, _("Default access privileges"));
1113  myopt.title = buf.data;
1114  myopt.translate_header = true;
1115  myopt.translate_columns = translate_columns;
1116  myopt.n_translate_columns = lengthof(translate_columns);
1117 
1118  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1119 
1120  termPQExpBuffer(&buf);
1121  PQclear(res);
1122  return true;
1123 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
#define lengthof(array)
Definition: c.h:629
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
void psql_error(const char *fmt,...)
Definition: common.c:221
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:172
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
const bool * translate_columns
Definition: print.h:170
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition: describe.c:5493
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:182
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ listDomains()

bool listDomains ( const char *  pattern,
bool  verbose,
bool  showSystem 
)

Definition at line 3653 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, and printQueryOpt::translate_header.

Referenced by exec_command_d().

3654 {
3656  PGresult *res;
3657  printQueryOpt myopt = pset.popt;
3658 
3659  initPQExpBuffer(&buf);
3660 
3661  printfPQExpBuffer(&buf,
3662  "SELECT n.nspname as \"%s\",\n"
3663  " t.typname as \"%s\",\n"
3664  " pg_catalog.format_type(t.typbasetype, t.typtypmod) as \"%s\",\n",
3665  gettext_noop("Schema"),
3666  gettext_noop("Name"),
3667  gettext_noop("Type"));
3668 
3669  if (pset.sversion >= 90100)
3670  appendPQExpBuffer(&buf,
3671  " (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type bt\n"
3672  " WHERE c.oid = t.typcollation AND bt.oid = t.typbasetype AND t.typcollation <> bt.typcollation) as \"%s\",\n",
3673  gettext_noop("Collation"));
3674  appendPQExpBuffer(&buf,
3675  " CASE WHEN t.typnotnull THEN 'not null' END as \"%s\",\n"
3676  " t.typdefault as \"%s\",\n"
3677  " pg_catalog.array_to_string(ARRAY(\n"
3678  " SELECT pg_catalog.pg_get_constraintdef(r.oid, true) FROM pg_catalog.pg_constraint r WHERE t.oid = r.contypid\n"
3679  " ), ' ') as \"%s\"",
3680  gettext_noop("Nullable"),
3681  gettext_noop("Default"),
3682  gettext_noop("Check"));
3683 
3684  if (verbose)
3685  {
3686  if (pset.sversion >= 90200)
3687  {
3688  appendPQExpBufferStr(&buf, ",\n ");
3689  printACLColumn(&buf, "t.typacl");
3690  }
3691  appendPQExpBuffer(&buf,
3692  ",\n d.description as \"%s\"",
3693  gettext_noop("Description"));
3694  }
3695 
3696  appendPQExpBufferStr(&buf,
3697  "\nFROM pg_catalog.pg_type t\n"
3698  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
3699 
3700  if (verbose)
3701  appendPQExpBufferStr(&buf,
3702  " LEFT JOIN pg_catalog.pg_description d "
3703  "ON d.classoid = t.tableoid AND d.objoid = t.oid "
3704  "AND d.objsubid = 0\n");
3705 
3706  appendPQExpBufferStr(&buf, "WHERE t.typtype = 'd'\n");
3707 
3708  if (!showSystem && !pattern)
3709  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
3710  " AND n.nspname <> 'information_schema'\n");
3711 
3712  processSQLNamePattern(pset.db, &buf, pattern, true, false,
3713  "n.nspname", "t.typname", NULL,
3714  "pg_catalog.pg_type_is_visible(t.oid)");
3715 
3716  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
3717 
3718  res = PSQLexec(buf.data);
3719  termPQExpBuffer(&buf);
3720  if (!res)
3721  return false;
3722 
3723  myopt.nullPrint = NULL;
3724  myopt.title = _("List of domains");
3725  myopt.translate_header = true;
3726 
3727  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
3728 
3729  PQclear(res);
3730  return true;
3731 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
static int verbose
Definition: pg_basebackup.c:88
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition: describe.c:5493
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ listEventTriggers()

bool listEventTriggers ( const char *  pattern,
bool  verbose 
)

Definition at line 3815 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, printQueryOpt::nullPrint, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by exec_command_d().

3816 {
3818  PGresult *res;
3819  printQueryOpt myopt = pset.popt;
3820  static const bool translate_columns[] =
3821  {false, false, false, true, false, false, false};
3822 
3823  initPQExpBuffer(&buf);
3824 
3825  printfPQExpBuffer(&buf,
3826  "SELECT evtname as \"%s\", "
3827  "evtevent as \"%s\", "
3828  "pg_catalog.pg_get_userbyid(e.evtowner) as \"%s\",\n"
3829  " case evtenabled when 'O' then '%s'"
3830  " when 'R' then '%s'"
3831  " when 'A' then '%s'"
3832  " when 'D' then '%s' end as \"%s\",\n"
3833  " e.evtfoid::pg_catalog.regproc as \"%s\", "
3834  "pg_catalog.array_to_string(array(select x"
3835  " from pg_catalog.unnest(evttags) as t(x)), ', ') as \"%s\"",
3836  gettext_noop("Name"),
3837  gettext_noop("Event"),
3838  gettext_noop("Owner"),
3839  gettext_noop("enabled"),
3840  gettext_noop("replica"),
3841  gettext_noop("always"),
3842  gettext_noop("disabled"),
3843  gettext_noop("Enabled"),
3844  gettext_noop("Procedure"),
3845  gettext_noop("Tags"));
3846  if (verbose)
3847  appendPQExpBuffer(&buf,
3848  ",\npg_catalog.obj_description(e.oid, 'pg_event_trigger') as \"%s\"",
3849  gettext_noop("Description"));
3850  appendPQExpBufferStr(&buf,
3851  "\nFROM pg_catalog.pg_event_trigger e ");
3852 
3853  processSQLNamePattern(pset.db, &buf, pattern, false, false,
3854  NULL, "evtname", NULL, NULL);
3855 
3856  appendPQExpBufferStr(&buf, "ORDER BY 1");
3857 
3858  res = PSQLexec(buf.data);
3859  termPQExpBuffer(&buf);
3860  if (!res)
3861  return false;
3862 
3863  myopt.nullPrint = NULL;
3864  myopt.title = _("List of event triggers");
3865  myopt.translate_header = true;
3866  myopt.translate_columns = translate_columns;
3867  myopt.n_translate_columns = lengthof(translate_columns);
3868 
3869  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
3870 
3871  PQclear(res);
3872  return true;
3873 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
char * nullPrint
Definition: print.h:166
PsqlSettings pset
Definition: startup.c:33
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
#define gettext_noop(x)
Definition: c.h:1036
FILE * queryFout
Definition: settings.h:84
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule)
Definition: string_utils.c:833
#define lengthof(array)
Definition: c.h:629
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:169
static int verbose
Definition: pg_basebackup.c:88
FILE * logfile
Definition: settings.h:115
void PQclear(PGresult *res)
Definition: fe-exec.c:671
char * title
Definition: print.h:167
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:172
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3287
const bool * translate_columns
Definition: print.h:170
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
PGresult * PSQLexec(const char *query)
Definition: common.c:690

◆ listExtensionContents()

bool listExtensionContents ( const char *  pattern)

Definition at line 5077 of file describe.c.

References appendPQExpBufferStr(), buf, cancel_pressed, PQExpBufferData::data, _psqlSettings::db, formatPGVersionNumber(), i, initPQExpBuffer(), listOneExtensionContents(), PQclear(), PQgetvalue(), PQntuples(), printfPQExpBuffer(), processSQLNamePattern(), pset, psql_error(), PSQLexec(), _psqlSettings::quiet, _psqlSettings::sversion, and termPQExpBuffer().

Referenced by exec_command_d().

5078 {
5080  PGresult *res;
5081  int i;
5082 
5083  if (pset.sversion < 90100)
5084  {
5085  char sverbuf[32];
5086 
5087  psql_error("The server (version %s) does not support extensions.\n",
5089  sverbuf, sizeof(sverbuf)));
5090  return true;
5091  }
5092 
5093  initPQExpBuffer(&buf);
5094  printfPQExpBuffer(&buf,
5095  "SELECT e.extname, e.oid\n"
5096  "FROM pg_catalog.pg_extension e\n");
5097 
5098  processSQLNamePattern(pset.db, &buf, pattern,
5099  false, false,
5100  NULL, "e.extname", NULL,
5101  NULL);
5102 
5103  appendPQExpBufferStr(&buf, "ORDER BY 1;");
5104 
5105  res = PSQLexec(buf.data);
5106  termPQExpBuffer(&buf);
5107  if (!res)
5108  return false;
5109 
5110  if (PQntuples(res) == 0)
5111  {
5112  if (!pset.quiet)
5113  {
5114  if (pattern)
5115  psql_error("Did not find any extension named \"%s\".\n",
5116  pattern);
5117  else
5118  psql_error("Did not find any extensions.\n");
5119  }
5120  PQclear(res);
5121  return false;
5122