PostgreSQL Source Code  git master
describe.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include "catalog/pg_am.h"
#include "catalog/pg_attribute_d.h"
#include "catalog/pg_cast_d.h"
#include "catalog/pg_class_d.h"
#include "catalog/pg_default_acl_d.h"
#include "common.h"
#include "common/logging.h"
#include "describe.h"
#include "fe_utils/mbprint.h"
#include "fe_utils/print.h"
#include "fe_utils/string_utils.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 listPartitionedTables (const char *reltypes, const char *pattern, bool verbose)
 
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)
 
bool listOperatorClasses (const char *access_method_pattern, const char *type_pattern, bool verbose)
 
bool listOperatorFamilies (const char *access_method_pattern, const char *type_pattern, bool verbose)
 
bool listOpFamilyOperators (const char *access_method_pattern, const char *family_pattern, bool verbose)
 
bool listOpFamilyProcedures (const char *access_method_pattern, const char *family_pattern)
 

Function Documentation

◆ add_role_attribute()

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

Definition at line 3572 of file describe.c.

References appendPQExpBufferStr(), and PQExpBufferData::len.

Referenced by describeRoles().

3573 {
3574  if (buf->len > 0)
3575  appendPQExpBufferStr(buf, ", ");
3576 
3577  appendPQExpBufferStr(buf, str);
3578 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369

◆ add_tablespace_footer()

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

Definition at line 3347 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().

3349 {
3350  /* relkinds for which we support tablespaces */
3351  if (relkind == RELKIND_RELATION ||
3352  relkind == RELKIND_MATVIEW ||
3353  relkind == RELKIND_INDEX ||
3354  relkind == RELKIND_PARTITIONED_TABLE ||
3355  relkind == RELKIND_PARTITIONED_INDEX ||
3356  relkind == RELKIND_TOASTVALUE)
3357  {
3358  /*
3359  * We ignore the database default tablespace so that users not using
3360  * tablespaces don't need to know about them. This case also covers
3361  * pre-8.0 servers, for which tablespace will always be 0.
3362  */
3363  if (tablespace != 0)
3364  {
3365  PGresult *result = NULL;
3367 
3368  initPQExpBuffer(&buf);
3369  printfPQExpBuffer(&buf,
3370  "SELECT spcname FROM pg_catalog.pg_tablespace\n"
3371  "WHERE oid = '%u';", tablespace);
3372  result = PSQLexec(buf.data);
3373  if (!result)
3374  {
3375  termPQExpBuffer(&buf);
3376  return;
3377  }
3378  /* Should always be the case, but.... */
3379  if (PQntuples(result) > 0)
3380  {
3381  if (newline)
3382  {
3383  /* Add the tablespace as a new footer */
3384  printfPQExpBuffer(&buf, _("Tablespace: \"%s\""),
3385  PQgetvalue(result, 0, 0));
3386  printTableAddFooter(cont, buf.data);
3387  }
3388  else
3389  {
3390  /* Append the tablespace to the latest footer */
3391  printfPQExpBuffer(&buf, "%s", cont->footer->data);
3392 
3393  /*-------
3394  translator: before this string there's an index description like
3395  '"foo_pkey" PRIMARY KEY, btree (a)' */
3396  appendPQExpBuffer(&buf, _(", tablespace \"%s\""),
3397  PQgetvalue(result, 0, 0));
3398  printTableSetFooter(cont, buf.data);
3399  }
3400  }
3401  PQclear(result);
3402  termPQExpBuffer(&buf);
3403  }
3404  }
3405 }
void printTableSetFooter(printTableContent *const content, const char *footer)
Definition: print.c:3223
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3163
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2769
static chr newline(void)
Definition: regc_lex.c:1138
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:67
char * tablespace
Definition: pgbench.c:188
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition: print.c:3198
printTableFooter * footer
Definition: print.h:161
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * data
Definition: print.h:139
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ describeAccessMethods()

bool describeAccessMethods ( const char *  pattern,
bool  verbose 
)

Definition at line 149 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, pg_log_error, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by exec_command_d().

150 {
152  PGresult *res;
153  printQueryOpt myopt = pset.popt;
154  static const bool translate_columns[] = {false, true, false, false};
155 
156  if (pset.sversion < 90600)
157  {
158  char sverbuf[32];
159 
160  pg_log_error("The server (version %s) does not support access methods.",
162  sverbuf, sizeof(sverbuf)));
163  return true;
164  }
165 
166  initPQExpBuffer(&buf);
167 
168  printfPQExpBuffer(&buf,
169  "SELECT amname AS \"%s\",\n"
170  " CASE amtype"
171  " WHEN 'i' THEN '%s'"
172  " WHEN 't' THEN '%s'"
173  " END AS \"%s\"",
174  gettext_noop("Name"),
175  gettext_noop("Index"),
176  gettext_noop("Table"),
177  gettext_noop("Type"));
178 
179  if (verbose)
180  {
181  appendPQExpBuffer(&buf,
182  ",\n amhandler AS \"%s\",\n"
183  " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"",
184  gettext_noop("Handler"),
185  gettext_noop("Description"));
186  }
187 
189  "\nFROM pg_catalog.pg_am\n");
190 
191  processSQLNamePattern(pset.db, &buf, pattern, false, false,
192  NULL, "amname", NULL,
193  NULL);
194 
195  appendPQExpBufferStr(&buf, "ORDER BY 1;");
196 
197  res = PSQLexec(buf.data);
198  termPQExpBuffer(&buf);
199  if (!res)
200  return false;
201 
202  myopt.nullPrint = NULL;
203  myopt.title = _("List of access methods");
204  myopt.translate_header = true;
205  myopt.translate_columns = translate_columns;
206  myopt.n_translate_columns = lengthof(translate_columns);
207 
208  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
209 
210  PQclear(res);
211  return true;
212 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * nullPrint
Definition: print.h:170
PsqlSettings pset
Definition: startup.c:31
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
#define pg_log_error(...)
Definition: logging.h:79
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define gettext_noop(x)
Definition: c.h:1160
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:827
#define lengthof(array)
Definition: c.h:668
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:173
static int verbose
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * title
Definition: print.h:171
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:176
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3433
const bool * translate_columns
Definition: print.h:174
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:177
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ describeAggregates()

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

Definition at line 63 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().

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

◆ describeFunctions()

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

Definition at line 315 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, pg_log_error, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by exec_command_d().

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

◆ describeOneTableDetails()

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

Definition at line 1445 of file describe.c.

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

Referenced by describeTableDetails().

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

◆ describeOneTSConfig()

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

Definition at line 5173 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().

5175 {
5177  title;
5178  PGresult *res;
5179  printQueryOpt myopt = pset.popt;
5180 
5181  initPQExpBuffer(&buf);
5182 
5183  printfPQExpBuffer(&buf,
5184  "SELECT\n"
5185  " ( SELECT t.alias FROM\n"
5186  " pg_catalog.ts_token_type(c.cfgparser) AS t\n"
5187  " WHERE t.tokid = m.maptokentype ) AS \"%s\",\n"
5188  " pg_catalog.btrim(\n"
5189  " ARRAY( SELECT mm.mapdict::pg_catalog.regdictionary\n"
5190  " FROM pg_catalog.pg_ts_config_map AS mm\n"
5191  " WHERE mm.mapcfg = m.mapcfg AND mm.maptokentype = m.maptokentype\n"
5192  " ORDER BY mapcfg, maptokentype, mapseqno\n"
5193  " ) :: pg_catalog.text,\n"
5194  " '{}') AS \"%s\"\n"
5195  "FROM pg_catalog.pg_ts_config AS c, pg_catalog.pg_ts_config_map AS m\n"
5196  "WHERE c.oid = '%s' AND m.mapcfg = c.oid\n"
5197  "GROUP BY m.mapcfg, m.maptokentype, c.cfgparser\n"
5198  "ORDER BY 1;",
5199  gettext_noop("Token"),
5200  gettext_noop("Dictionaries"),
5201  oid);
5202 
5203  res = PSQLexec(buf.data);
5204  termPQExpBuffer(&buf);
5205  if (!res)
5206  return false;
5207 
5208  initPQExpBuffer(&title);
5209 
5210  if (nspname)
5211  appendPQExpBuffer(&title, _("Text search configuration \"%s.%s\""),
5212  nspname, cfgname);
5213  else
5214  appendPQExpBuffer(&title, _("Text search configuration \"%s\""),
5215  cfgname);
5216 
5217  if (pnspname)
5218  appendPQExpBuffer(&title, _("\nParser: \"%s.%s\""),
5219  pnspname, prsname);
5220  else
5221  appendPQExpBuffer(&title, _("\nParser: \"%s\""),
5222  prsname);
5223 
5224  myopt.nullPrint = NULL;
5225  myopt.title = title.data;
5226  myopt.footers = NULL;
5227  myopt.topt.default_footer = false;
5228  myopt.translate_header = true;
5229 
5230  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5231 
5232  termPQExpBuffer(&title);
5233 
5234  PQclear(res);
5235  return true;
5236 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * nullPrint
Definition: print.h:170
PsqlSettings pset
Definition: startup.c:31
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
printTableOpt topt
Definition: print.h:169
#define gettext_noop(x)
Definition: c.h:1160
FILE * queryFout
Definition: settings.h:84
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:173
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * title
Definition: print.h:171
char ** footers
Definition: print.h:172
bool default_footer
Definition: print.h:113
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3433
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ describeOneTSParser()

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

Definition at line 4778 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().

4779 {
4781  PGresult *res;
4782  PQExpBufferData title;
4783  printQueryOpt myopt = pset.popt;
4784  static const bool translate_columns[] = {true, false, false};
4785 
4786  initPQExpBuffer(&buf);
4787 
4788  printfPQExpBuffer(&buf,
4789  "SELECT '%s' AS \"%s\",\n"
4790  " p.prsstart::pg_catalog.regproc AS \"%s\",\n"
4791  " pg_catalog.obj_description(p.prsstart, 'pg_proc') as \"%s\"\n"
4792  " FROM pg_catalog.pg_ts_parser p\n"
4793  " WHERE p.oid = '%s'\n"
4794  "UNION ALL\n"
4795  "SELECT '%s',\n"
4796  " p.prstoken::pg_catalog.regproc,\n"
4797  " pg_catalog.obj_description(p.prstoken, 'pg_proc')\n"
4798  " FROM pg_catalog.pg_ts_parser p\n"
4799  " WHERE p.oid = '%s'\n"
4800  "UNION ALL\n"
4801  "SELECT '%s',\n"
4802  " p.prsend::pg_catalog.regproc,\n"
4803  " pg_catalog.obj_description(p.prsend, 'pg_proc')\n"
4804  " FROM pg_catalog.pg_ts_parser p\n"
4805  " WHERE p.oid = '%s'\n"
4806  "UNION ALL\n"
4807  "SELECT '%s',\n"
4808  " p.prsheadline::pg_catalog.regproc,\n"
4809  " pg_catalog.obj_description(p.prsheadline, 'pg_proc')\n"
4810  " FROM pg_catalog.pg_ts_parser p\n"
4811  " WHERE p.oid = '%s'\n"
4812  "UNION ALL\n"
4813  "SELECT '%s',\n"
4814  " p.prslextype::pg_catalog.regproc,\n"
4815  " pg_catalog.obj_description(p.prslextype, 'pg_proc')\n"
4816  " FROM pg_catalog.pg_ts_parser p\n"
4817  " WHERE p.oid = '%s';",
4818  gettext_noop("Start parse"),
4819  gettext_noop("Method"),
4820  gettext_noop("Function"),
4821  gettext_noop("Description"),
4822  oid,
4823  gettext_noop("Get next token"),
4824  oid,
4825  gettext_noop("End parse"),
4826  oid,
4827  gettext_noop("Get headline"),
4828  oid,
4829  gettext_noop("Get token types"),
4830  oid);
4831 
4832  res = PSQLexec(buf.data);
4833  termPQExpBuffer(&buf);
4834  if (!res)
4835  return false;
4836 
4837  myopt.nullPrint = NULL;
4838  initPQExpBuffer(&title);
4839  if (nspname)
4840  printfPQExpBuffer(&title, _("Text search parser \"%s.%s\""),
4841  nspname, prsname);
4842  else
4843  printfPQExpBuffer(&title, _("Text search parser \"%s\""), prsname);
4844  myopt.title = title.data;
4845  myopt.footers = NULL;
4846  myopt.topt.default_footer = false;
4847  myopt.translate_header = true;
4848  myopt.translate_columns = translate_columns;
4849  myopt.n_translate_columns = lengthof(translate_columns);
4850 
4851  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4852 
4853  PQclear(res);
4854 
4855  initPQExpBuffer(&buf);
4856 
4857  printfPQExpBuffer(&buf,
4858  "SELECT t.alias as \"%s\",\n"
4859  " t.description as \"%s\"\n"
4860  "FROM pg_catalog.ts_token_type( '%s'::pg_catalog.oid ) as t\n"
4861  "ORDER BY 1;",
4862  gettext_noop("Token name"),
4863  gettext_noop("Description"),
4864  oid);
4865 
4866  res = PSQLexec(buf.data);
4867  termPQExpBuffer(&buf);
4868  if (!res)
4869  return false;
4870 
4871  myopt.nullPrint = NULL;
4872  if (nspname)
4873  printfPQExpBuffer(&title, _("Token types for parser \"%s.%s\""),
4874  nspname, prsname);
4875  else
4876  printfPQExpBuffer(&title, _("Token types for parser \"%s\""), prsname);
4877  myopt.title = title.data;
4878  myopt.footers = NULL;
4879  myopt.topt.default_footer = true;
4880  myopt.translate_header = true;
4881  myopt.translate_columns = NULL;
4882  myopt.n_translate_columns = 0;
4883 
4884  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4885 
4886  termPQExpBuffer(&title);
4887  PQclear(res);
4888  return true;
4889 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * nullPrint
Definition: print.h:170
PsqlSettings pset
Definition: startup.c:31
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
printTableOpt topt
Definition: print.h:169
#define gettext_noop(x)
Definition: c.h:1160
FILE * queryFout
Definition: settings.h:84
#define lengthof(array)
Definition: c.h:668
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:173
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * title
Definition: print.h:171
char ** footers
Definition: print.h:172
bool default_footer
Definition: print.h:113
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:176
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3433
const bool * translate_columns
Definition: print.h:174
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ describeOperators()

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

Definition at line 783 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().

784 {
786  PGresult *res;
787  printQueryOpt myopt = pset.popt;
788 
789  initPQExpBuffer(&buf);
790 
791  /*
792  * Note: before Postgres 9.1, we did not assign comments to any built-in
793  * operators, preferring to let the comment on the underlying function
794  * suffice. The coalesce() on the obj_description() calls below supports
795  * this convention by providing a fallback lookup of a comment on the
796  * operator's function. As of 9.1 there is a policy that every built-in
797  * operator should have a comment; so the coalesce() is no longer
798  * necessary so far as built-in operators are concerned. We keep it
799  * anyway, for now, because (1) third-party modules may still be following
800  * the old convention, and (2) we'd need to do it anyway when talking to a
801  * pre-9.1 server.
802  */
803 
804  printfPQExpBuffer(&buf,
805  "SELECT n.nspname as \"%s\",\n"
806  " o.oprname AS \"%s\",\n"
807  " CASE WHEN o.oprkind='l' THEN NULL ELSE pg_catalog.format_type(o.oprleft, NULL) END AS \"%s\",\n"
808  " CASE WHEN o.oprkind='r' THEN NULL ELSE pg_catalog.format_type(o.oprright, NULL) END AS \"%s\",\n"
809  " pg_catalog.format_type(o.oprresult, NULL) AS \"%s\",\n",
810  gettext_noop("Schema"),
811  gettext_noop("Name"),
812  gettext_noop("Left arg type"),
813  gettext_noop("Right arg type"),
814  gettext_noop("Result type"));
815 
816  if (verbose)
817  appendPQExpBuffer(&buf,
818  " o.oprcode AS \"%s\",\n",
819  gettext_noop("Function"));
820 
821  appendPQExpBuffer(&buf,
822  " coalesce(pg_catalog.obj_description(o.oid, 'pg_operator'),\n"
823  " pg_catalog.obj_description(o.oprcode, 'pg_proc')) AS \"%s\"\n"
824  "FROM pg_catalog.pg_operator o\n"
825  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace\n",
826  gettext_noop("Description"));
827 
828  if (!showSystem && !pattern)
829  appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
830  " AND n.nspname <> 'information_schema'\n");
831 
832  processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern, true,
833  "n.nspname", "o.oprname", NULL,
834  "pg_catalog.pg_operator_is_visible(o.oid)");
835 
836  appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3, 4;");
837 
838  res = PSQLexec(buf.data);
839  termPQExpBuffer(&buf);
840  if (!res)
841  return false;
842 
843  myopt.nullPrint = NULL;
844  myopt.title = _("List of operators");
845  myopt.translate_header = true;
846 
847  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
848 
849  PQclear(res);
850  return true;
851 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * nullPrint
Definition: print.h:170
PsqlSettings pset
Definition: startup.c:31
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define gettext_noop(x)
Definition: c.h:1160
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:827
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:173
static int verbose
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * title
Definition: print.h:171
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3433
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ describePublications()

bool describePublications ( const char *  pattern)

Definition at line 5794 of file describe.c.

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

Referenced by exec_command_d().

5795 {
5797  int i;
5798  PGresult *res;
5799  bool has_pubtruncate;
5800  bool has_pubviaroot;
5801 
5802  if (pset.sversion < 100000)
5803  {
5804  char sverbuf[32];
5805 
5806  pg_log_error("The server (version %s) does not support publications.",
5808  sverbuf, sizeof(sverbuf)));
5809  return true;
5810  }
5811 
5812  has_pubtruncate = (pset.sversion >= 110000);
5813  has_pubviaroot = (pset.sversion >= 130000);
5814 
5815  initPQExpBuffer(&buf);
5816 
5817  printfPQExpBuffer(&buf,
5818  "SELECT oid, pubname,\n"
5819  " pg_catalog.pg_get_userbyid(pubowner) AS owner,\n"
5820  " puballtables, pubinsert, pubupdate, pubdelete");
5821  if (has_pubtruncate)
5822  appendPQExpBufferStr(&buf,
5823  ", pubtruncate");
5824  if (has_pubviaroot)
5825  appendPQExpBufferStr(&buf,
5826  ", pubviaroot");
5827  appendPQExpBufferStr(&buf,
5828  "\nFROM pg_catalog.pg_publication\n");
5829 
5830  processSQLNamePattern(pset.db, &buf, pattern, false, false,
5831  NULL, "pubname", NULL,
5832  NULL);
5833 
5834  appendPQExpBufferStr(&buf, "ORDER BY 2;");
5835 
5836  res = PSQLexec(buf.data);
5837  if (!res)
5838  {
5839  termPQExpBuffer(&buf);
5840  return false;
5841  }
5842 
5843  if (PQntuples(res) == 0)
5844  {
5845  if (!pset.quiet)
5846  {
5847  if (pattern)
5848  pg_log_error("Did not find any publication named \"%s\".",
5849  pattern);
5850  else
5851  pg_log_error("Did not find any publications.");
5852  }
5853 
5854  termPQExpBuffer(&buf);
5855  PQclear(res);
5856  return false;
5857  }
5858 
5859  for (i = 0; i < PQntuples(res); i++)
5860  {
5861  const char align = 'l';
5862  int ncols = 5;
5863  int nrows = 1;
5864  int tables = 0;
5865  PGresult *tabres;
5866  char *pubid = PQgetvalue(res, i, 0);
5867  char *pubname = PQgetvalue(res, i, 1);
5868  bool puballtables = strcmp(PQgetvalue(res, i, 3), "t") == 0;
5869  int j;
5870  PQExpBufferData title;
5871  printTableOpt myopt = pset.popt.topt;
5872  printTableContent cont;
5873 
5874  if (has_pubtruncate)
5875  ncols++;
5876  if (has_pubviaroot)
5877  ncols++;
5878 
5879  initPQExpBuffer(&title);
5880  printfPQExpBuffer(&title, _("Publication %s"), pubname);
5881  printTableInit(&cont, &myopt, title.data, ncols, nrows);
5882 
5883  printTableAddHeader(&cont, gettext_noop("Owner"), true, align);
5884  printTableAddHeader(&cont, gettext_noop("All tables"), true, align);
5885  printTableAddHeader(&cont, gettext_noop("Inserts"), true, align);
5886  printTableAddHeader(&cont, gettext_noop("Updates"), true, align);
5887  printTableAddHeader(&cont, gettext_noop("Deletes"), true, align);
5888  if (has_pubtruncate)
5889  printTableAddHeader(&cont, gettext_noop("Truncates"), true, align);
5890  if (has_pubviaroot)
5891  printTableAddHeader(&cont, gettext_noop("Via root"), true, align);
5892 
5893  printTableAddCell(&cont, PQgetvalue(res, i, 2), false, false);
5894  printTableAddCell(&cont, PQgetvalue(res, i, 3), false, false);
5895  printTableAddCell(&cont, PQgetvalue(res, i, 4), false, false);
5896  printTableAddCell(&cont, PQgetvalue(res, i, 5), false, false);
5897  printTableAddCell(&cont, PQgetvalue(res, i, 6), false, false);
5898  if (has_pubtruncate)
5899  printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false);
5900  if (has_pubviaroot)
5901  printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
5902 
5903  if (!puballtables)
5904  {
5905  printfPQExpBuffer(&buf,
5906  "SELECT n.nspname, c.relname\n"
5907  "FROM pg_catalog.pg_class c,\n"
5908  " pg_catalog.pg_namespace n,\n"
5909  " pg_catalog.pg_publication_rel pr\n"
5910  "WHERE c.relnamespace = n.oid\n"
5911  " AND c.oid = pr.prrelid\n"
5912  " AND pr.prpubid = '%s'\n"
5913  "ORDER BY 1,2", pubid);
5914 
5915  tabres = PSQLexec(buf.data);
5916  if (!tabres)
5917  {
5918  printTableCleanup(&cont);
5919  PQclear(res);
5920  termPQExpBuffer(&buf);
5921  termPQExpBuffer(&title);
5922  return false;
5923  }
5924  else
5925  tables = PQntuples(tabres);
5926 
5927  if (tables > 0)
5928  printTableAddFooter(&cont, _("Tables:"));
5929 
5930  for (j = 0; j < tables; j++)
5931  {
5932  printfPQExpBuffer(&buf, " \"%s.%s\"",
5933  PQgetvalue(tabres, j, 0),
5934  PQgetvalue(tabres, j, 1));
5935 
5936  printTableAddFooter(&cont, buf.data);
5937  }
5938  PQclear(tabres);
5939  }
5940 
5941  printTable(&cont, pset.queryFout, false, pset.logfile);
5942  printTableCleanup(&cont);
5943 
5944  termPQExpBuffer(&title);
5945  }
5946 
5947  termPQExpBuffer(&buf);
5948  PQclear(res);
5949 
5950  return true;
5951 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
PsqlSettings pset
Definition: startup.c:31
void printTableCleanup(printTableContent *const content)
Definition: print.c:3241
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3163
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
#define pg_log_error(...)
Definition: logging.h:79
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
printTableOpt topt
Definition: print.h:169
#define gettext_noop(x)
Definition: c.h:1160
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:827
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2769
void printTableAddHeader(printTableContent *const content, char *header, const bool translate, const char align)
Definition: print.c:3110
void printTableAddCell(printTableContent *const content, char *cell, const bool translate, const bool mustfree)
Definition: print.c:3150
static char * buf
Definition: pg_test_fsync.c:67
void printTable(const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3330
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition: print.c:3198
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
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:3073
int i
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:177
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ describeRoles()

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

Definition at line 3413 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().

3414 {
3416  PGresult *res;
3417  printTableContent cont;
3418  printTableOpt myopt = pset.popt.topt;
3419  int ncols = 3;
3420  int nrows = 0;
3421  int i;
3422  int conns;
3423  const char align = 'l';
3424  char **attr;
3425 
3426  myopt.default_footer = false;
3427 
3428  initPQExpBuffer(&buf);
3429 
3430  if (pset.sversion >= 80100)
3431  {
3432  printfPQExpBuffer(&buf,
3433  "SELECT r.rolname, r.rolsuper, r.rolinherit,\n"
3434  " r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,\n"
3435  " r.rolconnlimit, r.rolvaliduntil,\n"
3436  " ARRAY(SELECT b.rolname\n"
3437  " FROM pg_catalog.pg_auth_members m\n"
3438  " JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)\n"
3439  " WHERE m.member = r.oid) as memberof");
3440 
3441  if (verbose && pset.sversion >= 80200)
3442  {
3443  appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
3444  ncols++;
3445  }
3446  if (pset.sversion >= 90100)
3447  {
3448  appendPQExpBufferStr(&buf, "\n, r.rolreplication");
3449  }
3450 
3451  if (pset.sversion >= 90500)
3452  {
3453  appendPQExpBufferStr(&buf, "\n, r.rolbypassrls");
3454  }
3455 
3456  appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_roles r\n");
3457 
3458  if (!showSystem && !pattern)
3459  appendPQExpBufferStr(&buf, "WHERE r.rolname !~ '^pg_'\n");
3460 
3461  processSQLNamePattern(pset.db, &buf, pattern, false, false,
3462  NULL, "r.rolname", NULL, NULL);
3463  }
3464  else
3465  {
3466  printfPQExpBuffer(&buf,
3467  "SELECT u.usename AS rolname,\n"
3468  " u.usesuper AS rolsuper,\n"
3469  " true AS rolinherit, false AS rolcreaterole,\n"
3470  " u.usecreatedb AS rolcreatedb, true AS rolcanlogin,\n"
3471  " -1 AS rolconnlimit,"
3472  " u.valuntil as rolvaliduntil,\n"
3473  " ARRAY(SELECT g.groname FROM pg_catalog.pg_group g WHERE u.usesysid = ANY(g.grolist)) as memberof"
3474  "\nFROM pg_catalog.pg_user u\n");
3475 
3476  processSQLNamePattern(pset.db, &buf, pattern, false, false,
3477  NULL, "u.usename", NULL, NULL);
3478  }
3479 
3480  appendPQExpBufferStr(&buf, "ORDER BY 1;");
3481 
3482  res = PSQLexec(buf.data);
3483  if (!res)
3484  return false;
3485 
3486  nrows = PQntuples(res);
3487  attr = pg_malloc0((nrows + 1) * sizeof(*attr));
3488 
3489  printTableInit(&cont, &myopt, _("List of roles"), ncols, nrows);
3490 
3491  printTableAddHeader(&cont, gettext_noop("Role name"), true, align);
3492  printTableAddHeader(&cont, gettext_noop("Attributes"), true, align);
3493  printTableAddHeader(&cont, gettext_noop("Member of"), true, align);
3494 
3495  if (verbose && pset.sversion >= 80200)
3496  printTableAddHeader(&cont, gettext_noop("Description"), true, align);
3497 
3498  for (i = 0; i < nrows; i++)
3499  {
3500  printTableAddCell(&cont, PQgetvalue(res, i, 0), false, false);
3501 
3502  resetPQExpBuffer(&buf);
3503  if (strcmp(PQgetvalue(res, i, 1), "t") == 0)
3504  add_role_attribute(&buf, _("Superuser"));
3505 
3506  if (strcmp(PQgetvalue(res, i, 2), "t") != 0)
3507  add_role_attribute(&buf, _("No inheritance"));
3508 
3509  if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
3510  add_role_attribute(&buf, _("Create role"));
3511 
3512  if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
3513  add_role_attribute(&buf, _("Create DB"));
3514 
3515  if (strcmp(PQgetvalue(res, i, 5), "t") != 0)
3516  add_role_attribute(&buf, _("Cannot login"));
3517 
3518  if (pset.sversion >= 90100)
3519  if (strcmp(PQgetvalue(res, i, (verbose ? 10 : 9)), "t") == 0)
3520  add_role_attribute(&buf, _("Replication"));
3521 
3522  if (pset.sversion >= 90500)
3523  if (strcmp(PQgetvalue(res, i, (verbose ? 11 : 10)), "t") == 0)
3524  add_role_attribute(&buf, _("Bypass RLS"));
3525 
3526  conns = atoi(PQgetvalue(res, i, 6));
3527  if (conns >= 0)
3528  {
3529  if (buf.len > 0)
3530  appendPQExpBufferChar(&buf, '\n');
3531 
3532  if (conns == 0)
3533  appendPQExpBufferStr(&buf, _("No connections"));
3534  else
3535  appendPQExpBuffer(&buf, ngettext("%d connection",
3536  "%d connections",
3537  conns),
3538  conns);
3539  }
3540 
3541  if (strcmp(PQgetvalue(res, i, 7), "") != 0)
3542  {
3543  if (buf.len > 0)
3544  appendPQExpBufferChar(&buf, '\n');
3545  appendPQExpBufferStr(&buf, _("Password valid until "));
3546  appendPQExpBufferStr(&buf, PQgetvalue(res, i, 7));
3547  }
3548 
3549  attr[i] = pg_strdup(buf.data);
3550 
3551  printTableAddCell(&cont, attr[i], false, false);
3552 
3553  printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
3554 
3555  if (verbose && pset.sversion >= 80200)
3556  printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
3557  }
3558  termPQExpBuffer(&buf);
3559 
3560  printTable(&cont, pset.queryFout, false, pset.logfile);
3561  printTableCleanup(&cont);
3562 
3563  for (i = 0; i < nrows; i++)
3564  free(attr[i]);
3565  free(attr);
3566 
3567  PQclear(res);
3568  return true;
3569 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
PsqlSettings pset
Definition: startup.c:31
void printTableCleanup(printTableContent *const content)
Definition: print.c:3241
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3163
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
printTableOpt topt
Definition: print.h:169
#define gettext_noop(x)
Definition: c.h:1160
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:827
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2769
static void add_role_attribute(PQExpBuffer buf, const char *const str)
Definition: describe.c:3572
void printTableAddHeader(printTableContent *const content, char *header, const bool translate, const char align)
Definition: print.c:3110
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:3150
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
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:3330
static int verbose
#define ngettext(s, p, n)
Definition: c.h:1146
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
#define free(a)
Definition: header.h:65
bool default_footer
Definition: print.h:113
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:3073
int i
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ describeSubscriptions()

bool describeSubscriptions ( const char *  pattern,
bool  verbose 
)

Definition at line 5960 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, pg_log_error, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by exec_command_d().

5961 {
5963  PGresult *res;
5964  printQueryOpt myopt = pset.popt;
5965  static const bool translate_columns[] = {false, false, false, false,
5966  false, false};
5967 
5968  if (pset.sversion < 100000)
5969  {
5970  char sverbuf[32];
5971 
5972  pg_log_error("The server (version %s) does not support subscriptions.",
5974  sverbuf, sizeof(sverbuf)));
5975  return true;
5976  }
5977 
5978  initPQExpBuffer(&buf);
5979 
5980  printfPQExpBuffer(&buf,
5981  "SELECT subname AS \"%s\"\n"
5982  ", pg_catalog.pg_get_userbyid(subowner) AS \"%s\"\n"
5983  ", subenabled AS \"%s\"\n"
5984  ", subpublications AS \"%s\"\n",
5985  gettext_noop("Name"),
5986  gettext_noop("Owner"),
5987  gettext_noop("Enabled"),
5988  gettext_noop("Publication"));
5989 
5990  if (verbose)
5991  {
5992  appendPQExpBuffer(&buf,
5993  ", subsynccommit AS \"%s\"\n"
5994  ", subconninfo AS \"%s\"\n",
5995  gettext_noop("Synchronous commit"),
5996  gettext_noop("Conninfo"));
5997  }
5998 
5999  /* Only display subscriptions in current database. */
6000  appendPQExpBufferStr(&buf,
6001  "FROM pg_catalog.pg_subscription\n"
6002  "WHERE subdbid = (SELECT oid\n"
6003  " FROM pg_catalog.pg_database\n"
6004  " WHERE datname = pg_catalog.current_database())");
6005 
6006  processSQLNamePattern(pset.db, &buf, pattern, true, false,
6007  NULL, "subname", NULL,
6008  NULL);
6009 
6010  appendPQExpBufferStr(&buf, "ORDER BY 1;");
6011 
6012  res = PSQLexec(buf.data);
6013  termPQExpBuffer(&buf);
6014  if (!res)
6015  return false;
6016 
6017  myopt.nullPrint = NULL;
6018  myopt.title = _("List of subscriptions");
6019  myopt.translate_header = true;
6020  myopt.translate_columns = translate_columns;
6021  myopt.n_translate_columns = lengthof(translate_columns);
6022 
6023  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6024 
6025  PQclear(res);
6026  return true;
6027 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * nullPrint
Definition: print.h:170
PsqlSettings pset
Definition: startup.c:31
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
#define pg_log_error(...)
Definition: logging.h:79
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define gettext_noop(x)
Definition: c.h:1160
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:827
#define lengthof(array)
Definition: c.h:668
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:173
static int verbose
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * title
Definition: print.h:171
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:176
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3433
const bool * translate_columns
Definition: print.h:174
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:177
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ describeTableDetails()

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

Definition at line 1367 of file describe.c.

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

Referenced by exec_command_d().

1368 {
1370  PGresult *res;
1371  int i;
1372 
1373  initPQExpBuffer(&buf);
1374 
1375  printfPQExpBuffer(&buf,
1376  "SELECT c.oid,\n"
1377  " n.nspname,\n"
1378  " c.relname\n"
1379  "FROM pg_catalog.pg_class c\n"
1380  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n");
1381 
1382  if (!showSystem && !pattern)
1383  appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
1384  " AND n.nspname <> 'information_schema'\n");
1385 
1386  processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern, false,
1387  "n.nspname", "c.relname", NULL,
1388  "pg_catalog.pg_table_is_visible(c.oid)");
1389 
1390  appendPQExpBufferStr(&buf, "ORDER BY 2, 3;");
1391 
1392  res = PSQLexec(buf.data);
1393  termPQExpBuffer(&buf);
1394  if (!res)
1395  return false;
1396 
1397  if (PQntuples(res) == 0)
1398  {
1399  if (!pset.quiet)
1400  {
1401  if (pattern)
1402  pg_log_error("Did not find any relation named \"%s\".",
1403  pattern);
1404  else
1405  pg_log_error("Did not find any relations.");
1406  }
1407  PQclear(res);
1408  return false;
1409  }
1410 
1411  for (i = 0; i < PQntuples(res); i++)
1412  {
1413  const char *oid;
1414  const char *nspname;
1415  const char *relname;
1416 
1417  oid = PQgetvalue(res, i, 0);
1418  nspname = PQgetvalue(res, i, 1);
1419  relname = PQgetvalue(res, i, 2);
1420 
1421  if (!describeOneTableDetails(nspname, relname, oid, verbose))
1422  {
1423  PQclear(res);
1424  return false;
1425  }
1426  if (cancel_pressed)
1427  {
1428  PQclear(res);
1429  return false;
1430  }
1431  }
1432 
1433  PQclear(res);
1434  return true;
1435 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
PsqlSettings pset
Definition: startup.c:31
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3163
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
#define pg_log_error(...)
Definition: logging.h:79
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
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:827
NameData relname
Definition: pg_class.h:38
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2769
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:1445
static int verbose
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
void PQclear(PGresult *res)
Definition: fe-exec.c:694
int i
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ describeTablespaces()

bool describeTablespaces ( const char *  pattern,
bool  verbose 
)

Definition at line 219 of file describe.c.

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, _psqlSettings::db, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, printQueryOpt::nullPrint, pg_log_info, _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().

220 {
222  PGresult *res;
223  printQueryOpt myopt = pset.popt;
224 
225  if (pset.sversion < 80000)
226  {
227  char sverbuf[32];
228 
229  pg_log_info("The server (version %s) does not support tablespaces.",
231  sverbuf, sizeof(sverbuf)));
232  return true;
233  }
234 
235  initPQExpBuffer(&buf);
236 
237  if (pset.sversion >= 90200)
238  printfPQExpBuffer(&buf,
239  "SELECT spcname AS \"%s\",\n"
240  " pg_catalog.pg_get_userbyid(spcowner) AS \"%s\",\n"
241  " pg_catalog.pg_tablespace_location(oid) AS \"%s\"",
242  gettext_noop("Name"),
243  gettext_noop("Owner"),
244  gettext_noop("Location"));
245  else
246  printfPQExpBuffer(&buf,
247  "SELECT spcname AS \"%s\",\n"
248  " pg_catalog.pg_get_userbyid(spcowner) AS \"%s\",\n"
249  " spclocation AS \"%s\"",
250  gettext_noop("Name"),
251  gettext_noop("Owner"),
252  gettext_noop("Location"));
253 
254  if (verbose)
255  {
256  appendPQExpBufferStr(&buf, ",\n ");
257  printACLColumn(&buf, "spcacl");
258  }
259 
260  if (verbose && pset.sversion >= 90000)
261  appendPQExpBuffer(&buf,
262  ",\n spcoptions AS \"%s\"",
263  gettext_noop("Options"));
264 
265  if (verbose && pset.sversion >= 90200)
266  appendPQExpBuffer(&buf,
267  ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"",
268  gettext_noop("Size"));
269 
270  if (verbose && pset.sversion >= 80200)
271  appendPQExpBuffer(&buf,
272  ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"",
273  gettext_noop("Description"));
274 
276  "\nFROM pg_catalog.pg_tablespace\n");
277 
278  processSQLNamePattern(pset.db, &buf, pattern, false, false,
279  NULL, "spcname", NULL,
280  NULL);
281 
282  appendPQExpBufferStr(&buf, "ORDER BY 1;");
283 
284  res = PSQLexec(buf.data);
285  termPQExpBuffer(&buf);
286  if (!res)
287  return false;
288 
289  myopt.nullPrint = NULL;
290  myopt.title = _("List of tablespaces");
291  myopt.translate_header = true;
292 
293  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
294 
295  PQclear(res);
296  return true;
297 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * nullPrint
Definition: print.h:170
PsqlSettings pset
Definition: startup.c:31
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define gettext_noop(x)
Definition: c.h:1160
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:827
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:173
static int verbose
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * title
Definition: print.h:171
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3433
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition: describe.c:6037
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
#define pg_log_info(...)
Definition: logging.h:87
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:177
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ describeTypes()

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

Definition at line 667 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().

668 {
670  PGresult *res;
671  printQueryOpt myopt = pset.popt;
672 
673  initPQExpBuffer(&buf);
674 
675  printfPQExpBuffer(&buf,
676  "SELECT n.nspname as \"%s\",\n"
677  " pg_catalog.format_type(t.oid, NULL) AS \"%s\",\n",
678  gettext_noop("Schema"),
679  gettext_noop("Name"));
680  if (verbose)
681  appendPQExpBuffer(&buf,
682  " t.typname AS \"%s\",\n"
683  " CASE WHEN t.typrelid != 0\n"
684  " THEN CAST('tuple' AS pg_catalog.text)\n"
685  " WHEN t.typlen < 0\n"
686  " THEN CAST('var' AS pg_catalog.text)\n"
687  " ELSE CAST(t.typlen AS pg_catalog.text)\n"
688  " END AS \"%s\",\n",
689  gettext_noop("Internal name"),
690  gettext_noop("Size"));
691  if (verbose && pset.sversion >= 80300)
692  {
694  " pg_catalog.array_to_string(\n"
695  " ARRAY(\n"
696  " SELECT e.enumlabel\n"
697  " FROM pg_catalog.pg_enum e\n"
698  " WHERE e.enumtypid = t.oid\n");
699 
700  if (pset.sversion >= 90100)
702  " ORDER BY e.enumsortorder\n");
703  else
705  " ORDER BY e.oid\n");
706 
707  appendPQExpBuffer(&buf,
708  " ),\n"
709  " E'\\n'\n"
710  " ) AS \"%s\",\n",
711  gettext_noop("Elements"));
712  }
713  if (verbose)
714  {
715  appendPQExpBuffer(&buf,
716  " pg_catalog.pg_get_userbyid(t.typowner) AS \"%s\",\n",
717  gettext_noop("Owner"));
718  }
719  if (verbose && pset.sversion >= 90200)
720  {
721  printACLColumn(&buf, "t.typacl");
722  appendPQExpBufferStr(&buf, ",\n ");
723  }
724 
725  appendPQExpBuffer(&buf,
726  " pg_catalog.obj_description(t.oid, 'pg_type') as \"%s\"\n",
727  gettext_noop("Description"));
728 
729  appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_type t\n"
730  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
731 
732  /*
733  * do not include complex types (typrelid!=0) unless they are standalone
734  * composite types
735  */
736  appendPQExpBufferStr(&buf, "WHERE (t.typrelid = 0 ");
737  appendPQExpBufferStr(&buf, "OR (SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
738  " FROM pg_catalog.pg_class c "
739  "WHERE c.oid = t.typrelid))\n");
740 
741  /*
742  * do not include array types (before 8.3 we have to use the assumption
743  * that their names start with underscore)
744  */
745  if (pset.sversion >= 80300)
746  appendPQExpBufferStr(&buf, " AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n");
747  else
748  appendPQExpBufferStr(&buf, " AND t.typname !~ '^_'\n");
749 
750  if (!showSystem && !pattern)
751  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
752  " AND n.nspname <> 'information_schema'\n");
753 
754  /* Match name pattern against either internal or external name */
755  processSQLNamePattern(pset.db, &buf, pattern, true, false,
756  "n.nspname", "t.typname",
757  "pg_catalog.format_type(t.oid, NULL)",
758  "pg_catalog.pg_type_is_visible(t.oid)");
759 
760  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
761 
762  res = PSQLexec(buf.data);
763  termPQExpBuffer(&buf);
764  if (!res)
765  return false;
766 
767  myopt.nullPrint = NULL;
768  myopt.title = _("List of data types");
769  myopt.translate_header = true;
770 
771  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
772 
773  PQclear(res);
774  return true;
775 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * nullPrint
Definition: print.h:170
PsqlSettings pset
Definition: startup.c:31
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define gettext_noop(x)
Definition: c.h:1160
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:827
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:173
static int verbose
#define CppAsString2(x)
Definition: c.h:222
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * title
Definition: print.h:171
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3433
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition: describe.c:6037
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ listAllDbs()

bool listAllDbs ( const char *  pattern,
bool  verbose 
)

Definition at line 860 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().

861 {
862  PGresult *res;
864  printQueryOpt myopt = pset.popt;
865 
866  initPQExpBuffer(&buf);
867 
868  printfPQExpBuffer(&buf,
869  "SELECT d.datname as \"%s\",\n"
870  " pg_catalog.pg_get_userbyid(d.datdba) as \"%s\",\n"
871  " pg_catalog.pg_encoding_to_char(d.encoding) as \"%s\",\n",
872  gettext_noop("Name"),
873  gettext_noop("Owner"),
874  gettext_noop("Encoding"));
875  if (pset.sversion >= 80400)
876  appendPQExpBuffer(&buf,
877  " d.datcollate as \"%s\",\n"
878  " d.datctype as \"%s\",\n",
879  gettext_noop("Collate"),
880  gettext_noop("Ctype"));
881  appendPQExpBufferStr(&buf, " ");
882  printACLColumn(&buf, "d.datacl");
883  if (verbose && pset.sversion >= 80200)
884  appendPQExpBuffer(&buf,
885  ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n"
886  " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n"
887  " ELSE 'No Access'\n"
888  " END as \"%s\"",
889  gettext_noop("Size"));
890  if (verbose && pset.sversion >= 80000)
891  appendPQExpBuffer(&buf,
892  ",\n t.spcname as \"%s\"",
893  gettext_noop("Tablespace"));
894  if (verbose && pset.sversion >= 80200)
895  appendPQExpBuffer(&buf,
896  ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"",
897  gettext_noop("Description"));
899  "\nFROM pg_catalog.pg_database d\n");
900  if (verbose && pset.sversion >= 80000)
902  " JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
903 
904  if (pattern)
905  processSQLNamePattern(pset.db, &buf, pattern, false, false,
906  NULL, "d.datname", NULL, NULL);
907 
908  appendPQExpBufferStr(&buf, "ORDER BY 1;");
909  res = PSQLexec(buf.data);
910  termPQExpBuffer(&buf);
911  if (!res)
912  return false;
913 
914  myopt.nullPrint = NULL;
915  myopt.title = _("List of databases");
916  myopt.translate_header = true;
917 
918  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
919 
920  PQclear(res);
921  return true;
922 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * nullPrint
Definition: print.h:170
PsqlSettings pset
Definition: startup.c:31
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define gettext_noop(x)
Definition: c.h:1160
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:827
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:173
static int verbose
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * title
Definition: print.h:171
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3433
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition: describe.c:6037
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ listCasts()

bool listCasts ( const char *  pattern,
bool  verbose 
)

Definition at line 4376 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, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by exec_command_d().

4377 {
4379  PGresult *res;
4380  printQueryOpt myopt = pset.popt;
4381  static const bool translate_columns[] = {false, false, false, true, false};
4382 
4383  initPQExpBuffer(&buf);
4384 
4385  printfPQExpBuffer(&buf,
4386  "SELECT pg_catalog.format_type(castsource, NULL) AS \"%s\",\n"
4387  " pg_catalog.format_type(casttarget, NULL) AS \"%s\",\n",
4388  gettext_noop("Source type"),
4389  gettext_noop("Target type"));
4390 
4391  /*
4392  * We don't attempt to localize '(binary coercible)' or '(with inout)',
4393  * because there's too much risk of gettext translating a function name
4394  * that happens to match some string in the PO database.
4395  */
4396  if (pset.sversion >= 80400)
4397  appendPQExpBuffer(&buf,
4398  " CASE WHEN c.castmethod = '%c' THEN '(binary coercible)'\n"
4399  " WHEN c.castmethod = '%c' THEN '(with inout)'\n"
4400  " ELSE p.proname\n"
4401  " END AS \"%s\",\n",
4402  COERCION_METHOD_BINARY,
4403  COERCION_METHOD_INOUT,
4404  gettext_noop("Function"));
4405  else
4406  appendPQExpBuffer(&buf,
4407  " CASE WHEN c.castfunc = 0 THEN '(binary coercible)'\n"
4408  " ELSE p.proname\n"
4409  " END AS \"%s\",\n",
4410  gettext_noop("Function"));
4411 
4412  appendPQExpBuffer(&buf,
4413  " CASE WHEN c.castcontext = '%c' THEN '%s'\n"
4414  " WHEN c.castcontext = '%c' THEN '%s'\n"
4415  " ELSE '%s'\n"
4416  " END AS \"%s\"",
4417  COERCION_CODE_EXPLICIT,
4418  gettext_noop("no"),
4419  COERCION_CODE_ASSIGNMENT,
4420  gettext_noop("in assignment"),
4421  gettext_noop("yes"),
4422  gettext_noop("Implicit?"));
4423 
4424  if (verbose)
4425  appendPQExpBuffer(&buf,
4426  ",\n d.description AS \"%s\"",
4427  gettext_noop("Description"));
4428 
4429  /*
4430  * We need a left join to pg_proc for binary casts; the others are just
4431  * paranoia.
4432  */
4433  appendPQExpBufferStr(&buf,
4434  "\nFROM pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p\n"
4435  " ON c.castfunc = p.oid\n"
4436  " LEFT JOIN pg_catalog.pg_type ts\n"
4437  " ON c.castsource = ts.oid\n"
4438  " LEFT JOIN pg_catalog.pg_namespace ns\n"
4439  " ON ns.oid = ts.typnamespace\n"
4440  " LEFT JOIN pg_catalog.pg_type tt\n"
4441  " ON c.casttarget = tt.oid\n"
4442  " LEFT JOIN pg_catalog.pg_namespace nt\n"
4443  " ON nt.oid = tt.typnamespace\n");
4444 
4445  if (verbose)
4446  appendPQExpBufferStr(&buf,
4447  " LEFT JOIN pg_catalog.pg_description d\n"
4448  " ON d.classoid = c.tableoid AND d.objoid = "
4449  "c.oid AND d.objsubid = 0\n");
4450 
4451  appendPQExpBufferStr(&buf, "WHERE ( (true");
4452 
4453  /*
4454  * Match name pattern against either internal or external name of either
4455  * castsource or casttarget
4456  */
4457  processSQLNamePattern(pset.db, &buf, pattern, true, false,
4458  "ns.nspname", "ts.typname",
4459  "pg_catalog.format_type(ts.oid, NULL)",
4460  "pg_catalog.pg_type_is_visible(ts.oid)");
4461 
4462  appendPQExpBufferStr(&buf, ") OR (true");
4463 
4464  processSQLNamePattern(pset.db, &buf, pattern, true, false,
4465  "nt.nspname", "tt.typname",
4466  "pg_catalog.format_type(tt.oid, NULL)",
4467  "pg_catalog.pg_type_is_visible(tt.oid)");
4468 
4469  appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;");
4470 
4471  res = PSQLexec(buf.data);
4472  termPQExpBuffer(&buf);
4473  if (!res)
4474  return false;
4475 
4476  myopt.nullPrint = NULL;
4477  myopt.title = _("List of casts");
4478  myopt.translate_header = true;
4479  myopt.translate_columns = translate_columns;
4480  myopt.n_translate_columns = lengthof(translate_columns);
4481 
4482  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4483 
4484  PQclear(res);
4485  return true;
4486 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * nullPrint
Definition: print.h:170
PsqlSettings pset
Definition: startup.c:31
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define gettext_noop(x)
Definition: c.h:1160
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:827
#define lengthof(array)
Definition: c.h:668
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:173
static int verbose
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * title
Definition: print.h:171
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:176
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3433
const bool * translate_columns
Definition: print.h:174
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ listCollations()

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

Definition at line 4494 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, pg_log_error, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, and printQueryOpt::translate_header.

Referenced by exec_command_d().

4495 {
4497  PGresult *res;
4498  printQueryOpt myopt = pset.popt;
4499  static const bool translate_columns[] = {false, false, false, false, false, true, false};
4500 
4501  if (pset.sversion < 90100)
4502  {
4503  char sverbuf[32];
4504 
4505  pg_log_error("The server (version %s) does not support collations.",
4507  sverbuf, sizeof(sverbuf)));
4508  return true;
4509  }
4510 
4511  initPQExpBuffer(&buf);
4512 
4513  printfPQExpBuffer(&buf,
4514  "SELECT n.nspname AS \"%s\",\n"
4515  " c.collname AS \"%s\",\n"
4516  " c.collcollate AS \"%s\",\n"
4517  " c.collctype AS \"%s\"",
4518  gettext_noop("Schema"),
4519  gettext_noop("Name"),
4520  gettext_noop("Collate"),
4521  gettext_noop("Ctype"));
4522 
4523  if (pset.sversion >= 100000)
4524  appendPQExpBuffer(&buf,
4525  ",\n CASE c.collprovider WHEN 'd' THEN 'default' WHEN 'c' THEN 'libc' WHEN 'i' THEN 'icu' END AS \"%s\"",
4526  gettext_noop("Provider"));
4527  else
4528  appendPQExpBuffer(&buf,
4529  ",\n 'libc' AS \"%s\"",
4530  gettext_noop("Provider"));
4531 
4532  if (pset.sversion >= 120000)
4533  appendPQExpBuffer(&buf,
4534  ",\n CASE WHEN c.collisdeterministic THEN '%s' ELSE '%s' END AS \"%s\"",
4535  gettext_noop("yes"), gettext_noop("no"),
4536  gettext_noop("Deterministic?"));
4537  else
4538  appendPQExpBuffer(&buf,
4539  ",\n '%s' AS \"%s\"",
4540  gettext_noop("yes"),
4541  gettext_noop("Deterministic?"));
4542 
4543  if (verbose)
4544  appendPQExpBuffer(&buf,
4545  ",\n pg_catalog.obj_description(c.oid, 'pg_collation') AS \"%s\"",
4546  gettext_noop("Description"));
4547 
4548  appendPQExpBufferStr(&buf,
4549  "\nFROM pg_catalog.pg_collation c, pg_catalog.pg_namespace n\n"
4550  "WHERE n.oid = c.collnamespace\n");
4551 
4552  if (!showSystem && !pattern)
4553  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4554  " AND n.nspname <> 'information_schema'\n");
4555 
4556  /*
4557  * Hide collations that aren't usable in the current database's encoding.
4558  * If you think to change this, note that pg_collation_is_visible rejects
4559  * unusable collations, so you will need to hack name pattern processing
4560  * somehow to avoid inconsistent behavior.
4561  */
4562  appendPQExpBufferStr(&buf, " AND c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))\n");
4563 
4564  processSQLNamePattern(pset.db, &buf, pattern, true, false,
4565  "n.nspname", "c.collname", NULL,
4566  "pg_catalog.pg_collation_is_visible(c.oid)");
4567 
4568  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4569 
4570  res = PSQLexec(buf.data);
4571  termPQExpBuffer(&buf);
4572  if (!res)
4573  return false;
4574 
4575  myopt.nullPrint = NULL;
4576  myopt.title = _("List of collations");
4577  myopt.translate_header = true;
4578  myopt.translate_columns = translate_columns;
4579  myopt.n_translate_columns = lengthof(translate_columns);
4580 
4581  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4582 
4583  PQclear(res);
4584  return true;
4585 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * nullPrint
Definition: print.h:170
PsqlSettings pset
Definition: startup.c:31
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
#define pg_log_error(...)
Definition: logging.h:79
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define gettext_noop(x)
Definition: c.h:1160
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:827
#define lengthof(array)
Definition: c.h:668
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:173
static int verbose
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * title
Definition: print.h:171
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:176
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3433
const bool * translate_columns
Definition: print.h:174
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:177
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ listConversions()

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

Definition at line 4234 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().

4235 {
4237  PGresult *res;
4238  printQueryOpt myopt = pset.popt;
4239  static const bool translate_columns[] =
4240  {false, false, false, false, true, false};
4241 
4242  initPQExpBuffer(&buf);
4243 
4244  printfPQExpBuffer(&buf,
4245  "SELECT n.nspname AS \"%s\",\n"
4246  " c.conname AS \"%s\",\n"
4247  " pg_catalog.pg_encoding_to_char(c.conforencoding) AS \"%s\",\n"
4248  " pg_catalog.pg_encoding_to_char(c.contoencoding) AS \"%s\",\n"
4249  " CASE WHEN c.condefault THEN '%s'\n"
4250  " ELSE '%s' END AS \"%s\"",
4251  gettext_noop("Schema"),
4252  gettext_noop("Name"),
4253  gettext_noop("Source"),
4254  gettext_noop("Destination"),
4255  gettext_noop("yes"), gettext_noop("no"),
4256  gettext_noop("Default?"));
4257 
4258  if (verbose)
4259  appendPQExpBuffer(&buf,
4260  ",\n d.description AS \"%s\"",
4261  gettext_noop("Description"));
4262 
4263  appendPQExpBufferStr(&buf,
4264  "\nFROM pg_catalog.pg_conversion c\n"
4265  " JOIN pg_catalog.pg_namespace n "
4266  "ON n.oid = c.connamespace\n");
4267 
4268  if (verbose)
4269  appendPQExpBufferStr(&buf,
4270  "LEFT JOIN pg_catalog.pg_description d "
4271  "ON d.classoid = c.tableoid\n"
4272  " AND d.objoid = c.oid "
4273  "AND d.objsubid = 0\n");
4274 
4275  appendPQExpBufferStr(&buf, "WHERE true\n");
4276 
4277  if (!showSystem && !pattern)
4278  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4279  " AND n.nspname <> 'information_schema'\n");
4280 
4281  processSQLNamePattern(pset.db, &buf, pattern, true, false,
4282  "n.nspname", "c.conname", NULL,
4283  "pg_catalog.pg_conversion_is_visible(c.oid)");
4284 
4285  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4286 
4287  res = PSQLexec(buf.data);
4288  termPQExpBuffer(&buf);
4289  if (!res)
4290  return false;
4291 
4292  myopt.nullPrint = NULL;
4293  myopt.title = _("List of conversions");
4294  myopt.translate_header = true;
4295  myopt.translate_columns = translate_columns;
4296  myopt.n_translate_columns = lengthof(translate_columns);
4297 
4298  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4299 
4300  PQclear(res);
4301  return true;
4302 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * nullPrint
Definition: print.h:170
PsqlSettings pset
Definition: startup.c:31
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define gettext_noop(x)
Definition: c.h:1160
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:827
#define lengthof(array)
Definition: c.h:668
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:173
static int verbose
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * title
Definition: print.h:171
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:176
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3433
const bool * translate_columns
Definition: print.h:174
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ listDbRoleSettings()

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

Definition at line 3584 of file describe.c.

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

Referenced by exec_command_d().

3585 {
3587  PGresult *res;
3588  printQueryOpt myopt = pset.popt;
3589  bool havewhere;
3590 
3591  if (pset.sversion < 90000)
3592  {
3593  char sverbuf[32];
3594 
3595  pg_log_error("The server (version %s) does not support per-database role settings.",
3597  sverbuf, sizeof(sverbuf)));
3598  return true;
3599  }
3600 
3601  initPQExpBuffer(&buf);
3602 
3603  printfPQExpBuffer(&buf, "SELECT rolname AS \"%s\", datname AS \"%s\",\n"
3604  "pg_catalog.array_to_string(setconfig, E'\\n') AS \"%s\"\n"
3605  "FROM pg_catalog.pg_db_role_setting s\n"
3606  "LEFT JOIN pg_catalog.pg_database d ON d.oid = setdatabase\n"
3607  "LEFT JOIN pg_catalog.pg_roles r ON r.oid = setrole\n",
3608  gettext_noop("Role"),
3609  gettext_noop("Database"),
3610  gettext_noop("Settings"));
3611  havewhere = processSQLNamePattern(pset.db, &buf, pattern, false, false,
3612  NULL, "r.rolname", NULL, NULL);
3613  processSQLNamePattern(pset.db, &buf, pattern2, havewhere, false,
3614  NULL, "d.datname", NULL, NULL);
3615  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
3616 
3617  res = PSQLexec(buf.data);
3618  termPQExpBuffer(&buf);
3619  if (!res)
3620  return false;
3621 
3622  /*
3623  * Most functions in this file are content to print an empty table when
3624  * there are no matching objects. We intentionally deviate from that
3625  * here, but only in !quiet mode, because of the possibility that the user
3626  * is confused about what the two pattern arguments mean.
3627  */
3628  if (PQntuples(res) == 0 && !pset.quiet)
3629  {
3630  if (pattern && pattern2)
3631  pg_log_error("Did not find any settings for role \"%s\" and database \"%s\".",
3632  pattern, pattern2);
3633  else if (pattern)
3634  pg_log_error("Did not find any settings for role \"%s\".",
3635  pattern);
3636  else
3637  pg_log_error("Did not find any settings.");
3638  }
3639  else
3640  {
3641  myopt.nullPrint = NULL;
3642  myopt.title = _("List of settings");
3643  myopt.translate_header = true;
3644 
3645  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
3646  }
3647 
3648  PQclear(res);
3649  return true;
3650 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * nullPrint
Definition: print.h:170
PsqlSettings pset
Definition: startup.c:31
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
#define pg_log_error(...)
Definition: logging.h:79
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define gettext_noop(x)
Definition: c.h:1160
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:827
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2769
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:173
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * title
Definition: print.h:171
printQueryOpt popt
Definition: settings.h:91
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3433
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:177
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ listDefaultACLs()

bool listDefaultACLs ( const char *  pattern)

Definition at line 1090 of file describe.c.

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

Referenced by exec_command_d().

1091 {
1093  PGresult *res;
1094  printQueryOpt myopt = pset.popt;
1095  static const bool translate_columns[] = {false, false, true, false};
1096 
1097  if (pset.sversion < 90000)
1098  {
1099  char sverbuf[32];
1100 
1101  pg_log_error("The server (version %s) does not support altering default privileges.",
1103  sverbuf, sizeof(sverbuf)));
1104  return true;
1105  }
1106 
1107  initPQExpBuffer(&buf);
1108 
1109  printfPQExpBuffer(&buf,
1110  "SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS \"%s\",\n"
1111  " n.nspname AS \"%s\",\n"
1112  " 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"
1113  " ",
1114  gettext_noop("Owner"),
1115  gettext_noop("Schema"),
1116  DEFACLOBJ_RELATION,
1117  gettext_noop("table"),
1118  DEFACLOBJ_SEQUENCE,
1119  gettext_noop("sequence"),
1120  DEFACLOBJ_FUNCTION,
1121  gettext_noop("function"),
1122  DEFACLOBJ_TYPE,
1123  gettext_noop("type"),
1124  DEFACLOBJ_NAMESPACE,
1125  gettext_noop("schema"),
1126  gettext_noop("Type"));
1127 
1128  printACLColumn(&buf, "d.defaclacl");
1129 
1130  appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_default_acl d\n"
1131  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.defaclnamespace\n");
1132 
1133  processSQLNamePattern(pset.db, &buf, pattern, false, false,
1134  NULL,
1135  "n.nspname",
1136  "pg_catalog.pg_get_userbyid(d.defaclrole)",
1137  NULL);
1138 
1139  appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
1140 
1141  res = PSQLexec(buf.data);
1142  if (!res)
1143  {
1144  termPQExpBuffer(&buf);
1145  return false;
1146  }
1147 
1148  myopt.nullPrint = NULL;
1149  printfPQExpBuffer(&buf, _("Default access privileges"));
1150  myopt.title = buf.data;
1151  myopt.translate_header = true;
1152  myopt.translate_columns = translate_columns;
1153  myopt.n_translate_columns = lengthof(translate_columns);
1154 
1155  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1156 
1157  termPQExpBuffer(&buf);
1158  PQclear(res);
1159  return true;
1160 }
PGconn * db
Definition: settings.h:82
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * nullPrint
Definition: print.h:170
PsqlSettings pset
Definition: startup.c:31
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
#define pg_log_error(...)
Definition: logging.h:79
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define gettext_noop(x)
Definition: c.h:1160
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:827
#define lengthof(array)
Definition: c.h:668
static char * buf
Definition: pg_test_fsync.c:67
bool translate_header
Definition: print.h:173
FILE * logfile
Definition: settings.h:116
void PQclear(PGresult *res)
Definition: fe-exec.c:694
char * title
Definition: print.h:171
printQueryOpt popt
Definition: settings.h:91
int n_translate_columns
Definition: print.h:176
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3433
const bool * translate_columns
Definition: print.h:174
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition: describe.c:6037
#define _(x)
Definition: elog.c:88
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:177
PGresult * PSQLexec(const char *query)
Definition: common.c:536

◆ listDomains()