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 const char * map_typename_pattern (const char *pattern)
 
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)
 
static bool validateSQLNamePattern (PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule, bool *added_clause, int maxparts)
 
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 *func_pattern, char **arg_patterns, int num_arg_patterns, bool verbose, bool showSystem)
 
bool describeTypes (const char *pattern, bool verbose, bool showSystem)
 
bool describeOperators (const char *oper_pattern, char **arg_patterns, int num_arg_patterns, bool verbose, bool showSystem)
 
bool listAllDbs (const char *pattern, bool verbose)
 
bool permissionsList (const char *pattern, bool showSystem)
 
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 describeRoleGrants (const char *pattern, bool showSystem)
 
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 describeConfigurationParameters (const char *pattern, bool verbose, bool showSystem)
 
bool listEventTriggers (const char *pattern, bool verbose)
 
bool listExtendedStats (const char *pattern)
 
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)
 
static bool addFooterToPublicationDesc (PQExpBuffer buf, const char *footermsg, bool as_schema, printTableContent *const cont)
 
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 listOpFamilyFunctions (const char *access_method_pattern, const char *family_pattern, bool verbose)
 
bool listLargeObjects (bool verbose)
 

Function Documentation

◆ add_role_attribute()

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

Definition at line 3749 of file describe.c.

3750 {
3751  if (buf->len > 0)
3752  appendPQExpBufferStr(buf, ", ");
3753 
3755 }
const char * str
static char * buf
Definition: pg_test_fsync.c:73
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367

References appendPQExpBufferStr(), buf, and str.

Referenced by describeRoles().

◆ add_tablespace_footer()

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

Definition at line 3549 of file describe.c.

3551 {
3552  /* relkinds for which we support tablespaces */
3553  if (relkind == RELKIND_RELATION ||
3554  relkind == RELKIND_MATVIEW ||
3555  relkind == RELKIND_INDEX ||
3556  relkind == RELKIND_PARTITIONED_TABLE ||
3557  relkind == RELKIND_PARTITIONED_INDEX ||
3558  relkind == RELKIND_TOASTVALUE)
3559  {
3560  /*
3561  * We ignore the database default tablespace so that users not using
3562  * tablespaces don't need to know about them.
3563  */
3564  if (tablespace != 0)
3565  {
3566  PGresult *result = NULL;
3568 
3569  initPQExpBuffer(&buf);
3571  "SELECT spcname FROM pg_catalog.pg_tablespace\n"
3572  "WHERE oid = '%u';", tablespace);
3573  result = PSQLexec(buf.data);
3574  if (!result)
3575  {
3576  termPQExpBuffer(&buf);
3577  return;
3578  }
3579  /* Should always be the case, but.... */
3580  if (PQntuples(result) > 0)
3581  {
3582  if (newline)
3583  {
3584  /* Add the tablespace as a new footer */
3585  printfPQExpBuffer(&buf, _("Tablespace: \"%s\""),
3586  PQgetvalue(result, 0, 0));
3587  printTableAddFooter(cont, buf.data);
3588  }
3589  else
3590  {
3591  /* Append the tablespace to the latest footer */
3592  printfPQExpBuffer(&buf, "%s", cont->footer->data);
3593 
3594  /*-------
3595  translator: before this string there's an index description like
3596  '"foo_pkey" PRIMARY KEY, btree (a)' */
3597  appendPQExpBuffer(&buf, _(", tablespace \"%s\""),
3598  PQgetvalue(result, 0, 0));
3599  printTableSetFooter(cont, buf.data);
3600  }
3601  }
3602  PQclear(result);
3603  termPQExpBuffer(&buf);
3604  }
3605  }
3606 }
PGresult * PSQLexec(const char *query)
Definition: common.c:620
#define _(x)
Definition: elog.c:90
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
void printTableSetFooter(printTableContent *const content, const char *footer)
Definition: print.c:3335
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition: print.c:3310
#define newline
Definition: indent_codes.h:35
static char * tablespace
Definition: pgbench.c:216
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:235
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
printTableFooter * footer
Definition: print.h:177
char * data
Definition: print.h:155

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

Referenced by describeOneTableDetails().

◆ addFooterToPublicationDesc()

static bool addFooterToPublicationDesc ( PQExpBuffer  buf,
const char *  footermsg,
bool  as_schema,
printTableContent *const  cont 
)
static

Definition at line 6303 of file describe.c.

6305 {
6306  PGresult *res;
6307  int count = 0;
6308  int i = 0;
6309 
6310  res = PSQLexec(buf->data);
6311  if (!res)
6312  return false;
6313  else
6314  count = PQntuples(res);
6315 
6316  if (count > 0)
6317  printTableAddFooter(cont, footermsg);
6318 
6319  for (i = 0; i < count; i++)
6320  {
6321  if (as_schema)
6322  printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, 0));
6323  else
6324  {
6325  printfPQExpBuffer(buf, " \"%s.%s\"", PQgetvalue(res, i, 0),
6326  PQgetvalue(res, i, 1));
6327 
6328  if (!PQgetisnull(res, i, 3))
6329  appendPQExpBuffer(buf, " (%s)", PQgetvalue(res, i, 3));
6330 
6331  if (!PQgetisnull(res, i, 2))
6332  appendPQExpBuffer(buf, " WHERE %s", PQgetvalue(res, i, 2));
6333  }
6334 
6335  printTableAddFooter(cont, buf->data);
6336  }
6337 
6338  PQclear(res);
6339  return true;
6340 }
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3901
int i
Definition: isn.c:73

References appendPQExpBuffer(), buf, i, PQclear(), PQgetisnull(), PQgetvalue(), PQntuples(), printfPQExpBuffer(), printTableAddFooter(), PSQLexec(), and res.

Referenced by describePublications().

◆ describeAccessMethods()

bool describeAccessMethods ( const char *  pattern,
bool  verbose 
)

Definition at line 141 of file describe.c.

142 {
144  PGresult *res;
145  printQueryOpt myopt = pset.popt;
146  static const bool translate_columns[] = {false, true, false, false};
147 
148  if (pset.sversion < 90600)
149  {
150  char sverbuf[32];
151 
152  pg_log_error("The server (version %s) does not support access methods.",
154  sverbuf, sizeof(sverbuf)));
155  return true;
156  }
157 
159 
161  "SELECT amname AS \"%s\",\n"
162  " CASE amtype"
163  " WHEN 'i' THEN '%s'"
164  " WHEN 't' THEN '%s'"
165  " END AS \"%s\"",
166  gettext_noop("Name"),
167  gettext_noop("Index"),
168  gettext_noop("Table"),
169  gettext_noop("Type"));
170 
171  if (verbose)
172  {
174  ",\n amhandler AS \"%s\",\n"
175  " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"",
176  gettext_noop("Handler"),
177  gettext_noop("Description"));
178  }
179 
181  "\nFROM pg_catalog.pg_am\n");
182 
183  if (!validateSQLNamePattern(&buf, pattern, false, false,
184  NULL, "amname", NULL,
185  NULL,
186  NULL, 1))
187  {
189  return false;
190  }
191 
192  appendPQExpBufferStr(&buf, "ORDER BY 1;");
193 
194  res = PSQLexec(buf.data);
196  if (!res)
197  return false;
198 
199  myopt.title = _("List of access methods");
200  myopt.translate_header = true;
201  myopt.translate_columns = translate_columns;
202  myopt.n_translate_columns = lengthof(translate_columns);
203 
204  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
205 
206  PQclear(res);
207  return true;
208 }
#define gettext_noop(x)
Definition: c.h:1196
#define lengthof(array)
Definition: c.h:788
static bool validateSQLNamePattern(PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule, bool *added_clause, int maxparts)
Definition: describe.c:6174
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3549
int verbose
#define pg_log_error(...)
Definition: logging.h:106
PsqlSettings pset
Definition: startup.c:32
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
Definition: string_utils.c:177
printQueryOpt popt
Definition: settings.h:91
FILE * logfile
Definition: settings.h:120
FILE * queryFout
Definition: settings.h:84
const bool * translate_columns
Definition: print.h:190
char * title
Definition: print.h:187
bool translate_header
Definition: print.h:189
int n_translate_columns
Definition: print.h:192

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, pg_log_error, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ describeAggregates()

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

Definition at line 71 of file describe.c.

72 {
74  PGresult *res;
75  printQueryOpt myopt = pset.popt;
76 
78 
80  "SELECT n.nspname as \"%s\",\n"
81  " p.proname AS \"%s\",\n"
82  " pg_catalog.format_type(p.prorettype, NULL) AS \"%s\",\n"
83  " CASE WHEN p.pronargs = 0\n"
84  " THEN CAST('*' AS pg_catalog.text)\n"
85  " ELSE pg_catalog.pg_get_function_arguments(p.oid)\n"
86  " END AS \"%s\",\n",
87  gettext_noop("Schema"),
88  gettext_noop("Name"),
89  gettext_noop("Result data type"),
90  gettext_noop("Argument data types"));
91 
92  if (pset.sversion >= 110000)
94  " pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"\n"
95  "FROM pg_catalog.pg_proc p\n"
96  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"
97  "WHERE p.prokind = 'a'\n",
98  gettext_noop("Description"));
99  else
101  " pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"\n"
102  "FROM pg_catalog.pg_proc p\n"
103  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"
104  "WHERE p.proisagg\n",
105  gettext_noop("Description"));
106 
107  if (!showSystem && !pattern)
108  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
109  " AND n.nspname <> 'information_schema'\n");
110 
111  if (!validateSQLNamePattern(&buf, pattern, true, false,
112  "n.nspname", "p.proname", NULL,
113  "pg_catalog.pg_function_is_visible(p.oid)",
114  NULL, 3))
115  {
117  return false;
118  }
119 
120  appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
121 
122  res = PSQLexec(buf.data);
124  if (!res)
125  return false;
126 
127  myopt.title = _("List of aggregate functions");
128  myopt.translate_header = true;
129 
130  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
131 
132  PQclear(res);
133  return true;
134 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, and validateSQLNamePattern().

Referenced by exec_command_d().

◆ describeConfigurationParameters()

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

Definition at line 4556 of file describe.c.

4558 {
4560  PGresult *res;
4561  printQueryOpt myopt = pset.popt;
4562 
4563  initPQExpBuffer(&buf);
4565  "SELECT s.name AS \"%s\", "
4566  "pg_catalog.current_setting(s.name) AS \"%s\"",
4567  gettext_noop("Parameter"),
4568  gettext_noop("Value"));
4569 
4570  if (verbose)
4571  {
4573  ", s.vartype AS \"%s\", s.context AS \"%s\", ",
4574  gettext_noop("Type"),
4575  gettext_noop("Context"));
4576  if (pset.sversion >= 150000)
4577  printACLColumn(&buf, "p.paracl");
4578  else
4579  appendPQExpBuffer(&buf, "NULL AS \"%s\"",
4580  gettext_noop("Access privileges"));
4581  }
4582 
4583  appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_settings s\n");
4584 
4585  if (verbose && pset.sversion >= 150000)
4587  " LEFT JOIN pg_catalog.pg_parameter_acl p\n"
4588  " ON pg_catalog.lower(s.name) = p.parname\n");
4589 
4590  if (pattern)
4591  processSQLNamePattern(pset.db, &buf, pattern,
4592  false, false,
4593  NULL, "pg_catalog.lower(s.name)", NULL,
4594  NULL, NULL, NULL);
4595  else
4596  appendPQExpBufferStr(&buf, "WHERE s.source <> 'default' AND\n"
4597  " s.setting IS DISTINCT FROM s.boot_val\n");
4598 
4599  appendPQExpBufferStr(&buf, "ORDER BY 1;");
4600 
4601  res = PSQLexec(buf.data);
4602  termPQExpBuffer(&buf);
4603  if (!res)
4604  return false;
4605 
4606  if (pattern)
4607  myopt.title = _("List of configuration parameters");
4608  else
4609  myopt.title = _("List of non-default configuration parameters");
4610  myopt.translate_header = true;
4611 
4612  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4613 
4614  PQclear(res);
4615  return true;
4616 }
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition: describe.c:6669
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, PQExpBuffer dbnamebuf, int *dotcnt)
Definition: string_utils.c:891
PGconn * db
Definition: settings.h:82

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

Referenced by exec_command_d().

◆ describeFunctions()

bool describeFunctions ( const char *  functypes,
const char *  func_pattern,
char **  arg_patterns,
int  num_arg_patterns,
bool  verbose,
bool  showSystem 
)

Definition at line 288 of file describe.c.

291 {
292  bool showAggregate = strchr(functypes, 'a') != NULL;
293  bool showNormal = strchr(functypes, 'n') != NULL;
294  bool showProcedure = strchr(functypes, 'p') != NULL;
295  bool showTrigger = strchr(functypes, 't') != NULL;
296  bool showWindow = strchr(functypes, 'w') != NULL;
297  bool have_where;
299  PGresult *res;
300  printQueryOpt myopt = pset.popt;
301  static const bool translate_columns[] = {false, false, false, false, true, true, true, false, true, false, false, false, false};
302 
303  /* No "Parallel" column before 9.6 */
304  static const bool translate_columns_pre_96[] = {false, false, false, false, true, true, false, true, false, false, false, false};
305 
306  if (strlen(functypes) != strspn(functypes, "anptwS+"))
307  {
308  pg_log_error("\\df only takes [anptwS+] as options");
309  return true;
310  }
311 
312  if (showProcedure && pset.sversion < 110000)
313  {
314  char sverbuf[32];
315 
316  pg_log_error("\\df does not take a \"%c\" option with server version %s",
317  'p',
319  sverbuf, sizeof(sverbuf)));
320  return true;
321  }
322 
323  if (!showAggregate && !showNormal && !showProcedure && !showTrigger && !showWindow)
324  {
325  showAggregate = showNormal = showTrigger = showWindow = true;
326  if (pset.sversion >= 110000)
327  showProcedure = true;
328  }
329 
331 
333  "SELECT n.nspname as \"%s\",\n"
334  " p.proname as \"%s\",\n",
335  gettext_noop("Schema"),
336  gettext_noop("Name"));
337 
338  if (pset.sversion >= 110000)
340  " pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n"
341  " pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n"
342  " CASE p.prokind\n"
343  " WHEN 'a' THEN '%s'\n"
344  " WHEN 'w' THEN '%s'\n"
345  " WHEN 'p' THEN '%s'\n"
346  " ELSE '%s'\n"
347  " END as \"%s\"",
348  gettext_noop("Result data type"),
349  gettext_noop("Argument data types"),
350  /* translator: "agg" is short for "aggregate" */
351  gettext_noop("agg"),
352  gettext_noop("window"),
353  gettext_noop("proc"),
354  gettext_noop("func"),
355  gettext_noop("Type"));
356  else
358  " pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n"
359  " pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n"
360  " CASE\n"
361  " WHEN p.proisagg THEN '%s'\n"
362  " WHEN p.proiswindow THEN '%s'\n"
363  " WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN '%s'\n"
364  " ELSE '%s'\n"
365  " END as \"%s\"",
366  gettext_noop("Result data type"),
367  gettext_noop("Argument data types"),
368  /* translator: "agg" is short for "aggregate" */
369  gettext_noop("agg"),
370  gettext_noop("window"),
371  gettext_noop("trigger"),
372  gettext_noop("func"),
373  gettext_noop("Type"));
374 
375  if (verbose)
376  {
378  ",\n CASE\n"
379  " WHEN p.provolatile = 'i' THEN '%s'\n"
380  " WHEN p.provolatile = 's' THEN '%s'\n"
381  " WHEN p.provolatile = 'v' THEN '%s'\n"
382  " END as \"%s\"",
383  gettext_noop("immutable"),
384  gettext_noop("stable"),
385  gettext_noop("volatile"),
386  gettext_noop("Volatility"));
387  if (pset.sversion >= 90600)
389  ",\n CASE\n"
390  " WHEN p.proparallel = 'r' THEN '%s'\n"
391  " WHEN p.proparallel = 's' THEN '%s'\n"
392  " WHEN p.proparallel = 'u' THEN '%s'\n"
393  " END as \"%s\"",
394  gettext_noop("restricted"),
395  gettext_noop("safe"),
396  gettext_noop("unsafe"),
397  gettext_noop("Parallel"));
399  ",\n pg_catalog.pg_get_userbyid(p.proowner) as \"%s\""
400  ",\n CASE WHEN prosecdef THEN '%s' ELSE '%s' END AS \"%s\"",
401  gettext_noop("Owner"),
402  gettext_noop("definer"),
403  gettext_noop("invoker"),
404  gettext_noop("Security"));
405  appendPQExpBufferStr(&buf, ",\n ");
406  printACLColumn(&buf, "p.proacl");
408  ",\n l.lanname as \"%s\"",
409  gettext_noop("Language"));
411  ",\n CASE WHEN l.lanname IN ('internal', 'c') THEN p.prosrc END as \"%s\"",
412  gettext_noop("Internal name"));
414  ",\n pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"",
415  gettext_noop("Description"));
416  }
417 
419  "\nFROM pg_catalog.pg_proc p"
420  "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n");
421 
422  for (int i = 0; i < num_arg_patterns; i++)
423  {
425  " LEFT JOIN pg_catalog.pg_type t%d ON t%d.oid = p.proargtypes[%d]\n"
426  " LEFT JOIN pg_catalog.pg_namespace nt%d ON nt%d.oid = t%d.typnamespace\n",
427  i, i, i, i, i, i);
428  }
429 
430  if (verbose)
432  " LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang\n");
433 
434  have_where = false;
435 
436  /* filter by function type, if requested */
437  if (showNormal && showAggregate && showProcedure && showTrigger && showWindow)
438  /* Do nothing */ ;
439  else if (showNormal)
440  {
441  if (!showAggregate)
442  {
443  if (have_where)
444  appendPQExpBufferStr(&buf, " AND ");
445  else
446  {
447  appendPQExpBufferStr(&buf, "WHERE ");
448  have_where = true;
449  }
450  if (pset.sversion >= 110000)
451  appendPQExpBufferStr(&buf, "p.prokind <> 'a'\n");
452  else
453  appendPQExpBufferStr(&buf, "NOT p.proisagg\n");
454  }
455  if (!showProcedure && pset.sversion >= 110000)
456  {
457  if (have_where)
458  appendPQExpBufferStr(&buf, " AND ");
459  else
460  {
461  appendPQExpBufferStr(&buf, "WHERE ");
462  have_where = true;
463  }
464  appendPQExpBufferStr(&buf, "p.prokind <> 'p'\n");
465  }
466  if (!showTrigger)
467  {
468  if (have_where)
469  appendPQExpBufferStr(&buf, " AND ");
470  else
471  {
472  appendPQExpBufferStr(&buf, "WHERE ");
473  have_where = true;
474  }
475  appendPQExpBufferStr(&buf, "p.prorettype <> 'pg_catalog.trigger'::pg_catalog.regtype\n");
476  }
477  if (!showWindow)
478  {
479  if (have_where)
480  appendPQExpBufferStr(&buf, " AND ");
481  else
482  {
483  appendPQExpBufferStr(&buf, "WHERE ");
484  have_where = true;
485  }
486  if (pset.sversion >= 110000)
487  appendPQExpBufferStr(&buf, "p.prokind <> 'w'\n");
488  else
489  appendPQExpBufferStr(&buf, "NOT p.proiswindow\n");
490  }
491  }
492  else
493  {
494  bool needs_or = false;
495 
496  appendPQExpBufferStr(&buf, "WHERE (\n ");
497  have_where = true;
498  /* Note: at least one of these must be true ... */
499  if (showAggregate)
500  {
501  if (pset.sversion >= 110000)
502  appendPQExpBufferStr(&buf, "p.prokind = 'a'\n");
503  else
504  appendPQExpBufferStr(&buf, "p.proisagg\n");
505  needs_or = true;
506  }
507  if (showTrigger)
508  {
509  if (needs_or)
510  appendPQExpBufferStr(&buf, " OR ");
512  "p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype\n");
513  needs_or = true;
514  }
515  if (showProcedure)
516  {
517  if (needs_or)
518  appendPQExpBufferStr(&buf, " OR ");
519  appendPQExpBufferStr(&buf, "p.prokind = 'p'\n");
520  needs_or = true;
521  }
522  if (showWindow)
523  {
524  if (needs_or)
525  appendPQExpBufferStr(&buf, " OR ");
526  if (pset.sversion >= 110000)
527  appendPQExpBufferStr(&buf, "p.prokind = 'w'\n");
528  else
529  appendPQExpBufferStr(&buf, "p.proiswindow\n");
530  }
531  appendPQExpBufferStr(&buf, " )\n");
532  }
533 
534  if (!validateSQLNamePattern(&buf, func_pattern, have_where, false,
535  "n.nspname", "p.proname", NULL,
536  "pg_catalog.pg_function_is_visible(p.oid)",
537  NULL, 3))
538  goto error_return;
539 
540  for (int i = 0; i < num_arg_patterns; i++)
541  {
542  if (strcmp(arg_patterns[i], "-") != 0)
543  {
544  /*
545  * Match type-name patterns against either internal or external
546  * name, like \dT. Unlike \dT, there seems no reason to
547  * discriminate against arrays or composite types.
548  */
549  char nspname[64];
550  char typname[64];
551  char ft[64];
552  char tiv[64];
553 
554  snprintf(nspname, sizeof(nspname), "nt%d.nspname", i);
555  snprintf(typname, sizeof(typname), "t%d.typname", i);
556  snprintf(ft, sizeof(ft),
557  "pg_catalog.format_type(t%d.oid, NULL)", i);
558  snprintf(tiv, sizeof(tiv),
559  "pg_catalog.pg_type_is_visible(t%d.oid)", i);
561  map_typename_pattern(arg_patterns[i]),
562  true, false,
563  nspname, typname, ft, tiv,
564  NULL, 3))
565  goto error_return;
566  }
567  else
568  {
569  /* "-" pattern specifies no such parameter */
570  appendPQExpBuffer(&buf, " AND t%d.typname IS NULL\n", i);
571  }
572  }
573 
574  if (!showSystem && !func_pattern)
575  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
576  " AND n.nspname <> 'information_schema'\n");
577 
578  appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
579 
580  res = PSQLexec(buf.data);
582  if (!res)
583  return false;
584 
585  myopt.title = _("List of functions");
586  myopt.translate_header = true;
587  if (pset.sversion >= 90600)
588  {
589  myopt.translate_columns = translate_columns;
590  myopt.n_translate_columns = lengthof(translate_columns);
591  }
592  else
593  {
594  myopt.translate_columns = translate_columns_pre_96;
595  myopt.n_translate_columns = lengthof(translate_columns_pre_96);
596  }
597 
598  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
599 
600  PQclear(res);
601  return true;
602 
603 error_return:
605  return false;
606 }
static const char * map_typename_pattern(const char *pattern)
Definition: describe.c:720
NameData typname
Definition: pg_type.h:41
#define snprintf
Definition: port.h:238

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, formatPGVersionNumber(), gettext_noop, i, initPQExpBuffer(), lengthof, _psqlSettings::logfile, map_typename_pattern(), printQueryOpt::n_translate_columns, pg_log_error, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, snprintf, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, typname, validateSQLNamePattern(), and verbose.

Referenced by exec_command_dfo().

◆ describeOneTableDetails()

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

Definition at line 1528 of file describe.c.

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

References _, add_tablespace_footer(), appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), Assert, atooid, buf, CppAsString2, StringInfoData::data, PQExpBufferData::data, printTableOpt::default_footer, _psqlSettings::encoding, printTableOpt::expanded, fmtId(), printQueryOpt::footers, free, gettext_noop, _psqlSettings::hide_compression, _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, res, resetPQExpBuffer(), storage, _psqlSettings::sversion, tablespace, termPQExpBuffer(), printQueryOpt::title, tmpbuf, printQueryOpt::topt, printQueryOpt::translate_header, and verbose.

Referenced by describeTableDetails().

◆ describeOneTSConfig()

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

Definition at line 5667 of file describe.c.

5669 {
5671  title;
5672  PGresult *res;
5673  printQueryOpt myopt = pset.popt;
5674 
5675  initPQExpBuffer(&buf);
5676 
5678  "SELECT\n"
5679  " ( SELECT t.alias FROM\n"
5680  " pg_catalog.ts_token_type(c.cfgparser) AS t\n"
5681  " WHERE t.tokid = m.maptokentype ) AS \"%s\",\n"
5682  " pg_catalog.btrim(\n"
5683  " ARRAY( SELECT mm.mapdict::pg_catalog.regdictionary\n"
5684  " FROM pg_catalog.pg_ts_config_map AS mm\n"
5685  " WHERE mm.mapcfg = m.mapcfg AND mm.maptokentype = m.maptokentype\n"
5686  " ORDER BY mapcfg, maptokentype, mapseqno\n"
5687  " ) :: pg_catalog.text,\n"
5688  " '{}') AS \"%s\"\n"
5689  "FROM pg_catalog.pg_ts_config AS c, pg_catalog.pg_ts_config_map AS m\n"
5690  "WHERE c.oid = '%s' AND m.mapcfg = c.oid\n"
5691  "GROUP BY m.mapcfg, m.maptokentype, c.cfgparser\n"
5692  "ORDER BY 1;",
5693  gettext_noop("Token"),
5694  gettext_noop("Dictionaries"),
5695  oid);
5696 
5697  res = PSQLexec(buf.data);
5698  termPQExpBuffer(&buf);
5699  if (!res)
5700  return false;
5701 
5702  initPQExpBuffer(&title);
5703 
5704  if (nspname)
5705  appendPQExpBuffer(&title, _("Text search configuration \"%s.%s\""),
5706  nspname, cfgname);
5707  else
5708  appendPQExpBuffer(&title, _("Text search configuration \"%s\""),
5709  cfgname);
5710 
5711  if (pnspname)
5712  appendPQExpBuffer(&title, _("\nParser: \"%s.%s\""),
5713  pnspname, prsname);
5714  else
5715  appendPQExpBuffer(&title, _("\nParser: \"%s\""),
5716  prsname);
5717 
5718  myopt.title = title.data;
5719  myopt.footers = NULL;
5720  myopt.topt.default_footer = false;
5721  myopt.translate_header = true;
5722 
5723  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5724 
5725  termPQExpBuffer(&title);
5726 
5727  PQclear(res);
5728  return true;
5729 }

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

Referenced by listTSConfigsVerbose().

◆ describeOneTSParser()

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

Definition at line 5284 of file describe.c.

5285 {
5287  PGresult *res;
5288  PQExpBufferData title;
5289  printQueryOpt myopt = pset.popt;
5290  static const bool translate_columns[] = {true, false, false};
5291 
5292  initPQExpBuffer(&buf);
5293 
5295  "SELECT '%s' AS \"%s\",\n"
5296  " p.prsstart::pg_catalog.regproc AS \"%s\",\n"
5297  " pg_catalog.obj_description(p.prsstart, 'pg_proc') as \"%s\"\n"
5298  " FROM pg_catalog.pg_ts_parser p\n"
5299  " WHERE p.oid = '%s'\n"
5300  "UNION ALL\n"
5301  "SELECT '%s',\n"
5302  " p.prstoken::pg_catalog.regproc,\n"
5303  " pg_catalog.obj_description(p.prstoken, 'pg_proc')\n"
5304  " FROM pg_catalog.pg_ts_parser p\n"
5305  " WHERE p.oid = '%s'\n"
5306  "UNION ALL\n"
5307  "SELECT '%s',\n"
5308  " p.prsend::pg_catalog.regproc,\n"
5309  " pg_catalog.obj_description(p.prsend, 'pg_proc')\n"
5310  " FROM pg_catalog.pg_ts_parser p\n"
5311  " WHERE p.oid = '%s'\n"
5312  "UNION ALL\n"
5313  "SELECT '%s',\n"
5314  " p.prsheadline::pg_catalog.regproc,\n"
5315  " pg_catalog.obj_description(p.prsheadline, 'pg_proc')\n"
5316  " FROM pg_catalog.pg_ts_parser p\n"
5317  " WHERE p.oid = '%s'\n"
5318  "UNION ALL\n"
5319  "SELECT '%s',\n"
5320  " p.prslextype::pg_catalog.regproc,\n"
5321  " pg_catalog.obj_description(p.prslextype, 'pg_proc')\n"
5322  " FROM pg_catalog.pg_ts_parser p\n"
5323  " WHERE p.oid = '%s';",
5324  gettext_noop("Start parse"),
5325  gettext_noop("Method"),
5326  gettext_noop("Function"),
5327  gettext_noop("Description"),
5328  oid,
5329  gettext_noop("Get next token"),
5330  oid,
5331  gettext_noop("End parse"),
5332  oid,
5333  gettext_noop("Get headline"),
5334  oid,
5335  gettext_noop("Get token types"),
5336  oid);
5337 
5338  res = PSQLexec(buf.data);
5339  termPQExpBuffer(&buf);
5340  if (!res)
5341  return false;
5342 
5343  initPQExpBuffer(&title);
5344  if (nspname)
5345  printfPQExpBuffer(&title, _("Text search parser \"%s.%s\""),
5346  nspname, prsname);
5347  else
5348  printfPQExpBuffer(&title, _("Text search parser \"%s\""), prsname);
5349  myopt.title = title.data;
5350  myopt.footers = NULL;
5351  myopt.topt.default_footer = false;
5352  myopt.translate_header = true;
5353  myopt.translate_columns = translate_columns;
5354  myopt.n_translate_columns = lengthof(translate_columns);
5355 
5356  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5357 
5358  PQclear(res);
5359 
5360  initPQExpBuffer(&buf);
5361 
5363  "SELECT t.alias as \"%s\",\n"
5364  " t.description as \"%s\"\n"
5365  "FROM pg_catalog.ts_token_type( '%s'::pg_catalog.oid ) as t\n"
5366  "ORDER BY 1;",
5367  gettext_noop("Token name"),
5368  gettext_noop("Description"),
5369  oid);
5370 
5371  res = PSQLexec(buf.data);
5372  termPQExpBuffer(&buf);
5373  if (!res)
5374  {
5375  termPQExpBuffer(&title);
5376  return false;
5377  }
5378 
5379  if (nspname)
5380  printfPQExpBuffer(&title, _("Token types for parser \"%s.%s\""),
5381  nspname, prsname);
5382  else
5383  printfPQExpBuffer(&title, _("Token types for parser \"%s\""), prsname);
5384  myopt.title = title.data;
5385  myopt.footers = NULL;
5386  myopt.topt.default_footer = true;
5387  myopt.translate_header = true;
5388  myopt.translate_columns = NULL;
5389  myopt.n_translate_columns = 0;
5390 
5391  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5392 
5393  termPQExpBuffer(&title);
5394  PQclear(res);
5395  return true;
5396 }

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

Referenced by listTSParsersVerbose().

◆ describeOperators()

bool describeOperators ( const char *  oper_pattern,
char **  arg_patterns,
int  num_arg_patterns,
bool  verbose,
bool  showSystem 
)

Definition at line 770 of file describe.c.

773 {
775  PGresult *res;
776  printQueryOpt myopt = pset.popt;
777 
779 
780  /*
781  * Note: before Postgres 9.1, we did not assign comments to any built-in
782  * operators, preferring to let the comment on the underlying function
783  * suffice. The coalesce() on the obj_description() calls below supports
784  * this convention by providing a fallback lookup of a comment on the
785  * operator's function. Since 9.1 there is a policy that every built-in
786  * operator should have a comment; so the coalesce() is no longer
787  * necessary so far as built-in operators are concerned. We keep it
788  * anyway, for now, because third-party modules may still be following the
789  * old convention.
790  *
791  * The support for postfix operators in this query is dead code as of
792  * Postgres 14, but we need to keep it for as long as we support talking
793  * to pre-v14 servers.
794  */
795 
797  "SELECT n.nspname as \"%s\",\n"
798  " o.oprname AS \"%s\",\n"
799  " CASE WHEN o.oprkind='l' THEN NULL ELSE pg_catalog.format_type(o.oprleft, NULL) END AS \"%s\",\n"
800  " CASE WHEN o.oprkind='r' THEN NULL ELSE pg_catalog.format_type(o.oprright, NULL) END AS \"%s\",\n"
801  " pg_catalog.format_type(o.oprresult, NULL) AS \"%s\",\n",
802  gettext_noop("Schema"),
803  gettext_noop("Name"),
804  gettext_noop("Left arg type"),
805  gettext_noop("Right arg type"),
806  gettext_noop("Result type"));
807 
808  if (verbose)
810  " o.oprcode AS \"%s\",\n",
811  gettext_noop("Function"));
812 
814  " coalesce(pg_catalog.obj_description(o.oid, 'pg_operator'),\n"
815  " pg_catalog.obj_description(o.oprcode, 'pg_proc')) AS \"%s\"\n"
816  "FROM pg_catalog.pg_operator o\n"
817  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace\n",
818  gettext_noop("Description"));
819 
820  if (num_arg_patterns >= 2)
821  {
822  num_arg_patterns = 2; /* ignore any additional arguments */
824  " LEFT JOIN pg_catalog.pg_type t0 ON t0.oid = o.oprleft\n"
825  " LEFT JOIN pg_catalog.pg_namespace nt0 ON nt0.oid = t0.typnamespace\n"
826  " LEFT JOIN pg_catalog.pg_type t1 ON t1.oid = o.oprright\n"
827  " LEFT JOIN pg_catalog.pg_namespace nt1 ON nt1.oid = t1.typnamespace\n");
828  }
829  else if (num_arg_patterns == 1)
830  {
832  " LEFT JOIN pg_catalog.pg_type t0 ON t0.oid = o.oprright\n"
833  " LEFT JOIN pg_catalog.pg_namespace nt0 ON nt0.oid = t0.typnamespace\n");
834  }
835 
836  if (!showSystem && !oper_pattern)
837  appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
838  " AND n.nspname <> 'information_schema'\n");
839 
840  if (!validateSQLNamePattern(&buf, oper_pattern,
841  !showSystem && !oper_pattern, true,
842  "n.nspname", "o.oprname", NULL,
843  "pg_catalog.pg_operator_is_visible(o.oid)",
844  NULL, 3))
845  goto error_return;
846 
847  if (num_arg_patterns == 1)
848  appendPQExpBufferStr(&buf, " AND o.oprleft = 0\n");
849 
850  for (int i = 0; i < num_arg_patterns; i++)
851  {
852  if (strcmp(arg_patterns[i], "-") != 0)
853  {
854  /*
855  * Match type-name patterns against either internal or external
856  * name, like \dT. Unlike \dT, there seems no reason to
857  * discriminate against arrays or composite types.
858  */
859  char nspname[64];
860  char typname[64];
861  char ft[64];
862  char tiv[64];
863 
864  snprintf(nspname, sizeof(nspname), "nt%d.nspname", i);
865  snprintf(typname, sizeof(typname), "t%d.typname", i);
866  snprintf(ft, sizeof(ft),
867  "pg_catalog.format_type(t%d.oid, NULL)", i);
868  snprintf(tiv, sizeof(tiv),
869  "pg_catalog.pg_type_is_visible(t%d.oid)", i);
871  map_typename_pattern(arg_patterns[i]),
872  true, false,
873  nspname, typname, ft, tiv,
874  NULL, 3))
875  goto error_return;
876  }
877  else
878  {
879  /* "-" pattern specifies no such parameter */
880  appendPQExpBuffer(&buf, " AND t%d.typname IS NULL\n", i);
881  }
882  }
883 
884  appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3, 4;");
885 
886  res = PSQLexec(buf.data);
888  if (!res)
889  return false;
890 
891  myopt.title = _("List of operators");
892  myopt.translate_header = true;
893 
894  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
895 
896  PQclear(res);
897  return true;
898 
899 error_return:
901  return false;
902 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, i, initPQExpBuffer(), _psqlSettings::logfile, map_typename_pattern(), _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, snprintf, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, typname, validateSQLNamePattern(), and verbose.

Referenced by exec_command_dfo().

◆ describePublications()

bool describePublications ( const char *  pattern)

Definition at line 6349 of file describe.c.

6350 {
6352  int i;
6353  PGresult *res;
6354  bool has_pubtruncate;
6355  bool has_pubviaroot;
6356 
6357  PQExpBufferData title;
6358  printTableContent cont;
6359 
6360  if (pset.sversion < 100000)
6361  {
6362  char sverbuf[32];
6363 
6364  pg_log_error("The server (version %s) does not support publications.",
6366  sverbuf, sizeof(sverbuf)));
6367  return true;
6368  }
6369 
6370  has_pubtruncate = (pset.sversion >= 110000);
6371  has_pubviaroot = (pset.sversion >= 130000);
6372 
6373  initPQExpBuffer(&buf);
6374 
6376  "SELECT oid, pubname,\n"
6377  " pg_catalog.pg_get_userbyid(pubowner) AS owner,\n"
6378  " puballtables, pubinsert, pubupdate, pubdelete");
6379  if (has_pubtruncate)
6381  ", pubtruncate");
6382  if (has_pubviaroot)
6384  ", pubviaroot");
6386  "\nFROM pg_catalog.pg_publication\n");
6387 
6388  if (!validateSQLNamePattern(&buf, pattern, false, false,
6389  NULL, "pubname", NULL,
6390  NULL,
6391  NULL, 1))
6392  {
6393  termPQExpBuffer(&buf);
6394  return false;
6395  }
6396 
6397  appendPQExpBufferStr(&buf, "ORDER BY 2;");
6398 
6399  res = PSQLexec(buf.data);
6400  if (!res)
6401  {
6402  termPQExpBuffer(&buf);
6403  return false;
6404  }
6405 
6406  if (PQntuples(res) == 0)
6407  {
6408  if (!pset.quiet)
6409  {
6410  if (pattern)
6411  pg_log_error("Did not find any publication named \"%s\".",
6412  pattern);
6413  else
6414  pg_log_error("Did not find any publications.");
6415  }
6416 
6417  termPQExpBuffer(&buf);
6418  PQclear(res);
6419  return false;
6420  }
6421 
6422  for (i = 0; i < PQntuples(res); i++)
6423  {
6424  const char align = 'l';
6425  int ncols = 5;
6426  int nrows = 1;
6427  char *pubid = PQgetvalue(res, i, 0);
6428  char *pubname = PQgetvalue(res, i, 1);
6429  bool puballtables = strcmp(PQgetvalue(res, i, 3), "t") == 0;
6430  printTableOpt myopt = pset.popt.topt;
6431 
6432  if (has_pubtruncate)
6433  ncols++;
6434  if (has_pubviaroot)
6435  ncols++;
6436 
6437  initPQExpBuffer(&title);
6438  printfPQExpBuffer(&title, _("Publication %s"), pubname);
6439  printTableInit(&cont, &myopt, title.data, ncols, nrows);
6440 
6441  printTableAddHeader(&cont, gettext_noop("Owner"), true, align);
6442  printTableAddHeader(&cont, gettext_noop("All tables"), true, align);
6443  printTableAddHeader(&cont, gettext_noop("Inserts"), true, align);
6444  printTableAddHeader(&cont, gettext_noop("Updates"), true, align);
6445  printTableAddHeader(&cont, gettext_noop("Deletes"), true, align);
6446  if (has_pubtruncate)
6447  printTableAddHeader(&cont, gettext_noop("Truncates"), true, align);
6448  if (has_pubviaroot)
6449  printTableAddHeader(&cont, gettext_noop("Via root"), true, align);
6450 
6451  printTableAddCell(&cont, PQgetvalue(res, i, 2), false, false);
6452  printTableAddCell(&cont, PQgetvalue(res, i, 3), false, false);
6453  printTableAddCell(&cont, PQgetvalue(res, i, 4), false, false);
6454  printTableAddCell(&cont, PQgetvalue(res, i, 5), false, false);
6455  printTableAddCell(&cont, PQgetvalue(res, i, 6), false, false);
6456  if (has_pubtruncate)
6457  printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false);
6458  if (has_pubviaroot)
6459  printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
6460 
6461  if (!puballtables)
6462  {
6463  /* Get the tables for the specified publication */
6465  "SELECT n.nspname, c.relname");
6466  if (pset.sversion >= 150000)
6467  {
6469  ", pg_get_expr(pr.prqual, c.oid)");
6471  ", (CASE WHEN pr.prattrs IS NOT NULL THEN\n"
6472  " pg_catalog.array_to_string("
6473  " ARRAY(SELECT attname\n"
6474  " FROM\n"
6475  " pg_catalog.generate_series(0, pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n"
6476  " pg_catalog.pg_attribute\n"
6477  " WHERE attrelid = c.oid AND attnum = prattrs[s]), ', ')\n"
6478  " ELSE NULL END)");
6479  }
6480  else
6482  ", NULL, NULL");
6484  "\nFROM pg_catalog.pg_class c,\n"
6485  " pg_catalog.pg_namespace n,\n"
6486  " pg_catalog.pg_publication_rel pr\n"
6487  "WHERE c.relnamespace = n.oid\n"
6488  " AND c.oid = pr.prrelid\n"
6489  " AND pr.prpubid = '%s'\n"
6490  "ORDER BY 1,2", pubid);
6491  if (!addFooterToPublicationDesc(&buf, _("Tables:"), false, &cont))
6492  goto error_return;
6493 
6494  if (pset.sversion >= 150000)
6495  {
6496  /* Get the schemas for the specified publication */
6498  "SELECT n.nspname\n"
6499  "FROM pg_catalog.pg_namespace n\n"
6500  " JOIN pg_catalog.pg_publication_namespace pn ON n.oid = pn.pnnspid\n"
6501  "WHERE pn.pnpubid = '%s'\n"
6502  "ORDER BY 1", pubid);
6503  if (!addFooterToPublicationDesc(&buf, _("Tables from schemas:"),
6504  true, &cont))
6505  goto error_return;
6506  }
6507  }
6508 
6509  printTable(&cont, pset.queryFout, false, pset.logfile);
6510  printTableCleanup(&cont);
6511 
6512  termPQExpBuffer(&title);
6513  }
6514 
6515  termPQExpBuffer(&buf);
6516  PQclear(res);
6517 
6518  return true;
6519 
6520 error_return:
6521  printTableCleanup(&cont);
6522  PQclear(res);
6523  termPQExpBuffer(&buf);
6524  termPQExpBuffer(&title);
6525  return false;
6526 }
static bool addFooterToPublicationDesc(PQExpBuffer buf, const char *footermsg, bool as_schema, printTableContent *const cont)
Definition: describe.c:6303

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

Referenced by exec_command_d().

◆ describeRoleGrants()

bool describeRoleGrants ( const char *  pattern,
bool  showSystem 
)

Definition at line 3830 of file describe.c.

3831 {
3833  PGresult *res;
3834  printQueryOpt myopt = pset.popt;
3835 
3836  initPQExpBuffer(&buf);
3838  "SELECT m.rolname AS \"%s\", r.rolname AS \"%s\",\n"
3839  " pg_catalog.concat_ws(', ',\n",
3840  gettext_noop("Role name"),
3841  gettext_noop("Member of"));
3842 
3843  if (pset.sversion >= 160000)
3845  " CASE WHEN pam.admin_option THEN 'ADMIN' END,\n"
3846  " CASE WHEN pam.inherit_option THEN 'INHERIT' END,\n"
3847  " CASE WHEN pam.set_option THEN 'SET' END\n");
3848  else
3850  " CASE WHEN pam.admin_option THEN 'ADMIN' END,\n"
3851  " CASE WHEN m.rolinherit THEN 'INHERIT' END,\n"
3852  " 'SET'\n");
3853 
3855  " ) AS \"%s\",\n"
3856  " g.rolname AS \"%s\"\n",
3857  gettext_noop("Options"),
3858  gettext_noop("Grantor"));
3859 
3861  "FROM pg_catalog.pg_roles m\n"
3862  " JOIN pg_catalog.pg_auth_members pam ON (pam.member = m.oid)\n"
3863  " LEFT JOIN pg_catalog.pg_roles r ON (pam.roleid = r.oid)\n"
3864  " LEFT JOIN pg_catalog.pg_roles g ON (pam.grantor = g.oid)\n");
3865 
3866  if (!showSystem && !pattern)
3867  appendPQExpBufferStr(&buf, "WHERE m.rolname !~ '^pg_'\n");
3868 
3869  if (!validateSQLNamePattern(&buf, pattern, false, false,
3870  NULL, "m.rolname", NULL, NULL,
3871  NULL, 1))
3872  {
3873  termPQExpBuffer(&buf);
3874  return false;
3875  }
3876 
3877  appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;\n");
3878 
3879  res = PSQLexec(buf.data);
3880  termPQExpBuffer(&buf);
3881  if (!res)
3882  return false;
3883 
3884  myopt.title = _("List of role grants");
3885  myopt.translate_header = true;
3886 
3887  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
3888 
3889  PQclear(res);
3890  return true;
3891 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, and validateSQLNamePattern().

Referenced by exec_command_d().

◆ describeRoles()

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

Definition at line 3614 of file describe.c.

3615 {
3617  PGresult *res;
3618  printTableContent cont;
3619  printTableOpt myopt = pset.popt.topt;
3620  int ncols = 2;
3621  int nrows = 0;
3622  int i;
3623  int conns;
3624  const char align = 'l';
3625  char **attr;
3626 
3627  myopt.default_footer = false;
3628 
3629  initPQExpBuffer(&buf);
3630 
3632  "SELECT r.rolname, r.rolsuper, r.rolinherit,\n"
3633  " r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,\n"
3634  " r.rolconnlimit, r.rolvaliduntil");
3635 
3636  if (verbose)
3637  {
3638  appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
3639  ncols++;
3640  }
3641  appendPQExpBufferStr(&buf, "\n, r.rolreplication");
3642 
3643  if (pset.sversion >= 90500)
3644  {
3645  appendPQExpBufferStr(&buf, "\n, r.rolbypassrls");
3646  }
3647 
3648  appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_roles r\n");
3649 
3650  if (!showSystem && !pattern)
3651  appendPQExpBufferStr(&buf, "WHERE r.rolname !~ '^pg_'\n");
3652 
3653  if (!validateSQLNamePattern(&buf, pattern, false, false,
3654  NULL, "r.rolname", NULL, NULL,
3655  NULL, 1))
3656  {
3657  termPQExpBuffer(&buf);
3658  return false;
3659  }
3660 
3661  appendPQExpBufferStr(&buf, "ORDER BY 1;");
3662 
3663  res = PSQLexec(buf.data);
3664  if (!res)
3665  return false;
3666 
3667  nrows = PQntuples(res);
3668  attr = pg_malloc0((nrows + 1) * sizeof(*attr));
3669 
3670  printTableInit(&cont, &myopt, _("List of roles"), ncols, nrows);
3671 
3672  printTableAddHeader(&cont, gettext_noop("Role name"), true, align);
3673  printTableAddHeader(&cont, gettext_noop("Attributes"), true, align);
3674 
3675  if (verbose)
3676  printTableAddHeader(&cont, gettext_noop("Description"), true, align);
3677 
3678  for (i = 0; i < nrows; i++)
3679  {
3680  printTableAddCell(&cont, PQgetvalue(res, i, 0), false, false);
3681 
3683  if (strcmp(PQgetvalue(res, i, 1), "t") == 0)
3684  add_role_attribute(&buf, _("Superuser"));
3685 
3686  if (strcmp(PQgetvalue(res, i, 2), "t") != 0)
3687  add_role_attribute(&buf, _("No inheritance"));
3688 
3689  if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
3690  add_role_attribute(&buf, _("Create role"));
3691 
3692  if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
3693  add_role_attribute(&buf, _("Create DB"));
3694 
3695  if (strcmp(PQgetvalue(res, i, 5), "t") != 0)
3696  add_role_attribute(&buf, _("Cannot login"));
3697 
3698  if (strcmp(PQgetvalue(res, i, (verbose ? 9 : 8)), "t") == 0)
3699  add_role_attribute(&buf, _("Replication"));
3700 
3701  if (pset.sversion >= 90500)
3702  if (strcmp(PQgetvalue(res, i, (verbose ? 10 : 9)), "t") == 0)
3703  add_role_attribute(&buf, _("Bypass RLS"));
3704 
3705  conns = atoi(PQgetvalue(res, i, 6));
3706  if (conns >= 0)
3707  {
3708  if (buf.len > 0)
3709  appendPQExpBufferChar(&buf, '\n');
3710 
3711  if (conns == 0)
3712  appendPQExpBufferStr(&buf, _("No connections"));
3713  else
3714  appendPQExpBuffer(&buf, ngettext("%d connection",
3715  "%d connections",
3716  conns),
3717  conns);
3718  }
3719 
3720  if (strcmp(PQgetvalue(res, i, 7), "") != 0)
3721  {
3722  if (buf.len > 0)
3723  appendPQExpBufferChar(&buf, '\n');
3724  appendPQExpBufferStr(&buf, _("Password valid until "));
3726  }
3727 
3728  attr[i] = pg_strdup(buf.data);
3729 
3730  printTableAddCell(&cont, attr[i], false, false);
3731 
3732  if (verbose)
3733  printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
3734  }
3735  termPQExpBuffer(&buf);
3736 
3737  printTable(&cont, pset.queryFout, false, pset.logfile);
3738  printTableCleanup(&cont);
3739 
3740  for (i = 0; i < nrows; i++)
3741  free(attr[i]);
3742  free(attr);
3743 
3744  PQclear(res);
3745  return true;
3746 }
#define ngettext(s, p, n)
Definition: c.h:1181
static void add_role_attribute(PQExpBuffer buf, const char *const str)
Definition: describe.c:3749
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
static IsoConnInfo * conns

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

Referenced by exec_command_d().

◆ describeSubscriptions()

bool describeSubscriptions ( const char *  pattern,
bool  verbose 
)

Definition at line 6535 of file describe.c.

6536 {
6538  PGresult *res;
6539  printQueryOpt myopt = pset.popt;
6540  static const bool translate_columns[] = {false, false, false, false,
6541  false, false, false, false, false, false, false, false, false, false,
6542  false};
6543 
6544  if (pset.sversion < 100000)
6545  {
6546  char sverbuf[32];
6547 
6548  pg_log_error("The server (version %s) does not support subscriptions.",
6550  sverbuf, sizeof(sverbuf)));
6551  return true;
6552  }
6553 
6554  initPQExpBuffer(&buf);
6555 
6557  "SELECT subname AS \"%s\"\n"
6558  ", pg_catalog.pg_get_userbyid(subowner) AS \"%s\"\n"
6559  ", subenabled AS \"%s\"\n"
6560  ", subpublications AS \"%s\"\n",
6561  gettext_noop("Name"),
6562  gettext_noop("Owner"),
6563  gettext_noop("Enabled"),
6564  gettext_noop("Publication"));
6565 
6566  if (verbose)
6567  {
6568  /* Binary mode and streaming are only supported in v14 and higher */
6569  if (pset.sversion >= 140000)
6570  {
6572  ", subbinary AS \"%s\"\n",
6573  gettext_noop("Binary"));
6574 
6575  if (pset.sversion >= 160000)
6577  ", (CASE substream\n"
6578  " WHEN 'f' THEN 'off'\n"
6579  " WHEN 't' THEN 'on'\n"
6580  " WHEN 'p' THEN 'parallel'\n"
6581  " END) AS \"%s\"\n",
6582  gettext_noop("Streaming"));
6583  else
6585  ", substream AS \"%s\"\n",
6586  gettext_noop("Streaming"));
6587  }
6588 
6589  /* Two_phase and disable_on_error are only supported in v15 and higher */
6590  if (pset.sversion >= 150000)
6592  ", subtwophasestate AS \"%s\"\n"
6593  ", subdisableonerr AS \"%s\"\n",
6594  gettext_noop("Two-phase commit"),
6595  gettext_noop("Disable on error"));
6596 
6597  if (pset.sversion >= 160000)
6599  ", suborigin AS \"%s\"\n"
6600  ", subpasswordrequired AS \"%s\"\n"
6601  ", subrunasowner AS \"%s\"\n",
6602  gettext_noop("Origin"),
6603  gettext_noop("Password required"),
6604  gettext_noop("Run as owner?"));
6605 
6606  if (pset.sversion >= 170000)
6608  ", subfailover AS \"%s\"\n",
6609  gettext_noop("Failover"));
6610 
6612  ", subsynccommit AS \"%s\"\n"
6613  ", subconninfo AS \"%s\"\n",
6614  gettext_noop("Synchronous commit"),
6615  gettext_noop("Conninfo"));
6616 
6617  /* Skip LSN is only supported in v15 and higher */
6618  if (pset.sversion >= 150000)
6620  ", subskiplsn AS \"%s\"\n",
6621  gettext_noop("Skip LSN"));
6622  }
6623 
6624  /* Only display subscriptions in current database. */
6626  "FROM pg_catalog.pg_subscription\n"
6627  "WHERE subdbid = (SELECT oid\n"
6628  " FROM pg_catalog.pg_database\n"
6629  " WHERE datname = pg_catalog.current_database())");
6630 
6631  if (!validateSQLNamePattern(&buf, pattern, true, false,
6632  NULL, "subname", NULL,
6633  NULL,
6634  NULL, 1))
6635  {
6636  termPQExpBuffer(&buf);
6637  return false;
6638  }
6639 
6640  appendPQExpBufferStr(&buf, "ORDER BY 1;");
6641 
6642  res = PSQLexec(buf.data);
6643  termPQExpBuffer(&buf);
6644  if (!res)
6645  return false;
6646 
6647  myopt.title = _("List of subscriptions");
6648  myopt.translate_header = true;
6649  myopt.translate_columns = translate_columns;
6650  myopt.n_translate_columns = lengthof(translate_columns);
6651 
6652  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6653 
6654  PQclear(res);
6655  return true;
6656 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, pg_log_error, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ describeTableDetails()

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

Definition at line 1445 of file describe.c.

1446 {
1448  PGresult *res;
1449  int i;
1450 
1451  initPQExpBuffer(&buf);
1452 
1454  "SELECT c.oid,\n"
1455  " n.nspname,\n"
1456  " c.relname\n"
1457  "FROM pg_catalog.pg_class c\n"
1458  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n");
1459 
1460  if (!showSystem && !pattern)
1461  appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
1462  " AND n.nspname <> 'information_schema'\n");
1463 
1464  if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern, false,
1465  "n.nspname", "c.relname", NULL,
1466  "pg_catalog.pg_table_is_visible(c.oid)",
1467  NULL, 3))
1468  {
1469  termPQExpBuffer(&buf);
1470  return false;
1471  }
1472 
1473  appendPQExpBufferStr(&buf, "ORDER BY 2, 3;");
1474 
1475  res = PSQLexec(buf.data);
1476  termPQExpBuffer(&buf);
1477  if (!res)
1478  return false;
1479 
1480  if (PQntuples(res) == 0)
1481  {
1482  if (!pset.quiet)
1483  {
1484  if (pattern)
1485  pg_log_error("Did not find any relation named \"%s\".",
1486  pattern);
1487  else
1488  pg_log_error("Did not find any relations.");
1489  }
1490  PQclear(res);
1491  return false;
1492  }
1493 
1494  for (i = 0; i < PQntuples(res); i++)
1495  {
1496  const char *oid;
1497  const char *nspname;
1498  const char *relname;
1499 
1500  oid = PQgetvalue(res, i, 0);
1501  nspname = PQgetvalue(res, i, 1);
1502  relname = PQgetvalue(res, i, 2);
1503 
1504  if (!describeOneTableDetails(nspname, relname, oid, verbose))
1505  {
1506  PQclear(res);
1507  return false;
1508  }
1509  if (cancel_pressed)
1510  {
1511  PQclear(res);
1512  return false;
1513  }
1514  }
1515 
1516  PQclear(res);
1517  return true;
1518 }
static bool describeOneTableDetails(const char *schemaname, const char *relationname, const char *oid, bool verbose)
Definition: describe.c:1528
volatile sig_atomic_t cancel_pressed
Definition: print.c:43

References appendPQExpBufferStr(), buf, cancel_pressed, describeOneTableDetails(), i, initPQExpBuffer(), pg_log_error, PQclear(), PQgetvalue(), PQntuples(), printfPQExpBuffer(), pset, PSQLexec(), _psqlSettings::quiet, relname, res, termPQExpBuffer(), validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ describeTablespaces()

bool describeTablespaces ( const char *  pattern,
bool  verbose 
)

Definition at line 215 of file describe.c.

216 {
218  PGresult *res;
219  printQueryOpt myopt = pset.popt;
220 
222 
224  "SELECT spcname AS \"%s\",\n"
225  " pg_catalog.pg_get_userbyid(spcowner) AS \"%s\",\n"
226  " pg_catalog.pg_tablespace_location(oid) AS \"%s\"",
227  gettext_noop("Name"),
228  gettext_noop("Owner"),
229  gettext_noop("Location"));
230 
231  if (verbose)
232  {
233  appendPQExpBufferStr(&buf, ",\n ");
234  printACLColumn(&buf, "spcacl");
236  ",\n spcoptions AS \"%s\""
237  ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\""
238  ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"",
239  gettext_noop("Options"),
240  gettext_noop("Size"),
241  gettext_noop("Description"));
242  }
243 
245  "\nFROM pg_catalog.pg_tablespace\n");
246 
247  if (!validateSQLNamePattern(&buf, pattern, false, false,
248  NULL, "spcname", NULL,
249  NULL,
250  NULL, 1))
251  {
253  return false;
254  }
255 
256  appendPQExpBufferStr(&buf, "ORDER BY 1;");
257 
258  res = PSQLexec(buf.data);
260  if (!res)
261  return false;
262 
263  myopt.title = _("List of tablespaces");
264  myopt.translate_header = true;
265 
266  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
267 
268  PQclear(res);
269  return true;
270 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ describeTypes()

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

Definition at line 615 of file describe.c.

616 {
618  PGresult *res;
619  printQueryOpt myopt = pset.popt;
620 
622 
624  "SELECT n.nspname as \"%s\",\n"
625  " pg_catalog.format_type(t.oid, NULL) AS \"%s\",\n",
626  gettext_noop("Schema"),
627  gettext_noop("Name"));
628  if (verbose)
629  {
631  " t.typname AS \"%s\",\n"
632  " CASE WHEN t.typrelid != 0\n"
633  " THEN CAST('tuple' AS pg_catalog.text)\n"
634  " WHEN t.typlen < 0\n"
635  " THEN CAST('var' AS pg_catalog.text)\n"
636  " ELSE CAST(t.typlen AS pg_catalog.text)\n"
637  " END AS \"%s\",\n"
638  " pg_catalog.array_to_string(\n"
639  " ARRAY(\n"
640  " SELECT e.enumlabel\n"
641  " FROM pg_catalog.pg_enum e\n"
642  " WHERE e.enumtypid = t.oid\n"
643  " ORDER BY e.enumsortorder\n"
644  " ),\n"
645  " E'\\n'\n"
646  " ) AS \"%s\",\n"
647  " pg_catalog.pg_get_userbyid(t.typowner) AS \"%s\",\n",
648  gettext_noop("Internal name"),
649  gettext_noop("Size"),
650  gettext_noop("Elements"),
651  gettext_noop("Owner"));
652  printACLColumn(&buf, "t.typacl");
653  appendPQExpBufferStr(&buf, ",\n ");
654  }
655 
657  " pg_catalog.obj_description(t.oid, 'pg_type') as \"%s\"\n",
658  gettext_noop("Description"));
659 
660  appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_type t\n"
661  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
662 
663  /*
664  * do not include complex types (typrelid!=0) unless they are standalone
665  * composite types
666  */
667  appendPQExpBufferStr(&buf, "WHERE (t.typrelid = 0 ");
668  appendPQExpBufferStr(&buf, "OR (SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
669  " FROM pg_catalog.pg_class c "
670  "WHERE c.oid = t.typrelid))\n");
671 
672  /*
673  * do not include array types unless the pattern contains []
674  */
675  if (pattern == NULL || strstr(pattern, "[]") == NULL)
676  appendPQExpBufferStr(&buf, " AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n");
677 
678  if (!showSystem && !pattern)
679  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
680  " AND n.nspname <> 'information_schema'\n");
681 
682  /* Match name pattern against either internal or external name */
684  true, false,
685  "n.nspname", "t.typname",
686  "pg_catalog.format_type(t.oid, NULL)",
687  "pg_catalog.pg_type_is_visible(t.oid)",
688  NULL, 3))
689  {
691  return false;
692  }
693 
694  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
695 
696  res = PSQLexec(buf.data);
698  if (!res)
699  return false;
700 
701  myopt.title = _("List of data types");
702  myopt.translate_header = true;
703 
704  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
705 
706  PQclear(res);
707  return true;
708 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, map_typename_pattern(), _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listAllDbs()

bool listAllDbs ( const char *  pattern,
bool  verbose 
)

Definition at line 911 of file describe.c.

912 {
913  PGresult *res;
915  printQueryOpt myopt = pset.popt;
916 
918 
920  "SELECT\n"
921  " d.datname as \"%s\",\n"
922  " pg_catalog.pg_get_userbyid(d.datdba) as \"%s\",\n"
923  " pg_catalog.pg_encoding_to_char(d.encoding) as \"%s\",\n",
924  gettext_noop("Name"),
925  gettext_noop("Owner"),
926  gettext_noop("Encoding"));
927  if (pset.sversion >= 150000)
929  " CASE d.datlocprovider WHEN 'b' THEN 'builtin' WHEN 'c' THEN 'libc' WHEN 'i' THEN 'icu' END AS \"%s\",\n",
930  gettext_noop("Locale Provider"));
931  else
933  " 'libc' AS \"%s\",\n",
934  gettext_noop("Locale Provider"));
936  " d.datcollate as \"%s\",\n"
937  " d.datctype as \"%s\",\n",
938  gettext_noop("Collate"),
939  gettext_noop("Ctype"));
940  if (pset.sversion >= 170000)
942  " d.datlocale as \"%s\",\n",
943  gettext_noop("Locale"));
944  else if (pset.sversion >= 150000)
946  " d.daticulocale as \"%s\",\n",
947  gettext_noop("Locale"));
948  else
950  " NULL as \"%s\",\n",
951  gettext_noop("Locale"));
952  if (pset.sversion >= 160000)
954  " d.daticurules as \"%s\",\n",
955  gettext_noop("ICU Rules"));
956  else
958  " NULL as \"%s\",\n",
959  gettext_noop("ICU Rules"));
960  appendPQExpBufferStr(&buf, " ");
961  printACLColumn(&buf, "d.datacl");
962  if (verbose)
964  ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n"
965  " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n"
966  " ELSE 'No Access'\n"
967  " END as \"%s\""
968  ",\n t.spcname as \"%s\""
969  ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"",
970  gettext_noop("Size"),
971  gettext_noop("Tablespace"),
972  gettext_noop("Description"));
974  "\nFROM pg_catalog.pg_database d\n");
975  if (verbose)
977  " JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
978 
979  if (pattern)
980  {
981  if (!validateSQLNamePattern(&buf, pattern, false, false,
982  NULL, "d.datname", NULL, NULL,
983  NULL, 1))
984  {
986  return false;
987  }
988  }
989 
990  appendPQExpBufferStr(&buf, "ORDER BY 1;");
991  res = PSQLexec(buf.data);
993  if (!res)
994  return false;
995 
996  myopt.title = _("List of databases");
997  myopt.translate_header = true;
998 
999  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1000 
1001  PQclear(res);
1002  return true;
1003 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_list(), and main().

◆ listCasts()

bool listCasts ( const char *  pattern,
bool  verbose 
)

Definition at line 4800 of file describe.c.

4801 {
4803  PGresult *res;
4804  printQueryOpt myopt = pset.popt;
4805  static const bool translate_columns[] = {false, false, false, true, false};
4806 
4807  initPQExpBuffer(&buf);
4808 
4810  "SELECT pg_catalog.format_type(castsource, NULL) AS \"%s\",\n"
4811  " pg_catalog.format_type(casttarget, NULL) AS \"%s\",\n",
4812  gettext_noop("Source type"),
4813  gettext_noop("Target type"));
4814 
4815  /*
4816  * We don't attempt to localize '(binary coercible)' or '(with inout)',
4817  * because there's too much risk of gettext translating a function name
4818  * that happens to match some string in the PO database.
4819  */
4821  " CASE WHEN c.castmethod = '%c' THEN '(binary coercible)'\n"
4822  " WHEN c.castmethod = '%c' THEN '(with inout)'\n"
4823  " ELSE p.proname\n"
4824  " END AS \"%s\",\n",
4825  COERCION_METHOD_BINARY,
4826  COERCION_METHOD_INOUT,
4827  gettext_noop("Function"));
4828 
4830  " CASE WHEN c.castcontext = '%c' THEN '%s'\n"
4831  " WHEN c.castcontext = '%c' THEN '%s'\n"
4832  " ELSE '%s'\n"
4833  " END AS \"%s\"",
4834  COERCION_CODE_EXPLICIT,
4835  gettext_noop("no"),
4836  COERCION_CODE_ASSIGNMENT,
4837  gettext_noop("in assignment"),
4838  gettext_noop("yes"),
4839  gettext_noop("Implicit?"));
4840 
4841  if (verbose)
4843  ",\n d.description AS \"%s\"",
4844  gettext_noop("Description"));
4845 
4846  /*
4847  * We need a left join to pg_proc for binary casts; the others are just
4848  * paranoia.
4849  */
4851  "\nFROM pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p\n"
4852  " ON c.castfunc = p.oid\n"
4853  " LEFT JOIN pg_catalog.pg_type ts\n"
4854  " ON c.castsource = ts.oid\n"
4855  " LEFT JOIN pg_catalog.pg_namespace ns\n"
4856  " ON ns.oid = ts.typnamespace\n"
4857  " LEFT JOIN pg_catalog.pg_type tt\n"
4858  " ON c.casttarget = tt.oid\n"
4859  " LEFT JOIN pg_catalog.pg_namespace nt\n"
4860  " ON nt.oid = tt.typnamespace\n");
4861 
4862  if (verbose)
4864  " LEFT JOIN pg_catalog.pg_description d\n"
4865  " ON d.classoid = c.tableoid AND d.objoid = "
4866  "c.oid AND d.objsubid = 0\n");
4867 
4868  appendPQExpBufferStr(&buf, "WHERE ( (true");
4869 
4870  /*
4871  * Match name pattern against either internal or external name of either
4872  * castsource or casttarget
4873  */
4874  if (!validateSQLNamePattern(&buf, pattern, true, false,
4875  "ns.nspname", "ts.typname",
4876  "pg_catalog.format_type(ts.oid, NULL)",
4877  "pg_catalog.pg_type_is_visible(ts.oid)",
4878  NULL, 3))
4879  goto error_return;
4880 
4881  appendPQExpBufferStr(&buf, ") OR (true");
4882 
4883  if (!validateSQLNamePattern(&buf, pattern, true, false,
4884  "nt.nspname", "tt.typname",
4885  "pg_catalog.format_type(tt.oid, NULL)",
4886  "pg_catalog.pg_type_is_visible(tt.oid)",
4887  NULL, 3))
4888  goto error_return;
4889 
4890  appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;");
4891 
4892  res = PSQLexec(buf.data);
4893  termPQExpBuffer(&buf);
4894  if (!res)
4895  return false;
4896 
4897  myopt.title = _("List of casts");
4898  myopt.translate_header = true;
4899  myopt.translate_columns = translate_columns;
4900  myopt.n_translate_columns = lengthof(translate_columns);
4901 
4902  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4903 
4904  PQclear(res);
4905  return true;
4906 
4907 error_return:
4908  termPQExpBuffer(&buf);
4909  return false;
4910 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listCollations()

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

Definition at line 4918 of file describe.c.

4919 {
4921  PGresult *res;
4922  printQueryOpt myopt = pset.popt;
4923  static const bool translate_columns[] = {false, false, false, false, false, false, false, true, false};
4924 
4925  initPQExpBuffer(&buf);
4926 
4928  "SELECT\n"
4929  " n.nspname AS \"%s\",\n"
4930  " c.collname AS \"%s\",\n",
4931  gettext_noop("Schema"),
4932  gettext_noop("Name"));
4933 
4934  if (pset.sversion >= 100000)
4936  " CASE c.collprovider WHEN 'd' THEN 'default' WHEN 'b' THEN 'builtin' WHEN 'c' THEN 'libc' WHEN 'i' THEN 'icu' END AS \"%s\",\n",
4937  gettext_noop("Provider"));
4938  else
4940  " 'libc' AS \"%s\",\n",
4941  gettext_noop("Provider"));
4942 
4944  " c.collcollate AS \"%s\",\n"
4945  " c.collctype AS \"%s\",\n",
4946  gettext_noop("Collate"),
4947  gettext_noop("Ctype"));
4948 
4949  if (pset.sversion >= 170000)
4951  " c.colllocale AS \"%s\",\n",
4952  gettext_noop("Locale"));
4953  else if (pset.sversion >= 150000)
4955  " c.colliculocale AS \"%s\",\n",
4956  gettext_noop("Locale"));
4957  else
4959  " c.collcollate AS \"%s\",\n",
4960  gettext_noop("Locale"));
4961 
4962  if (pset.sversion >= 160000)
4964  " c.collicurules AS \"%s\",\n",
4965  gettext_noop("ICU Rules"));
4966  else
4968  " NULL AS \"%s\",\n",
4969  gettext_noop("ICU Rules"));
4970 
4971  if (pset.sversion >= 120000)
4973  " CASE WHEN c.collisdeterministic THEN '%s' ELSE '%s' END AS \"%s\"",
4974  gettext_noop("yes"), gettext_noop("no"),
4975  gettext_noop("Deterministic?"));
4976  else
4978  " '%s' AS \"%s\"",
4979  gettext_noop("yes"),
4980  gettext_noop("Deterministic?"));
4981 
4982  if (verbose)
4984  ",\n pg_catalog.obj_description(c.oid, 'pg_collation') AS \"%s\"",
4985  gettext_noop("Description"));
4986 
4988  "\nFROM pg_catalog.pg_collation c, pg_catalog.pg_namespace n\n"
4989  "WHERE n.oid = c.collnamespace\n");
4990 
4991  if (!showSystem && !pattern)
4992  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4993  " AND n.nspname <> 'information_schema'\n");
4994 
4995  /*
4996  * Hide collations that aren't usable in the current database's encoding.
4997  * If you think to change this, note that pg_collation_is_visible rejects
4998  * unusable collations, so you will need to hack name pattern processing
4999  * somehow to avoid inconsistent behavior.
5000  */
5001  appendPQExpBufferStr(&buf, " AND c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))\n");
5002 
5003  if (!validateSQLNamePattern(&buf, pattern, true, false,
5004  "n.nspname", "c.collname", NULL,
5005  "pg_catalog.pg_collation_is_visible(c.oid)",
5006  NULL, 3))
5007  {
5008  termPQExpBuffer(&buf);
5009  return false;
5010  }
5011 
5012  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5013 
5014  res = PSQLexec(buf.data);
5015  termPQExpBuffer(&buf);
5016  if (!res)
5017  return false;
5018 
5019  myopt.title = _("List of collations");
5020  myopt.translate_header = true;
5021  myopt.translate_columns = translate_columns;
5022  myopt.n_translate_columns = lengthof(translate_columns);
5023 
5024  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5025 
5026  PQclear(res);
5027  return true;
5028 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listConversions()

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

Definition at line 4476 of file describe.c.

4477 {
4479  PGresult *res;
4480  printQueryOpt myopt = pset.popt;
4481  static const bool translate_columns[] =
4482  {false, false, false, false, true, false};
4483 
4484  initPQExpBuffer(&buf);
4485 
4487  "SELECT n.nspname AS \"%s\",\n"
4488  " c.conname AS \"%s\",\n"
4489  " pg_catalog.pg_encoding_to_char(c.conforencoding) AS \"%s\",\n"
4490  " pg_catalog.pg_encoding_to_char(c.contoencoding) AS \"%s\",\n"
4491  " CASE WHEN c.condefault THEN '%s'\n"
4492  " ELSE '%s' END AS \"%s\"",
4493  gettext_noop("Schema"),
4494  gettext_noop("Name"),
4495  gettext_noop("Source"),
4496  gettext_noop("Destination"),
4497  gettext_noop("yes"), gettext_noop("no"),
4498  gettext_noop("Default?"));
4499 
4500  if (verbose)
4502  ",\n d.description AS \"%s\"",
4503  gettext_noop("Description"));
4504 
4506  "\nFROM pg_catalog.pg_conversion c\n"
4507  " JOIN pg_catalog.pg_namespace n "
4508  "ON n.oid = c.connamespace\n");
4509 
4510  if (verbose)
4512  "LEFT JOIN pg_catalog.pg_description d "
4513  "ON d.classoid = c.tableoid\n"
4514  " AND d.objoid = c.oid "
4515  "AND d.objsubid = 0\n");
4516 
4517  appendPQExpBufferStr(&buf, "WHERE true\n");
4518 
4519  if (!showSystem && !pattern)
4520  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4521  " AND n.nspname <> 'information_schema'\n");
4522 
4523  if (!validateSQLNamePattern(&buf, pattern, true, false,
4524  "n.nspname", "c.conname", NULL,
4525  "pg_catalog.pg_conversion_is_visible(c.oid)",
4526  NULL, 3))
4527  {
4528  termPQExpBuffer(&buf);
4529  return false;
4530  }
4531 
4532  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4533 
4534  res = PSQLexec(buf.data);
4535  termPQExpBuffer(&buf);
4536  if (!res)
4537  return false;
4538 
4539  myopt.title = _("List of conversions");
4540  myopt.translate_header = true;
4541  myopt.translate_columns = translate_columns;
4542  myopt.n_translate_columns = lengthof(translate_columns);
4543 
4544  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4545 
4546  PQclear(res);
4547  return true;
4548 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listDbRoleSettings()

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

Definition at line 3761 of file describe.c.

3762 {
3764  PGresult *res;
3765  printQueryOpt myopt = pset.popt;
3766  bool havewhere;
3767 
3768  initPQExpBuffer(&buf);
3769 
3770  printfPQExpBuffer(&buf, "SELECT rolname AS \"%s\", datname AS \"%s\",\n"
3771  "pg_catalog.array_to_string(setconfig, E'\\n') AS \"%s\"\n"
3772  "FROM pg_catalog.pg_db_role_setting s\n"
3773  "LEFT JOIN pg_catalog.pg_database d ON d.oid = setdatabase\n"
3774  "LEFT JOIN pg_catalog.pg_roles r ON r.oid = setrole\n",
3775  gettext_noop("Role"),
3776  gettext_noop("Database"),
3777  gettext_noop("Settings"));
3778  if (!validateSQLNamePattern(&buf, pattern, false, false,
3779  NULL, "r.rolname", NULL, NULL, &havewhere, 1))
3780  goto error_return;
3781  if (!validateSQLNamePattern(&buf, pattern2, havewhere, false,
3782  NULL, "d.datname", NULL, NULL,
3783  NULL, 1))
3784  goto error_return;
3785  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
3786 
3787  res = PSQLexec(buf.data);
3788  termPQExpBuffer(&buf);
3789  if (!res)
3790  return false;
3791 
3792  /*
3793  * Most functions in this file are content to print an empty table when
3794  * there are no matching objects. We intentionally deviate from that
3795  * here, but only in !quiet mode, because of the possibility that the user
3796  * is confused about what the two pattern arguments mean.
3797  */
3798  if (PQntuples(res) == 0 && !pset.quiet)
3799  {
3800  if (pattern && pattern2)
3801  pg_log_error("Did not find any settings for role \"%s\" and database \"%s\".",
3802  pattern, pattern2);
3803  else if (pattern)
3804  pg_log_error("Did not find any settings for role \"%s\".",
3805  pattern);
3806  else
3807  pg_log_error("Did not find any settings.");
3808  }
3809  else
3810  {
3811  myopt.title = _("List of settings");
3812  myopt.translate_header = true;
3813 
3814  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
3815  }
3816 
3817  PQclear(res);
3818  return true;
3819 
3820 error_return:
3821  termPQExpBuffer(&buf);
3822  return false;
3823 }

References _, appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, pg_log_error, _psqlSettings::popt, PQclear(), PQntuples(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::quiet, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, and validateSQLNamePattern().

Referenced by exec_command_d().

◆ listDefaultACLs()

bool listDefaultACLs ( const char *  pattern)

Definition at line 1175 of file describe.c.

1176 {
1178  PGresult *res;
1179  printQueryOpt myopt = pset.popt;
1180  static const bool translate_columns[] = {false, false, true, false};
1181 
1182  initPQExpBuffer(&buf);
1183 
1185  "SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS \"%s\",\n"
1186  " n.nspname AS \"%s\",\n"
1187  " 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"
1188  " ",
1189  gettext_noop("Owner"),
1190  gettext_noop("Schema"),
1191  DEFACLOBJ_RELATION,
1192  gettext_noop("table"),
1193  DEFACLOBJ_SEQUENCE,
1194  gettext_noop("sequence"),
1195  DEFACLOBJ_FUNCTION,
1196  gettext_noop("function"),
1197  DEFACLOBJ_TYPE,
1198  gettext_noop("type"),
1199  DEFACLOBJ_NAMESPACE,
1200  gettext_noop("schema"),
1201  gettext_noop("Type"));
1202 
1203  printACLColumn(&buf, "d.defaclacl");
1204 
1205  appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_default_acl d\n"
1206  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.defaclnamespace\n");
1207 
1208  if (!validateSQLNamePattern(&buf, pattern, false, false,
1209  NULL,
1210  "n.nspname",
1211  "pg_catalog.pg_get_userbyid(d.defaclrole)",
1212  NULL,
1213  NULL, 3))
1214  goto error_return;
1215 
1216  appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
1217 
1218  res = PSQLexec(buf.data);
1219  if (!res)
1220  goto error_return;
1221 
1222  printfPQExpBuffer(&buf, _("Default access privileges"));
1223  myopt.title = buf.data;
1224  myopt.translate_header = true;
1225  myopt.translate_columns = translate_columns;
1226  myopt.n_translate_columns = lengthof(translate_columns);
1227 
1228  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1229 
1230  termPQExpBuffer(&buf);
1231  PQclear(res);
1232  return true;
1233 
1234 error_return:
1235  termPQExpBuffer(&buf);
1236  return false;
1237 }

References _, appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, and validateSQLNamePattern().

Referenced by exec_command_d().

◆ listDomains()

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

Definition at line 4393 of file describe.c.

4394 {
4396  PGresult *res;
4397  printQueryOpt myopt = pset.popt;
4398 
4399  initPQExpBuffer(&buf);
4400 
4402  "SELECT n.nspname as \"%s\",\n"
4403  " t.typname as \"%s\",\n"
4404  " pg_catalog.format_type(t.typbasetype, t.typtypmod) as \"%s\",\n"
4405  " (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type bt\n"
4406  " WHERE c.oid = t.typcollation AND bt.oid = t.typbasetype AND t.typcollation <> bt.typcollation) as \"%s\",\n"
4407  " CASE WHEN t.typnotnull THEN 'not null' END as \"%s\",\n"
4408  " t.typdefault as \"%s\",\n"
4409  " pg_catalog.array_to_string(ARRAY(\n"
4410  " SELECT pg_catalog.pg_get_constraintdef(r.oid, true) FROM pg_catalog.pg_constraint r WHERE t.oid = r.contypid AND r.contype = 'c' ORDER BY r.conname\n"
4411  " ), ' ') as \"%s\"",
4412  gettext_noop("Schema"),
4413  gettext_noop("Name"),
4414  gettext_noop("Type"),
4415  gettext_noop("Collation"),
4416  gettext_noop("Nullable"),
4417  gettext_noop("Default"),
4418  gettext_noop("Check"));
4419 
4420  if (verbose)
4421  {
4422  appendPQExpBufferStr(&buf, ",\n ");
4423  printACLColumn(&buf, "t.typacl");
4425  ",\n d.description as \"%s\"",
4426  gettext_noop("Description"));
4427  }
4428 
4430  "\nFROM pg_catalog.pg_type t\n"
4431  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
4432 
4433  if (verbose)
4435  " LEFT JOIN pg_catalog.pg_description d "
4436  "ON d.classoid = t.tableoid AND d.objoid = t.oid "
4437  "AND d.objsubid = 0\n");
4438 
4439  appendPQExpBufferStr(&buf, "WHERE t.typtype = 'd'\n");
4440 
4441  if (!showSystem && !pattern)
4442  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4443  " AND n.nspname <> 'information_schema'\n");
4444 
4445  if (!validateSQLNamePattern(&buf, pattern, true, false,
4446  "n.nspname", "t.typname", NULL,
4447  "pg_catalog.pg_type_is_visible(t.oid)",
4448  NULL, 3))
4449  {
4450  termPQExpBuffer(&buf);
4451  return false;
4452  }
4453 
4454  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4455 
4456  res = PSQLexec(buf.data);
4457  termPQExpBuffer(&buf);
4458  if (!res)
4459  return false;
4460 
4461  myopt.title = _("List of domains");
4462  myopt.translate_header = true;
4463 
4464  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4465 
4466  PQclear(res);
4467  return true;
4468 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listEventTriggers()

bool listEventTriggers ( const char *  pattern,
bool  verbose 
)

Definition at line 4624 of file describe.c.

4625 {
4627  PGresult *res;
4628  printQueryOpt myopt = pset.popt;
4629  static const bool translate_columns[] =
4630  {false, false, false, true, false, false, false};
4631 
4632  if (pset.sversion < 90300)
4633  {
4634  char sverbuf[32];
4635 
4636  pg_log_error("The server (version %s) does not support event triggers.",
4638  sverbuf, sizeof(sverbuf)));
4639  return true;
4640  }
4641 
4642  initPQExpBuffer(&buf);
4643 
4645  "SELECT evtname as \"%s\", "
4646  "evtevent as \"%s\", "
4647  "pg_catalog.pg_get_userbyid(e.evtowner) as \"%s\",\n"
4648  " case evtenabled when 'O' then '%s'"
4649  " when 'R' then '%s'"
4650  " when 'A' then '%s'"
4651  " when 'D' then '%s' end as \"%s\",\n"
4652  " e.evtfoid::pg_catalog.regproc as \"%s\", "
4653  "pg_catalog.array_to_string(array(select x"
4654  " from pg_catalog.unnest(evttags) as t(x)), ', ') as \"%s\"",
4655  gettext_noop("Name"),
4656  gettext_noop("Event"),
4657  gettext_noop("Owner"),
4658  gettext_noop("enabled"),
4659  gettext_noop("replica"),
4660  gettext_noop("always"),
4661  gettext_noop("disabled"),
4662  gettext_noop("Enabled"),
4663  gettext_noop("Function"),
4664  gettext_noop("Tags"));
4665  if (verbose)
4667  ",\npg_catalog.obj_description(e.oid, 'pg_event_trigger') as \"%s\"",
4668  gettext_noop("Description"));
4670  "\nFROM pg_catalog.pg_event_trigger e ");
4671 
4672  if (!validateSQLNamePattern(&buf, pattern, false, false,
4673  NULL, "evtname", NULL, NULL,
4674  NULL, 1))
4675  {
4676  termPQExpBuffer(&buf);
4677  return false;
4678  }
4679 
4680  appendPQExpBufferStr(&buf, "ORDER BY 1");
4681 
4682  res = PSQLexec(buf.data);
4683  termPQExpBuffer(&buf);
4684  if (!res)
4685  return false;
4686 
4687  myopt.title = _("List of event triggers");
4688  myopt.translate_header = true;
4689  myopt.translate_columns = translate_columns;
4690  myopt.n_translate_columns = lengthof(translate_columns);
4691 
4692  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4693 
4694  PQclear(res);
4695  return true;
4696 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, pg_log_error, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listExtendedStats()

bool listExtendedStats ( const char *  pattern)

Definition at line 4704 of file describe.c.

4705 {
4707  PGresult *res;
4708  printQueryOpt myopt = pset.popt;
4709 
4710  if (pset.sversion < 100000)
4711  {
4712  char sverbuf[32];
4713 
4714  pg_log_error("The server (version %s) does not support extended statistics.",
4716  sverbuf, sizeof(sverbuf)));
4717  return true;
4718  }
4719 
4720  initPQExpBuffer(&buf);
4722  "SELECT \n"
4723  "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text AS \"%s\", \n"
4724  "es.stxname AS \"%s\", \n",
4725  gettext_noop("Schema"),
4726  gettext_noop("Name"));
4727 
4728  if (pset.sversion >= 140000)
4730  "pg_catalog.format('%%s FROM %%s', \n"
4731  " pg_catalog.pg_get_statisticsobjdef_columns(es.oid), \n"
4732  " es.stxrelid::pg_catalog.regclass) AS \"%s\"",
4733  gettext_noop("Definition"));
4734  else
4736  "pg_catalog.format('%%s FROM %%s', \n"
4737  " (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(a.attname),', ') \n"
4738  " FROM pg_catalog.unnest(es.stxkeys) s(attnum) \n"
4739  " JOIN pg_catalog.pg_attribute a \n"
4740  " ON (es.stxrelid = a.attrelid \n"
4741  " AND a.attnum = s.attnum \n"
4742  " AND NOT a.attisdropped)), \n"
4743  "es.stxrelid::pg_catalog.regclass) AS \"%s\"",
4744  gettext_noop("Definition"));
4745 
4747  ",\nCASE WHEN 'd' = any(es.stxkind) THEN 'defined' \n"
4748  "END AS \"%s\", \n"
4749  "CASE WHEN 'f' = any(es.stxkind) THEN 'defined' \n"
4750  "END AS \"%s\"",
4751  gettext_noop("Ndistinct"),
4752  gettext_noop("Dependencies"));
4753 
4754  /*
4755  * Include the MCV statistics kind.
4756  */
4757  if (pset.sversion >= 120000)
4758  {
4760  ",\nCASE WHEN 'm' = any(es.stxkind) THEN 'defined' \n"
4761  "END AS \"%s\" ",
4762  gettext_noop("MCV"));
4763  }
4764 
4766  " \nFROM pg_catalog.pg_statistic_ext es \n");
4767 
4768  if (!validateSQLNamePattern(&buf, pattern,
4769  false, false,
4770  "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text", "es.stxname",
4771  NULL, "pg_catalog.pg_statistics_obj_is_visible(es.oid)",
4772  NULL, 3))
4773  {
4774  termPQExpBuffer(&buf);
4775  return false;
4776  }
4777 
4778  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4779 
4780  res = PSQLexec(buf.data);
4781  termPQExpBuffer(&buf);
4782  if (!res)
4783  return false;
4784 
4785  myopt.title = _("List of extended statistics");
4786  myopt.translate_header = true;
4787 
4788  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4789 
4790  PQclear(res);
4791  return true;
4792 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, pg_log_error, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, and validateSQLNamePattern().

Referenced by exec_command_d().

◆ listExtensionContents()

bool listExtensionContents ( const char *  pattern)

Definition at line 6063 of file describe.c.

6064 {
6066  PGresult *res;
6067  int i;
6068 
6069  initPQExpBuffer(&buf);
6071  "SELECT e.extname, e.oid\n"
6072  "FROM pg_catalog.pg_extension e\n");
6073 
6074  if (!validateSQLNamePattern(&buf, pattern,
6075  false, false,
6076  NULL, "e.extname", NULL,
6077  NULL,
6078  NULL, 1))
6079  {
6080  termPQExpBuffer(&buf);
6081  return false;
6082  }
6083 
6084  appendPQExpBufferStr(&buf, "ORDER BY 1;");
6085 
6086  res = PSQLexec(buf.data);
6087  termPQExpBuffer(&buf);
6088  if (!res)
6089  return false;
6090 
6091  if (PQntuples(res) == 0)
6092  {
6093  if (!pset.quiet)
6094  {
6095  if (pattern)
6096  pg_log_error("Did not find any extension named \"%s\".",
6097  pattern);
6098  else
6099  pg_log_error("Did not find any extensions.");
6100  }
6101  PQclear(res);
6102  return false;
6103  }
6104 
6105  for (i = 0; i < PQntuples(res); i++)
6106  {
6107  const char *extname;
6108  const char *oid;
6109 
6110  extname = PQgetvalue(res, i, 0);
6111  oid = PQgetvalue(res, i, 1);
6112 
6113  if (!listOneExtensionContents(extname, oid))
6114  {
6115  PQclear(res);
6116  return false;
6117  }
6118  if (cancel_pressed)
6119  {
6120  PQclear(res);
6121  return false;
6122  }
6123  }
6124 
6125  PQclear(res);
6126  return true;
6127 }
static bool listOneExtensionContents(const char *extname, const char *oid)
Definition: describe.c:6130

References appendPQExpBufferStr(), buf, cancel_pressed, i, initPQExpBuffer(), listOneExtensionContents(), pg_log_error, PQclear(), PQgetvalue(), PQntuples(), printfPQExpBuffer(), pset, PSQLexec(), _psqlSettings::quiet, res, termPQExpBuffer(), and validateSQLNamePattern().

Referenced by exec_command_d().

◆ listExtensions()

bool listExtensions ( const char *  pattern)

Definition at line 6012 of file describe.c.

6013 {
6015  PGresult *res;
6016  printQueryOpt myopt = pset.popt;
6017 
6018  initPQExpBuffer(&buf);
6020  "SELECT e.extname AS \"%s\", "
6021  "e.extversion AS \"%s\", n.nspname AS \"%s\", c.description AS \"%s\"\n"
6022  "FROM pg_catalog.pg_extension e "
6023  "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace "
6024  "LEFT JOIN pg_catalog.pg_description c ON c.objoid = e.oid "
6025  "AND c.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass\n",
6026  gettext_noop("Name"),
6027  gettext_noop("Version"),
6028  gettext_noop("Schema"),
6029  gettext_noop("Description"));
6030 
6031  if (!validateSQLNamePattern(&buf, pattern,
6032  false, false,
6033  NULL, "e.extname", NULL,
6034  NULL,
6035  NULL, 1))
6036  {
6037  termPQExpBuffer(&buf);
6038  return false;
6039  }
6040 
6041  appendPQExpBufferStr(&buf, "ORDER BY 1;");
6042 
6043  res = PSQLexec(buf.data);
6044  termPQExpBuffer(&buf);
6045  if (!res)
6046  return false;
6047 
6048  myopt.title = _("List of installed extensions");
6049  myopt.translate_header = true;
6050 
6051  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6052 
6053  PQclear(res);
6054  return true;
6055 }

References _, appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, and validateSQLNamePattern().

Referenced by exec_command_d().

◆ listForeignDataWrappers()

bool listForeignDataWrappers ( const char *  pattern,
bool  verbose 
)

Definition at line 5738 of file describe.c.

5739 {
5741  PGresult *res;
5742  printQueryOpt myopt = pset.popt;
5743 
5744  initPQExpBuffer(&buf);
5746  "SELECT fdw.fdwname AS \"%s\",\n"
5747  " pg_catalog.pg_get_userbyid(fdw.fdwowner) AS \"%s\",\n"
5748  " fdw.fdwhandler::pg_catalog.regproc AS \"%s\",\n"
5749  " fdw.fdwvalidator::pg_catalog.regproc AS \"%s\"",
5750  gettext_noop("Name"),
5751  gettext_noop("Owner"),
5752  gettext_noop("Handler"),
5753  gettext_noop("Validator"));
5754 
5755  if (verbose)
5756  {
5757  appendPQExpBufferStr(&buf, ",\n ");
5758  printACLColumn(&buf, "fdwacl");
5760  ",\n CASE WHEN fdwoptions IS NULL THEN '' ELSE "
5761  " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
5762  " pg_catalog.quote_ident(option_name) || ' ' || "
5763  " pg_catalog.quote_literal(option_value) FROM "
5764  " pg_catalog.pg_options_to_table(fdwoptions)), ', ') || ')' "
5765  " END AS \"%s\""
5766  ",\n d.description AS \"%s\" ",
5767  gettext_noop("FDW options"),
5768  gettext_noop("Description"));
5769  }
5770 
5771  appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
5772 
5773  if (verbose)
5775  "LEFT JOIN pg_catalog.pg_description d\n"
5776  " ON d.classoid = fdw.tableoid "
5777  "AND d.objoid = fdw.oid AND d.objsubid = 0\n");
5778 
5779  if (!validateSQLNamePattern(&buf, pattern, false, false,
5780  NULL, "fdwname", NULL, NULL,
5781  NULL, 1))
5782  {
5783  termPQExpBuffer(&buf);
5784  return false;
5785  }
5786 
5787  appendPQExpBufferStr(&buf, "ORDER BY 1;");
5788 
5789  res = PSQLexec(buf.data);
5790  termPQExpBuffer(&buf);
5791  if (!res)
5792  return false;
5793 
5794  myopt.title = _("List of foreign-data wrappers");
5795  myopt.translate_header = true;
5796 
5797  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5798 
5799  PQclear(res);
5800  return true;
5801 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listForeignServers()

bool listForeignServers ( const char *  pattern,
bool  verbose 
)

Definition at line 5809 of file describe.c.

5810 {
5812  PGresult *res;
5813  printQueryOpt myopt = pset.popt;
5814 
5815  initPQExpBuffer(&buf);
5817  "SELECT s.srvname AS \"%s\",\n"
5818  " pg_catalog.pg_get_userbyid(s.srvowner) AS \"%s\",\n"
5819  " f.fdwname AS \"%s\"",
5820  gettext_noop("Name"),
5821  gettext_noop("Owner"),
5822  gettext_noop("Foreign-data wrapper"));
5823 
5824  if (verbose)
5825  {
5826  appendPQExpBufferStr(&buf, ",\n ");
5827  printACLColumn(&buf, "s.srvacl");
5829  ",\n"
5830  " s.srvtype AS \"%s\",\n"
5831  " s.srvversion AS \"%s\",\n"
5832  " CASE WHEN srvoptions IS NULL THEN '' ELSE "
5833  " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
5834  " pg_catalog.quote_ident(option_name) || ' ' || "
5835  " pg_catalog.quote_literal(option_value) FROM "
5836  " pg_catalog.pg_options_to_table(srvoptions)), ', ') || ')' "
5837  " END AS \"%s\",\n"
5838  " d.description AS \"%s\"",
5839  gettext_noop("Type"),
5840  gettext_noop("Version"),
5841  gettext_noop("FDW options"),
5842  gettext_noop("Description"));
5843  }
5844 
5846  "\nFROM pg_catalog.pg_foreign_server s\n"
5847  " JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid=s.srvfdw\n");
5848 
5849  if (verbose)
5851  "LEFT JOIN pg_catalog.pg_description d\n "
5852  "ON d.classoid = s.tableoid AND d.objoid = s.oid "
5853  "AND d.objsubid = 0\n");
5854 
5855  if (!validateSQLNamePattern(&buf, pattern, false, false,
5856  NULL, "s.srvname", NULL, NULL,
5857  NULL, 1))
5858  {
5859  termPQExpBuffer(&buf);
5860  return false;
5861  }
5862 
5863  appendPQExpBufferStr(&buf, "ORDER BY 1;");
5864 
5865  res = PSQLexec(buf.data);
5866  termPQExpBuffer(&buf);
5867  if (!res)
5868  return false;
5869 
5870  myopt.title = _("List of foreign servers");
5871  myopt.translate_header = true;
5872 
5873  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5874 
5875  PQclear(res);
5876  return true;
5877 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listForeignTables()

bool listForeignTables ( const char *  pattern,
bool  verbose 
)

Definition at line 5940 of file describe.c.

5941 {
5943  PGresult *res;
5944  printQueryOpt myopt = pset.popt;
5945 
5946  initPQExpBuffer(&buf);
5948  "SELECT n.nspname AS \"%s\",\n"
5949  " c.relname AS \"%s\",\n"
5950  " s.srvname AS \"%s\"",
5951  gettext_noop("Schema"),
5952  gettext_noop("Table"),
5953  gettext_noop("Server"));
5954 
5955  if (verbose)
5957  ",\n CASE WHEN ftoptions IS NULL THEN '' ELSE "
5958  " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
5959  " pg_catalog.quote_ident(option_name) || ' ' || "
5960  " pg_catalog.quote_literal(option_value) FROM "
5961  " pg_catalog.pg_options_to_table(ftoptions)), ', ') || ')' "
5962  " END AS \"%s\",\n"
5963  " d.description AS \"%s\"",
5964  gettext_noop("FDW options"),
5965  gettext_noop("Description"));
5966 
5968  "\nFROM pg_catalog.pg_foreign_table ft\n"
5969  " INNER JOIN pg_catalog.pg_class c"
5970  " ON c.oid = ft.ftrelid\n"
5971  " INNER JOIN pg_catalog.pg_namespace n"
5972  " ON n.oid = c.relnamespace\n"
5973  " INNER JOIN pg_catalog.pg_foreign_server s"
5974  " ON s.oid = ft.ftserver\n");
5975  if (verbose)
5977  " LEFT JOIN pg_catalog.pg_description d\n"
5978  " ON d.classoid = c.tableoid AND "
5979  "d.objoid = c.oid AND d.objsubid = 0\n");
5980 
5981  if (!validateSQLNamePattern(&buf, pattern, false, false,
5982  "n.nspname", "c.relname", NULL,
5983  "pg_catalog.pg_table_is_visible(c.oid)",
5984  NULL, 3))
5985  {
5986  termPQExpBuffer(&buf);
5987  return false;
5988  }
5989 
5990  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5991 
5992  res = PSQLexec(buf.data);
5993  termPQExpBuffer(&buf);
5994  if (!res)
5995  return false;
5996 
5997  myopt.title = _("List of foreign tables");
5998  myopt.translate_header = true;
5999 
6000  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6001 
6002  PQclear(res);
6003  return true;
6004 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listLanguages()

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

Definition at line 4317 of file describe.c.

4318 {
4320  PGresult *res;
4321  printQueryOpt myopt = pset.popt;
4322 
4323  initPQExpBuffer(&buf);
4324 
4326  "SELECT l.lanname AS \"%s\",\n"
4327  " pg_catalog.pg_get_userbyid(l.lanowner) as \"%s\",\n"
4328  " l.lanpltrusted AS \"%s\"",
4329  gettext_noop("Name"),
4330  gettext_noop("Owner"),
4331  gettext_noop("Trusted"));
4332 
4333  if (verbose)
4334  {
4336  ",\n NOT l.lanispl AS \"%s\",\n"
4337  " l.lanplcallfoid::pg_catalog.regprocedure AS \"%s\",\n"
4338  " l.lanvalidator::pg_catalog.regprocedure AS \"%s\",\n "
4339  "l.laninline::pg_catalog.regprocedure AS \"%s\",\n ",
4340  gettext_noop("Internal language"),
4341  gettext_noop("Call handler"),
4342  gettext_noop("Validator"),
4343  gettext_noop("Inline handler"));
4344  printACLColumn(&buf, "l.lanacl");
4345  }
4346 
4348  ",\n d.description AS \"%s\""
4349  "\nFROM pg_catalog.pg_language l\n"
4350  "LEFT JOIN pg_catalog.pg_description d\n"
4351  " ON d.classoid = l.tableoid AND d.objoid = l.oid\n"
4352  " AND d.objsubid = 0\n",
4353  gettext_noop("Description"));
4354 
4355  if (pattern)
4356  {
4357  if (!validateSQLNamePattern(&buf, pattern, false, false,
4358  NULL, "l.lanname", NULL, NULL,
4359  NULL, 2))
4360  {
4361  termPQExpBuffer(&buf);
4362  return false;
4363  }
4364  }
4365 
4366  if (!showSystem && !pattern)
4367  appendPQExpBufferStr(&buf, "WHERE l.lanplcallfoid != 0\n");
4368 
4369 
4370  appendPQExpBufferStr(&buf, "ORDER BY 1;");
4371 
4372  res = PSQLexec(buf.data);
4373  termPQExpBuffer(&buf);
4374  if (!res)
4375  return false;
4376 
4377  myopt.title = _("List of languages");
4378  myopt.translate_header = true;
4379 
4380  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4381 
4382  PQclear(res);
4383  return true;
4384 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listLargeObjects()

bool listLargeObjects ( bool  verbose)

Definition at line 7064 of file describe.c.

7065 {
7067  PGresult *res;
7068  printQueryOpt myopt = pset.popt;
7069 
7070  initPQExpBuffer(&buf);
7071 
7073  "SELECT oid as \"%s\",\n"
7074  " pg_catalog.pg_get_userbyid(lomowner) as \"%s\",\n ",
7075  gettext_noop("ID"),
7076  gettext_noop("Owner"));
7077 
7078  if (verbose)
7079  {
7080  printACLColumn(&buf, "lomacl");
7081  appendPQExpBufferStr(&buf, ",\n ");
7082  }
7083 
7085  "pg_catalog.obj_description(oid, 'pg_largeobject') as \"%s\"\n"
7086  "FROM pg_catalog.pg_largeobject_metadata\n"
7087  "ORDER BY oid",
7088  gettext_noop("Description"));
7089 
7090  res = PSQLexec(buf.data);
7091  termPQExpBuffer(&buf);
7092  if (!res)
7093  return false;
7094 
7095  myopt.title = _("Large objects");
7096  myopt.translate_header = true;
7097 
7098  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7099 
7100  PQclear(res);
7101  return true;
7102 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, and verbose.

Referenced by exec_command_d(), and exec_command_lo().

◆ listOneExtensionContents()

static bool listOneExtensionContents ( const char *  extname,
const char *  oid 
)
static

Definition at line 6130 of file describe.c.

6131 {
6133  PGresult *res;
6134  PQExpBufferData title;
6135  printQueryOpt myopt = pset.popt;
6136 
6137  initPQExpBuffer(&buf);
6139  "SELECT pg_catalog.pg_describe_object(classid, objid, 0) AS \"%s\"\n"
6140  "FROM pg_catalog.pg_depend\n"
6141  "WHERE refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass AND refobjid = '%s' AND deptype = 'e'\n"
6142  "ORDER BY 1;",
6143  gettext_noop("Object description"),
6144  oid);
6145 
6146  res = PSQLexec(buf.data);
6147  termPQExpBuffer(&buf);
6148  if (!res)
6149  return false;
6150 
6151  initPQExpBuffer(&title);
6152  printfPQExpBuffer(&title, _("Objects in extension \"%s\""), extname);
6153  myopt.title = title.data;
6154  myopt.translate_header = true;
6155 
6156  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6157 
6158  termPQExpBuffer(&title);
6159  PQclear(res);
6160  return true;
6161 }

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

Referenced by listExtensionContents().

◆ listOperatorClasses()

bool listOperatorClasses ( const char *  access_method_pattern,
const char *  type_pattern,
bool  verbose 
)

Definition at line 6687 of file describe.c.

6689 {
6691  PGresult *res;
6692  printQueryOpt myopt = pset.popt;
6693  bool have_where = false;
6694  static const bool translate_columns[] = {false, false, false, false, false, false, false};
6695 
6696  initPQExpBuffer(&buf);
6697 
6699  "SELECT\n"
6700  " am.amname AS \"%s\",\n"
6701  " pg_catalog.format_type(c.opcintype, NULL) AS \"%s\",\n"
6702  " CASE\n"
6703  " WHEN c.opckeytype <> 0 AND c.opckeytype <> c.opcintype\n"
6704  " THEN pg_catalog.format_type(c.opckeytype, NULL)\n"
6705  " ELSE NULL\n"
6706  " END AS \"%s\",\n"
6707  " CASE\n"
6708  " WHEN pg_catalog.pg_opclass_is_visible(c.oid)\n"
6709  " THEN pg_catalog.format('%%I', c.opcname)\n"
6710  " ELSE pg_catalog.format('%%I.%%I', n.nspname, c.opcname)\n"
6711  " END AS \"%s\",\n"
6712  " (CASE WHEN c.opcdefault\n"
6713  " THEN '%s'\n"
6714  " ELSE '%s'\n"
6715  " END) AS \"%s\"",
6716  gettext_noop("AM"),
6717  gettext_noop("Input type"),
6718  gettext_noop("Storage type"),
6719  gettext_noop("Operator class"),
6720  gettext_noop("yes"),
6721  gettext_noop("no"),
6722  gettext_noop("Default?"));
6723  if (verbose)
6725  ",\n CASE\n"
6726  " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
6727  " THEN pg_catalog.format('%%I', of.opfname)\n"
6728  " ELSE pg_catalog.format('%%I.%%I', ofn.nspname, of.opfname)\n"
6729  " END AS \"%s\",\n"
6730  " pg_catalog.pg_get_userbyid(c.opcowner) AS \"%s\"\n",
6731  gettext_noop("Operator family"),
6732  gettext_noop("Owner"));
6734  "\nFROM pg_catalog.pg_opclass c\n"
6735  " LEFT JOIN pg_catalog.pg_am am on am.oid = c.opcmethod\n"
6736  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.opcnamespace\n"
6737  " LEFT JOIN pg_catalog.pg_type t ON t.oid = c.opcintype\n"
6738  " LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n");
6739  if (verbose)
6741  " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = c.opcfamily\n"
6742  " LEFT JOIN pg_catalog.pg_namespace ofn ON ofn.oid = of.opfnamespace\n");
6743 
6744  if (access_method_pattern)
6745  if (!validateSQLNamePattern(&buf, access_method_pattern,
6746  false, false, NULL, "am.amname", NULL, NULL,
6747  &have_where, 1))
6748  goto error_return;
6749  if (type_pattern)
6750  {
6751  /* Match type name pattern against either internal or external name */
6752  if (!validateSQLNamePattern(&buf, type_pattern, have_where, false,
6753  "tn.nspname", "t.typname",
6754  "pg_catalog.format_type(t.oid, NULL)",
6755  "pg_catalog.pg_type_is_visible(t.oid)",
6756  NULL, 3))
6757  goto error_return;
6758  }
6759 
6760  appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
6761  res = PSQLexec(buf.data);
6762  termPQExpBuffer(&buf);
6763  if (!res)
6764  return false;
6765 
6766  myopt.title = _("List of operator classes");
6767  myopt.translate_header = true;
6768  myopt.translate_columns = translate_columns;
6769  myopt.n_translate_columns = lengthof(translate_columns);
6770 
6771  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6772 
6773  PQclear(res);
6774  return true;
6775 
6776 error_return:
6777  termPQExpBuffer(&buf);
6778  return false;
6779 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listOperatorFamilies()

bool listOperatorFamilies ( const char *  access_method_pattern,
const char *  type_pattern,
bool  verbose 
)

Definition at line 6788 of file describe.c.

6790 {
6792  PGresult *res;
6793  printQueryOpt myopt = pset.popt;
6794  bool have_where = false;
6795  static const bool translate_columns[] = {false, false, false, false};
6796 
6797  initPQExpBuffer(&buf);
6798 
6800  "SELECT\n"
6801  " am.amname AS \"%s\",\n"
6802  " CASE\n"
6803  " WHEN pg_catalog.pg_opfamily_is_visible(f.oid)\n"
6804  " THEN pg_catalog.format('%%I', f.opfname)\n"
6805  " ELSE pg_catalog.format('%%I.%%I', n.nspname, f.opfname)\n"
6806  " END AS \"%s\",\n"
6807  " (SELECT\n"
6808  " pg_catalog.string_agg(pg_catalog.format_type(oc.opcintype, NULL), ', ')\n"
6809  " FROM pg_catalog.pg_opclass oc\n"
6810  " WHERE oc.opcfamily = f.oid) \"%s\"",
6811  gettext_noop("AM"),
6812  gettext_noop("Operator family"),
6813  gettext_noop("Applicable types"));
6814  if (verbose)
6816  ",\n pg_catalog.pg_get_userbyid(f.opfowner) AS \"%s\"\n",
6817  gettext_noop("Owner"));
6819  "\nFROM pg_catalog.pg_opfamily f\n"
6820  " LEFT JOIN pg_catalog.pg_am am on am.oid = f.opfmethod\n"
6821  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = f.opfnamespace\n");
6822 
6823  if (access_method_pattern)
6824  if (!validateSQLNamePattern(&buf, access_method_pattern,
6825  false, false, NULL, "am.amname", NULL, NULL,
6826  &have_where, 1))
6827  goto error_return;
6828  if (type_pattern)
6829  {
6831  " %s EXISTS (\n"
6832  " SELECT 1\n"
6833  " FROM pg_catalog.pg_type t\n"
6834  " JOIN pg_catalog.pg_opclass oc ON oc.opcintype = t.oid\n"
6835  " LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n"
6836  " WHERE oc.opcfamily = f.oid\n",
6837  have_where ? "AND" : "WHERE");
6838  /* Match type name pattern against either internal or external name */
6839  if (!validateSQLNamePattern(&buf, type_pattern, true, false,
6840  "tn.nspname", "t.typname",
6841  "pg_catalog.format_type(t.oid, NULL)",
6842  "pg_catalog.pg_type_is_visible(t.oid)",
6843  NULL, 3))
6844  goto error_return;
6845  appendPQExpBufferStr(&buf, " )\n");
6846  }
6847 
6848  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
6849  res = PSQLexec(buf.data);
6850  termPQExpBuffer(&buf);
6851  if (!res)
6852  return false;
6853 
6854  myopt.title = _("List of operator families");
6855  myopt.translate_header = true;
6856  myopt.translate_columns = translate_columns;
6857  myopt.n_translate_columns = lengthof(translate_columns);
6858 
6859  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6860 
6861  PQclear(res);
6862  return true;
6863 
6864 error_return:
6865  termPQExpBuffer(&buf);
6866  return false;
6867 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listOpFamilyFunctions()

bool listOpFamilyFunctions ( const char *  access_method_pattern,
const char *  family_pattern,
bool  verbose 
)

Definition at line 6975 of file describe.c.

6977 {
6979  PGresult *res;
6980  printQueryOpt myopt = pset.popt;
6981  bool have_where = false;
6982  static const bool translate_columns[] = {false, false, false, false, false, false};
6983 
6984  initPQExpBuffer(&buf);
6985 
6987  "SELECT\n"
6988  " am.amname AS \"%s\",\n"
6989  " CASE\n"
6990  " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
6991  " THEN pg_catalog.format('%%I', of.opfname)\n"
6992  " ELSE pg_catalog.format('%%I.%%I', ns.nspname, of.opfname)\n"
6993  " END AS \"%s\",\n"
6994  " pg_catalog.format_type(ap.amproclefttype, NULL) AS \"%s\",\n"
6995  " pg_catalog.format_type(ap.amprocrighttype, NULL) AS \"%s\",\n"
6996  " ap.amprocnum AS \"%s\"\n",
6997  gettext_noop("AM"),
6998  gettext_noop("Operator family"),
6999  gettext_noop("Registered left type"),
7000  gettext_noop("Registered right type"),
7001  gettext_noop("Number"));
7002 
7003  if (!verbose)
7005  ", p.proname AS \"%s\"\n",
7006  gettext_noop("Function"));
7007  else
7009  ", ap.amproc::pg_catalog.regprocedure AS \"%s\"\n",
7010  gettext_noop("Function"));
7011 
7013  "FROM pg_catalog.pg_amproc ap\n"
7014  " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = ap.amprocfamily\n"
7015  " LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod\n"
7016  " LEFT JOIN pg_catalog.pg_namespace ns ON of.opfnamespace = ns.oid\n"
7017  " LEFT JOIN pg_catalog.pg_proc p ON ap.amproc = p.oid\n");
7018 
7019  if (access_method_pattern)
7020  {
7021  if (!validateSQLNamePattern(&buf, access_method_pattern,
7022  false, false, NULL, "am.amname",
7023  NULL, NULL,
7024  &have_where, 1))
7025  goto error_return;
7026  }
7027  if (family_pattern)
7028  {
7029  if (!validateSQLNamePattern(&buf, family_pattern, have_where, false,
7030  "ns.nspname", "of.opfname", NULL, NULL,
7031  NULL, 3))
7032  goto error_return;
7033  }
7034 
7035  appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
7036  " ap.amproclefttype = ap.amprocrighttype DESC,\n"
7037  " 3, 4, 5;");
7038 
7039  res = PSQLexec(buf.data);
7040  termPQExpBuffer(&buf);
7041  if (!res)
7042  return false;
7043 
7044  myopt.title = _("List of support functions of operator families");
7045  myopt.translate_header = true;
7046  myopt.translate_columns = translate_columns;
7047  myopt.n_translate_columns = lengthof(translate_columns);
7048 
7049  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7050 
7051  PQclear(res);
7052  return true;
7053 
7054 error_return:
7055  termPQExpBuffer(&buf);
7056  return false;
7057 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listOpFamilyOperators()

bool listOpFamilyOperators ( const char *  access_method_pattern,
const char *  family_pattern,
bool  verbose 
)

Definition at line 6877 of file describe.c.

6879 {
6881  PGresult *res;
6882  printQueryOpt myopt = pset.popt;
6883  bool have_where = false;
6884 
6885  static const bool translate_columns[] = {false, false, false, false, false, false};
6886 
6887  initPQExpBuffer(&buf);
6888 
6890  "SELECT\n"
6891  " am.amname AS \"%s\",\n"
6892  " CASE\n"
6893  " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
6894  " THEN pg_catalog.format('%%I', of.opfname)\n"
6895  " ELSE pg_catalog.format('%%I.%%I', nsf.nspname, of.opfname)\n"
6896  " END AS \"%s\",\n"
6897  " o.amopopr::pg_catalog.regoperator AS \"%s\"\n,"
6898  " o.amopstrategy AS \"%s\",\n"
6899  " CASE o.amoppurpose\n"
6900  " WHEN 'o' THEN '%s'\n"
6901  " WHEN 's' THEN '%s'\n"
6902  " END AS \"%s\"\n",
6903  gettext_noop("AM"),
6904  gettext_noop("Operator family"),
6905  gettext_noop("Operator"),
6906  gettext_noop("Strategy"),
6907  gettext_noop("ordering"),
6908  gettext_noop("search"),
6909  gettext_noop("Purpose"));
6910 
6911  if (verbose)
6913  ", ofs.opfname AS \"%s\"\n",
6914  gettext_noop("Sort opfamily"));
6916  "FROM pg_catalog.pg_amop o\n"
6917  " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = o.amopfamily\n"
6918  " LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod AND am.oid = o.amopmethod\n"
6919  " LEFT JOIN pg_catalog.pg_namespace nsf ON of.opfnamespace = nsf.oid\n");
6920  if (verbose)
6922  " LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n");
6923 
6924  if (access_method_pattern)
6925  {
6926  if (!validateSQLNamePattern(&buf, access_method_pattern,
6927  false, false, NULL, "am.amname",
6928  NULL, NULL,
6929  &have_where, 1))
6930  goto error_return;
6931  }
6932 
6933  if (family_pattern)
6934  {
6935  if (!validateSQLNamePattern(&buf, family_pattern, have_where, false,
6936  "nsf.nspname", "of.opfname", NULL, NULL,
6937  NULL, 3))
6938  goto error_return;
6939  }
6940 
6941  appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
6942  " o.amoplefttype = o.amoprighttype DESC,\n"
6943  " pg_catalog.format_type(o.amoplefttype, NULL),\n"
6944  " pg_catalog.format_type(o.amoprighttype, NULL),\n"
6945  " o.amopstrategy;");
6946 
6947  res = PSQLexec(buf.data);
6948  termPQExpBuffer(&buf);
6949  if (!res)
6950  return false;
6951 
6952  myopt.title = _("List of operators of operator families");
6953  myopt.translate_header = true;
6954  myopt.translate_columns = translate_columns;
6955  myopt.n_translate_columns = lengthof(translate_columns);
6956 
6957  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6958 
6959  PQclear(res);
6960  return true;
6961 
6962 error_return:
6963  termPQExpBuffer(&buf);
6964  return false;
6965 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listPartitionedTables()

bool listPartitionedTables ( const char *  reltypes,
const char *  pattern,
bool  verbose 
)

Definition at line 4107 of file describe.c.

4108 {
4109  bool showTables = strchr(reltypes, 't') != NULL;
4110  bool showIndexes = strchr(reltypes, 'i') != NULL;
4111  bool showNested = strchr(reltypes, 'n') != NULL;
4113  PQExpBufferData title;
4114  PGresult *res;
4115  printQueryOpt myopt = pset.popt;
4116  bool translate_columns[] = {false, false, false, false, false, false, false, false, false, false};
4117  const char *tabletitle;
4118  bool mixed_output = false;
4119 
4120  /*
4121  * Note: Declarative table partitioning is only supported as of Pg 10.0.
4122  */
4123  if (pset.sversion < 100000)
4124  {
4125  char sverbuf[32];
4126 
4127  pg_log_error("The server (version %s) does not support declarative table partitioning.",
4129  sverbuf, sizeof(sverbuf)));
4130  return true;
4131  }
4132 
4133  /* If no relation kind was selected, show them all */
4134  if (!showTables && !showIndexes)
4135  showTables = showIndexes = true;
4136 
4137  if (showIndexes && !showTables)
4138  tabletitle = _("List of partitioned indexes"); /* \dPi */
4139  else if (showTables && !showIndexes)
4140  tabletitle = _("List of partitioned tables"); /* \dPt */
4141  else
4142  {
4143  /* show all kinds */
4144  tabletitle = _("List of partitioned relations");
4145  mixed_output = true;
4146  }
4147 
4148  initPQExpBuffer(&buf);
4149 
4151  "SELECT n.nspname as \"%s\",\n"
4152  " c.relname as \"%s\",\n"
4153  " pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"",
4154  gettext_noop("Schema"),
4155  gettext_noop("Name"),
4156  gettext_noop("Owner"));
4157 
4158  if (mixed_output)
4159  {
4161  ",\n CASE c.relkind"
4162  " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
4163  " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
4164  " END as \"%s\"",
4165  gettext_noop("partitioned table"),
4166  gettext_noop("partitioned index"),
4167  gettext_noop("Type"));
4168 
4169  translate_columns[3] = true;
4170  }
4171 
4172  if (showNested || pattern)
4174  ",\n inh.inhparent::pg_catalog.regclass as \"%s\"",
4175  gettext_noop("Parent name"));
4176 
4177  if (showIndexes)
4179  ",\n c2.oid::pg_catalog.regclass as \"%s\"",
4180  gettext_noop("Table"));
4181 
4182  if (verbose)
4183  {
4184  /*
4185  * Table access methods were introduced in v12, and can be set on
4186  * partitioned tables since v17.
4187  */
4188  appendPQExpBuffer(&buf, ",\n am.amname as \"%s\"",
4189  gettext_noop("Access method"));
4190 
4191  if (showNested)
4192  {
4194  ",\n s.dps as \"%s\"",
4195  gettext_noop("Leaf partition size"));
4197  ",\n s.tps as \"%s\"",
4198  gettext_noop("Total size"));
4199  }
4200  else
4201  /* Sizes of all partitions are considered in this case. */
4203  ",\n s.tps as \"%s\"",
4204  gettext_noop("Total size"));
4205 
4207  ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"",
4208  gettext_noop("Description"));
4209  }
4210 
4212  "\nFROM pg_catalog.pg_class c"
4213  "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace");
4214 
4215  if (showIndexes)
4217  "\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid"
4218  "\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid");
4219 
4220  if (showNested || pattern)
4222  "\n LEFT JOIN pg_catalog.pg_inherits inh ON c.oid = inh.inhrelid");
4223 
4224  if (verbose)
4225  {
4227  "\n LEFT JOIN pg_catalog.pg_am am ON c.relam = am.oid");
4228 
4229  if (pset.sversion < 120000)
4230  {
4232  ",\n LATERAL (WITH RECURSIVE d\n"
4233  " AS (SELECT inhrelid AS oid, 1 AS level\n"
4234  " FROM pg_catalog.pg_inherits\n"
4235  " WHERE inhparent = c.oid\n"
4236  " UNION ALL\n"
4237  " SELECT inhrelid, level + 1\n"
4238  " FROM pg_catalog.pg_inherits i\n"
4239  " JOIN d ON i.inhparent = d.oid)\n"
4240  " SELECT pg_catalog.pg_size_pretty(sum(pg_catalog.pg_table_size("
4241  "d.oid))) AS tps,\n"
4242  " pg_catalog.pg_size_pretty(sum("
4243  "\n CASE WHEN d.level = 1"
4244  " THEN pg_catalog.pg_table_size(d.oid) ELSE 0 END)) AS dps\n"
4245  " FROM d) s");
4246  }
4247  else
4248  {
4249  /* PostgreSQL 12 has pg_partition_tree function */
4251  ",\n LATERAL (SELECT pg_catalog.pg_size_pretty(sum("
4252  "\n CASE WHEN ppt.isleaf AND ppt.level = 1"
4253  "\n THEN pg_catalog.pg_table_size(ppt.relid)"
4254  " ELSE 0 END)) AS dps"
4255  ",\n pg_catalog.pg_size_pretty(sum("
4256  "pg_catalog.pg_table_size(ppt.relid))) AS tps"
4257  "\n FROM pg_catalog.pg_partition_tree(c.oid) ppt) s");
4258  }
4259  }
4260 
4261  appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
4262  if (showTables)
4263  appendPQExpBufferStr(&buf, CppAsString2(RELKIND_PARTITIONED_TABLE) ",");
4264  if (showIndexes)
4265  appendPQExpBufferStr(&buf, CppAsString2(RELKIND_PARTITIONED_INDEX) ",");
4266  appendPQExpBufferStr(&buf, "''"); /* dummy */
4267  appendPQExpBufferStr(&buf, ")\n");
4268 
4269  appendPQExpBufferStr(&buf, !showNested && !pattern ?
4270  " AND NOT c.relispartition\n" : "");
4271 
4272  if (!pattern)
4273  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4274  " AND n.nspname !~ '^pg_toast'\n"
4275  " AND n.nspname <> 'information_schema'\n");
4276 
4277  if (!validateSQLNamePattern(&buf, pattern, true, false,
4278  "n.nspname", "c.relname", NULL,
4279  "pg_catalog.pg_table_is_visible(c.oid)",
4280  NULL, 3))
4281  {
4282  termPQExpBuffer(&buf);
4283  return false;
4284  }
4285 
4286  appendPQExpBuffer(&buf, "ORDER BY \"Schema\", %s%s\"Name\";",
4287  mixed_output ? "\"Type\" DESC, " : "",
4288  showNested || pattern ? "\"Parent name\" NULLS FIRST, " : "");
4289 
4290  res = PSQLexec(buf.data);
4291  termPQExpBuffer(&buf);
4292  if (!res)
4293  return false;
4294 
4295  initPQExpBuffer(&title);
4296  appendPQExpBufferStr(&title, tabletitle);
4297 
4298  myopt.title = title.data;
4299  myopt.translate_header = true;
4300  myopt.translate_columns = translate_columns;
4301  myopt.n_translate_columns = lengthof(translate_columns);
4302 
4303  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4304 
4305  termPQExpBuffer(&title);
4306 
4307  PQclear(res);
4308  return true;
4309 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, PQExpBufferData::data, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, pg_log_error, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listPublications()

bool listPublications ( const char *  pattern)

Definition at line 6227 of file describe.c.

6228 {
6230  PGresult *res;
6231  printQueryOpt myopt = pset.popt;
6232  static const bool translate_columns[] = {false, false, false, false, false, false, false, false};
6233 
6234  if (pset.sversion < 100000)
6235  {
6236  char sverbuf[32];
6237 
6238  pg_log_error("The server (version %s) does not support publications.",
6240  sverbuf, sizeof(sverbuf)));
6241  return true;
6242  }
6243 
6244  initPQExpBuffer(&buf);
6245 
6247  "SELECT pubname AS \"%s\",\n"
6248  " pg_catalog.pg_get_userbyid(pubowner) AS \"%s\",\n"
6249  " puballtables AS \"%s\",\n"
6250  " pubinsert AS \"%s\",\n"
6251  " pubupdate AS \"%s\",\n"
6252  " pubdelete AS \"%s\"",
6253  gettext_noop("Name"),
6254  gettext_noop("Owner"),
6255  gettext_noop("All tables"),
6256  gettext_noop("Inserts"),
6257  gettext_noop("Updates"),
6258  gettext_noop("Deletes"));
6259  if (pset.sversion >= 110000)
6261  ",\n pubtruncate AS \"%s\"",
6262  gettext_noop("Truncates"));
6263  if (pset.sversion >= 130000)
6265  ",\n pubviaroot AS \"%s\"",
6266  gettext_noop("Via root"));
6267 
6269  "\nFROM pg_catalog.pg_publication\n");
6270 
6271  if (!validateSQLNamePattern(&buf, pattern, false, false,
6272  NULL, "pubname", NULL,
6273  NULL,
6274  NULL, 1))
6275  {
6276  termPQExpBuffer(&buf);
6277  return false;
6278  }
6279 
6280  appendPQExpBufferStr(&buf, "ORDER BY 1;");
6281 
6282  res = PSQLexec(buf.data);
6283  termPQExpBuffer(&buf);
6284  if (!res)
6285  return false;
6286 
6287  myopt.title = _("List of publications");
6288  myopt.translate_header = true;
6289  myopt.translate_columns = translate_columns;
6290  myopt.n_translate_columns = lengthof(translate_columns);
6291 
6292  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6293 
6294  PQclear(res);
6295 
6296  return true;
6297 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, pg_log_error, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, and validateSQLNamePattern().

Referenced by exec_command_d().

◆ listSchemas()

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

Definition at line 5036 of file describe.c.

5037 {
5039  PGresult *res;
5040  printQueryOpt myopt = pset.popt;
5041  int pub_schema_tuples = 0;
5042  char **footers = NULL;
5043 
5044  initPQExpBuffer(&buf);
5046  "SELECT n.nspname AS \"%s\",\n"
5047  " pg_catalog.pg_get_userbyid(n.nspowner) AS \"%s\"",
5048  gettext_noop("Name"),
5049  gettext_noop("Owner"));
5050 
5051  if (verbose)
5052  {
5053  appendPQExpBufferStr(&buf, ",\n ");
5054  printACLColumn(&buf, "n.nspacl");
5056  ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"",
5057  gettext_noop("Description"));
5058  }
5059 
5061  "\nFROM pg_catalog.pg_namespace n\n");
5062 
5063  if (!showSystem && !pattern)
5065  "WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'\n");
5066 
5067  if (!validateSQLNamePattern(&buf, pattern,
5068  !showSystem && !pattern, false,
5069  NULL, "n.nspname", NULL,
5070  NULL,
5071  NULL, 2))
5072  goto error_return;
5073 
5074  appendPQExpBufferStr(&buf, "ORDER BY 1;");
5075 
5076  res = PSQLexec(buf.data);
5077  if (!res)
5078  goto error_return;
5079 
5080  myopt.title = _("List of schemas");
5081  myopt.translate_header = true;
5082 
5083  if (pattern && pset.sversion >= 150000)
5084  {
5085  PGresult *result;
5086  int i;
5087 
5089  "SELECT pubname \n"
5090  "FROM pg_catalog.pg_publication p\n"
5091  " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
5092  " JOIN pg_catalog.pg_namespace n ON n.oid = pn.pnnspid \n"
5093  "WHERE n.nspname = '%s'\n"
5094  "ORDER BY 1",
5095  pattern);
5096  result = PSQLexec(buf.data);
5097  if (!result)
5098  goto error_return;
5099  else
5100  pub_schema_tuples = PQntuples(result);
5101 
5102  if (pub_schema_tuples > 0)
5103  {
5104  /*
5105  * Allocate memory for footers. Size of footers will be 1 (for
5106  * storing "Publications:" string) + publication schema mapping
5107  * count + 1 (for storing NULL).
5108  */
5109  footers = (char **) pg_malloc((1 + pub_schema_tuples + 1) * sizeof(char *));
5110  footers[0] = pg_strdup(_("Publications:"));
5111 
5112  /* Might be an empty set - that's ok */
5113  for (i = 0; i < pub_schema_tuples; i++)
5114  {
5115  printfPQExpBuffer(&buf, " \"%s\"",
5116  PQgetvalue(result, i, 0));
5117 
5118  footers[i + 1] = pg_strdup(buf.data);
5119  }
5120 
5121  footers[i + 1] = NULL;
5122  myopt.footers = footers;
5123  }
5124 
5125  PQclear(result);
5126  }
5127 
5128  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5129 
5130  termPQExpBuffer(&buf);
5131  PQclear(res);
5132 
5133  /* Free the memory allocated for the footer */
5134  if (footers)
5135  {
5136  char **footer = NULL;
5137 
5138  for (footer = footers; *footer; footer++)
5139  pg_free(*footer);
5140 
5141  pg_free(footers);
5142  }
5143 
5144  return true;
5145 
5146 error_return:
5147  termPQExpBuffer(&buf);
5148  return false;
5149 }
void pg_free(void *ptr)
Definition: fe_memutils.c:105
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, printQueryOpt::footers, gettext_noop, i, initPQExpBuffer(), _psqlSettings::logfile, pg_free(), pg_malloc(), pg_strdup(), _psqlSettings::popt, PQclear(), PQgetvalue(), PQntuples(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listTables()

bool listTables ( const char *  tabtypes,
const char *  pattern,
bool  verbose,
bool  showSystem 
)

Definition at line 3909 of file describe.c.

3910 {
3911  bool showTables = strchr(tabtypes, 't') != NULL;
3912  bool showIndexes = strchr(tabtypes, 'i') != NULL;
3913  bool showViews = strchr(tabtypes, 'v') != NULL;
3914  bool showMatViews = strchr(tabtypes, 'm') != NULL;
3915  bool showSeq = strchr(tabtypes, 's') != NULL;
3916  bool showForeign = strchr(tabtypes, 'E') != NULL;
3917 
3919  PGresult *res;
3920  printQueryOpt myopt = pset.popt;
3921  int cols_so_far;
3922  bool translate_columns[] = {false, false, true, false, false, false, false, false, false};
3923 
3924  /* If tabtypes is empty, we default to \dtvmsE (but see also command.c) */
3925  if (!(showTables || showIndexes || showViews || showMatViews || showSeq || showForeign))
3926  showTables = showViews = showMatViews = showSeq = showForeign = true;
3927 
3928  initPQExpBuffer(&buf);
3929 
3931  "SELECT n.nspname as \"%s\",\n"
3932  " c.relname as \"%s\",\n"
3933  " CASE c.relkind"
3934  " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'"
3935  " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'"
3936  " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'"
3937  " WHEN " CppAsString2(RELKIND_INDEX) " THEN '%s'"
3938  " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'"
3939  " WHEN " CppAsString2(RELKIND_TOASTVALUE) " THEN '%s'"
3940  " WHEN " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN '%s'"
3941  " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
3942  " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
3943  " END as \"%s\",\n"
3944  " pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"",
3945  gettext_noop("Schema"),
3946  gettext_noop("Name"),
3947  gettext_noop("table"),
3948  gettext_noop("view"),
3949  gettext_noop("materialized view"),
3950  gettext_noop("index"),
3951  gettext_noop("sequence"),
3952  gettext_noop("TOAST table"),
3953  gettext_noop("foreign table"),
3954  gettext_noop("partitioned table"),
3955  gettext_noop("partitioned index"),
3956  gettext_noop("Type"),
3957  gettext_noop("Owner"));
3958  cols_so_far = 4;
3959 
3960  if (showIndexes)
3961  {
3963  ",\n c2.relname as \"%s\"",
3964  gettext_noop("Table"));
3965  cols_so_far++;
3966  }
3967 
3968  if (verbose)
3969  {
3970  /*
3971  * Show whether a relation is permanent, temporary, or unlogged.
3972  */
3974  ",\n CASE c.relpersistence WHEN 'p' THEN '%s' WHEN 't' THEN '%s' WHEN 'u' THEN '%s' END as \"%s\"",
3975  gettext_noop("permanent"),
3976  gettext_noop("temporary"),
3977  gettext_noop("unlogged"),
3978  gettext_noop("Persistence"));
3979  translate_columns[cols_so_far] = true;
3980 
3981  /*
3982  * We don't bother to count cols_so_far below here, as there's no need
3983  * to; this might change with future additions to the output columns.
3984  */
3985 
3986  /*
3987  * Access methods exist for tables, materialized views and indexes.
3988  * This has been introduced in PostgreSQL 12 for tables.
3989  */
3990  if (pset.sversion >= 120000 && !pset.hide_tableam &&
3991  (showTables || showMatViews || showIndexes))
3993  ",\n am.amname as \"%s\"",
3994  gettext_noop("Access method"));
3995 
3997  ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\""
3998  ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"",
3999  gettext_noop("Size"),
4000  gettext_noop("Description"));
4001  }
4002 
4004  "\nFROM pg_catalog.pg_class c"
4005  "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace");
4006 
4007  if (pset.sversion >= 120000 && !pset.hide_tableam &&
4008  (showTables || showMatViews || showIndexes))
4010  "\n LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam");
4011 
4012  if (showIndexes)
4014  "\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid"
4015  "\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid");
4016 
4017  appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
4018  if (showTables)
4019  {
4020  appendPQExpBufferStr(&buf, CppAsString2(RELKIND_RELATION) ","
4021  CppAsString2(RELKIND_PARTITIONED_TABLE) ",");
4022  /* with 'S' or a pattern, allow 't' to match TOAST tables too */
4023  if (showSystem || pattern)
4024  appendPQExpBufferStr(&buf, CppAsString2(RELKIND_TOASTVALUE) ",");
4025  }
4026  if (showViews)
4027  appendPQExpBufferStr(&buf, CppAsString2(RELKIND_VIEW) ",");
4028  if (showMatViews)
4029  appendPQExpBufferStr(&buf, CppAsString2(RELKIND_MATVIEW) ",");
4030  if (showIndexes)
4031  appendPQExpBufferStr(&buf, CppAsString2(RELKIND_INDEX) ","
4032  CppAsString2(RELKIND_PARTITIONED_INDEX) ",");
4033  if (showSeq)
4034  appendPQExpBufferStr(&buf, CppAsString2(RELKIND_SEQUENCE) ",");
4035  if (showSystem || pattern)
4036  appendPQExpBufferStr(&buf, "'s',"); /* was RELKIND_SPECIAL */
4037  if (showForeign)
4038  appendPQExpBufferStr(&buf, CppAsString2(RELKIND_FOREIGN_TABLE) ",");
4039 
4040  appendPQExpBufferStr(&buf, "''"); /* dummy */
4041  appendPQExpBufferStr(&buf, ")\n");
4042 
4043  if (!showSystem && !pattern)
4044  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4045  " AND n.nspname !~ '^pg_toast'\n"
4046  " AND n.nspname <> 'information_schema'\n");
4047 
4048  if (!validateSQLNamePattern(&buf, pattern, true, false,
4049  "n.nspname", "c.relname", NULL,
4050  "pg_catalog.pg_table_is_visible(c.oid)",
4051  NULL, 3))
4052  {
4053  termPQExpBuffer(&buf);
4054  return false;
4055  }
4056 
4057  appendPQExpBufferStr(&buf, "ORDER BY 1,2;");
4058 
4059  res = PSQLexec(buf.data);
4060  termPQExpBuffer(&buf);
4061  if (!res)
4062  return false;
4063 
4064  /*
4065  * Most functions in this file are content to print an empty table when
4066  * there are no matching objects. We intentionally deviate from that
4067  * here, but only in !quiet mode, for historical reasons.
4068  */
4069  if (PQntuples(res) == 0 && !pset.quiet)
4070  {
4071  if (pattern)
4072  pg_log_error("Did not find any relation named \"%s\".",
4073  pattern);
4074  else
4075  pg_log_error("Did not find any relations.");
4076  }
4077  else
4078  {
4079  myopt.title = _("List of relations");
4080  myopt.translate_header = true;
4081  myopt.translate_columns = translate_columns;
4082  myopt.n_translate_columns = lengthof(translate_columns);
4083 
4084  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4085  }
4086 
4087  PQclear(res);
4088  return true;
4089 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, gettext_noop, _psqlSettings::hide_tableam, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, pg_log_error, _psqlSettings::popt, PQclear(), PQntuples(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::quiet, res, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listTSConfigs()

bool listTSConfigs ( const char *  pattern,
bool  verbose 
)

Definition at line 5534 of file describe.c.

5535 {
5537  PGresult *res;
5538  printQueryOpt myopt = pset.popt;
5539 
5540  if (verbose)
5541  return listTSConfigsVerbose(pattern);
5542 
5543  initPQExpBuffer(&buf);
5544 
5546  "SELECT\n"
5547  " n.nspname as \"%s\",\n"
5548  " c.cfgname as \"%s\",\n"
5549  " pg_catalog.obj_description(c.oid, 'pg_ts_config') as \"%s\"\n"
5550  "FROM pg_catalog.pg_ts_config c\n"
5551  "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace\n",
5552  gettext_noop("Schema"),
5553  gettext_noop("Name"),
5554  gettext_noop("Description")
5555  );
5556 
5557  if (!validateSQLNamePattern(&buf, pattern, false, false,
5558  "n.nspname", "c.cfgname", NULL,
5559  "pg_catalog.pg_ts_config_is_visible(c.oid)",
5560  NULL, 3))
5561  {
5562  termPQExpBuffer(&buf);
5563  return false;
5564  }
5565 
5566  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5567 
5568  res = PSQLexec(buf.data);
5569  termPQExpBuffer(&buf);
5570  if (!res)
5571  return false;
5572 
5573  myopt.title = _("List of text search configurations");
5574  myopt.translate_header = true;
5575 
5576  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5577 
5578  PQclear(res);
5579  return true;
5580 }
static bool listTSConfigsVerbose(const char *pattern)
Definition: describe.c:5583

References _, appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), listTSConfigsVerbose(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listTSConfigsVerbose()

static bool listTSConfigsVerbose ( const char *  pattern)
static

Definition at line 5583 of file describe.c.

5584 {
5586  PGresult *res;
5587  int i;
5588 
5589  initPQExpBuffer(&buf);
5590 
5592  "SELECT c.oid, c.cfgname,\n"
5593  " n.nspname,\n"
5594  " p.prsname,\n"
5595  " np.nspname as pnspname\n"
5596  "FROM pg_catalog.pg_ts_config c\n"
5597  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace,\n"
5598  " pg_catalog.pg_ts_parser p\n"
5599  " LEFT JOIN pg_catalog.pg_namespace np ON np.oid = p.prsnamespace\n"
5600  "WHERE p.oid = c.cfgparser\n"
5601  );
5602 
5603  if (!validateSQLNamePattern(&buf, pattern, true, false,
5604  "n.nspname", "c.cfgname", NULL,
5605  "pg_catalog.pg_ts_config_is_visible(c.oid)",
5606  NULL, 3))
5607  {
5608  termPQExpBuffer(&buf);
5609  return false;
5610  }
5611 
5612  appendPQExpBufferStr(&buf, "ORDER BY 3, 2;");
5613 
5614  res = PSQLexec(buf.data);
5615  termPQExpBuffer(&buf);
5616  if (!res)
5617  return false;
5618 
5619  if (PQntuples(res) == 0)
5620  {
5621  if (!pset.quiet)
5622  {
5623  if (pattern)
5624  pg_log_error("Did not find any text search configuration named \"%s\".",
5625  pattern);
5626  else
5627  pg_log_error("Did not find any text search configurations.");
5628  }
5629  PQclear(res);
5630  return false;
5631  }
5632 
5633  for (i = 0; i < PQntuples(res); i++)
5634  {
5635  const char *oid;
5636  const char *cfgname;
5637  const char *nspname = NULL;
5638  const char *prsname;
5639  const char *pnspname = NULL;
5640 
5641  oid = PQgetvalue(res, i, 0);
5642  cfgname = PQgetvalue(res, i, 1);
5643  if (!PQgetisnull(res, i, 2))
5644  nspname = PQgetvalue(res, i, 2);
5645  prsname = PQgetvalue(res, i, 3);
5646  if (!PQgetisnull(res, i, 4))
5647  pnspname = PQgetvalue(res, i, 4);
5648 
5649  if (!describeOneTSConfig(oid, nspname, cfgname, pnspname, prsname))
5650  {
5651  PQclear(res);
5652  return false;
5653  }
5654 
5655  if (cancel_pressed)
5656  {
5657  PQclear(res);
5658  return false;
5659  }
5660  }
5661 
5662  PQclear(res);
5663  return true;
5664 }
static bool describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname, const char *pnspname, const char *prsname)
Definition: describe.c:5667

References appendPQExpBufferStr(), buf, cancel_pressed, describeOneTSConfig(), i, initPQExpBuffer(), pg_log_error, PQclear(), PQgetisnull(), PQgetvalue(), PQntuples(), printfPQExpBuffer(), pset, PSQLexec(), _psqlSettings::quiet, res, termPQExpBuffer(), and validateSQLNamePattern().

Referenced by listTSConfigs().

◆ listTSDictionaries()

bool listTSDictionaries ( const char *  pattern,
bool  verbose 
)

Definition at line 5404 of file describe.c.

5405 {
5407  PGresult *res;
5408  printQueryOpt myopt = pset.popt;
5409 
5410  initPQExpBuffer(&buf);
5411 
5413  "SELECT\n"
5414  " n.nspname as \"%s\",\n"
5415  " d.dictname as \"%s\",\n",
5416  gettext_noop("Schema"),
5417  gettext_noop("Name"));
5418 
5419  if (verbose)
5420  {
5422  " ( SELECT COALESCE(nt.nspname, '(null)')::pg_catalog.text || '.' || t.tmplname FROM\n"
5423  " pg_catalog.pg_ts_template t\n"
5424  " LEFT JOIN pg_catalog.pg_namespace nt ON nt.oid = t.tmplnamespace\n"
5425  " WHERE d.dicttemplate = t.oid ) AS \"%s\",\n"
5426  " d.dictinitoption as \"%s\",\n",
5427  gettext_noop("Template"),
5428  gettext_noop("Init options"));
5429  }
5430 
5432  " pg_catalog.obj_description(d.oid, 'pg_ts_dict') as \"%s\"\n",
5433  gettext_noop("Description"));
5434 
5435  appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_dict d\n"
5436  "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace\n");
5437 
5438  if (!validateSQLNamePattern(&buf, pattern, false, false,
5439  "n.nspname", "d.dictname", NULL,
5440  "pg_catalog.pg_ts_dict_is_visible(d.oid)",
5441  NULL, 3))
5442  {
5443  termPQExpBuffer(&buf);
5444  return false;
5445  }
5446 
5447  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5448 
5449  res = PSQLexec(buf.data);
5450  termPQExpBuffer(&buf);
5451  if (!res)
5452  return false;
5453 
5454  myopt.title = _("List of text search dictionaries");
5455  myopt.translate_header = true;
5456 
5457  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5458 
5459  PQclear(res);
5460  return true;
5461 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listTSParsers()

bool listTSParsers ( const char *  pattern,
bool  verbose 
)

Definition at line 5157 of file describe.c.

5158 {
5160  PGresult *res;
5161  printQueryOpt myopt = pset.popt;
5162 
5163  if (verbose)
5164  return listTSParsersVerbose(pattern);
5165 
5166  initPQExpBuffer(&buf);
5167 
5169  "SELECT\n"
5170  " n.nspname as \"%s\",\n"
5171  " p.prsname as \"%s\",\n"
5172  " pg_catalog.obj_description(p.oid, 'pg_ts_parser') as \"%s\"\n"
5173  "FROM pg_catalog.pg_ts_parser p\n"
5174  "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n",
5175  gettext_noop("Schema"),
5176  gettext_noop("Name"),
5177  gettext_noop("Description")
5178  );
5179 
5180  if (!validateSQLNamePattern(&buf, pattern, false, false,
5181  "n.nspname", "p.prsname", NULL,
5182  "pg_catalog.pg_ts_parser_is_visible(p.oid)",
5183  NULL, 3))
5184  {
5185  termPQExpBuffer(&buf);
5186  return false;
5187  }
5188 
5189  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5190 
5191  res = PSQLexec(buf.data);
5192  termPQExpBuffer(&buf);
5193  if (!res)
5194  return false;
5195 
5196  myopt.title = _("List of text search parsers");
5197  myopt.translate_header = true;
5198 
5199  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5200 
5201  PQclear(res);
5202  return true;
5203 }
static bool listTSParsersVerbose(const char *pattern)
Definition: describe.c:5209

References _, appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), listTSParsersVerbose(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listTSParsersVerbose()

static bool listTSParsersVerbose ( const char *  pattern)
static

Definition at line 5209 of file describe.c.

5210 {
5212  PGresult *res;
5213  int i;
5214 
5215  initPQExpBuffer(&buf);
5216 
5218  "SELECT p.oid,\n"
5219  " n.nspname,\n"
5220  " p.prsname\n"
5221  "FROM pg_catalog.pg_ts_parser p\n"
5222  "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n"
5223  );
5224 
5225  if (!validateSQLNamePattern(&buf, pattern, false, false,
5226  "n.nspname", "p.prsname", NULL,
5227  "pg_catalog.pg_ts_parser_is_visible(p.oid)",
5228  NULL, 3))
5229  {
5230  termPQExpBuffer(&buf);
5231  return false;
5232  }
5233 
5234  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5235 
5236  res = PSQLexec(buf.data);
5237  termPQExpBuffer(&buf);
5238  if (!res)
5239  return false;
5240 
5241  if (PQntuples(res) == 0)
5242  {
5243  if (!pset.quiet)
5244  {
5245  if (pattern)
5246  pg_log_error("Did not find any text search parser named \"%s\".",
5247  pattern);
5248  else
5249  pg_log_error("Did not find any text search parsers.");
5250  }
5251  PQclear(res);
5252  return false;
5253  }
5254 
5255  for (i = 0; i < PQntuples(res); i++)
5256  {
5257  const char *oid;
5258  const char *nspname = NULL;
5259  const char *prsname;
5260 
5261  oid = PQgetvalue(res, i, 0);
5262  if (!PQgetisnull(res, i, 1))
5263  nspname = PQgetvalue(res, i, 1);
5264  prsname = PQgetvalue(res, i, 2);
5265 
5266  if (!describeOneTSParser(oid, nspname, prsname))
5267  {
5268  PQclear(res);
5269  return false;
5270  }
5271 
5272  if (cancel_pressed)
5273  {
5274  PQclear(res);
5275  return false;
5276  }
5277  }
5278 
5279  PQclear(res);
5280  return true;
5281 }
static bool describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
Definition: describe.c:5284

References appendPQExpBufferStr(), buf, cancel_pressed, describeOneTSParser(), i, initPQExpBuffer(), pg_log_error, PQclear(), PQgetisnull(), PQgetvalue(), PQntuples(), printfPQExpBuffer(), pset, PSQLexec(), _psqlSettings::quiet, res, termPQExpBuffer(), and validateSQLNamePattern().

Referenced by listTSParsers().

◆ listTSTemplates()

bool listTSTemplates ( const char *  pattern,
bool  verbose 
)

Definition at line 5469 of file describe.c.

5470 {
5472  PGresult *res;
5473  printQueryOpt myopt = pset.popt;
5474 
5475  initPQExpBuffer(&buf);
5476 
5477  if (verbose)
5479  "SELECT\n"
5480  " n.nspname AS \"%s\",\n"
5481  " t.tmplname AS \"%s\",\n"
5482  " t.tmplinit::pg_catalog.regproc AS \"%s\",\n"
5483  " t.tmpllexize::pg_catalog.regproc AS \"%s\",\n"
5484  " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
5485  gettext_noop("Schema"),
5486  gettext_noop("Name"),
5487  gettext_noop("Init"),
5488  gettext_noop("Lexize"),
5489  gettext_noop("Description"));
5490  else
5492  "SELECT\n"
5493  " n.nspname AS \"%s\",\n"
5494  " t.tmplname AS \"%s\",\n"
5495  " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
5496  gettext_noop("Schema"),
5497  gettext_noop("Name"),
5498  gettext_noop("Description"));
5499 
5500  appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_template t\n"
5501  "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.tmplnamespace\n");
5502 
5503  if (!validateSQLNamePattern(&buf, pattern, false, false,
5504  "n.nspname", "t.tmplname", NULL,
5505  "pg_catalog.pg_ts_template_is_visible(t.oid)",
5506  NULL, 3))
5507  {
5508  termPQExpBuffer(&buf);
5509  return false;
5510  }
5511 
5512  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5513 
5514  res = PSQLexec(buf.data);
5515  termPQExpBuffer(&buf);
5516  if (!res)
5517  return false;
5518 
5519  myopt.title = _("List of text search templates");
5520  myopt.translate_header = true;
5521 
5522  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5523 
5524  PQclear(res);
5525  return true;
5526 }

References _, appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listUserMappings()

bool listUserMappings ( const char *  pattern,
bool  verbose 
)

Definition at line 5885 of file describe.c.

5886 {
5888  PGresult *res;
5889  printQueryOpt myopt = pset.popt;
5890 
5891  initPQExpBuffer(&buf);
5893  "SELECT um.srvname AS \"%s\",\n"
5894  " um.usename AS \"%s\"",
5895  gettext_noop("Server"),
5896  gettext_noop("User name"));
5897 
5898  if (verbose)
5900  ",\n CASE WHEN umoptions IS NULL THEN '' ELSE "
5901  " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
5902  " pg_catalog.quote_ident(option_name) || ' ' || "
5903  " pg_catalog.quote_literal(option_value) FROM "
5904  " pg_catalog.pg_options_to_table(umoptions)), ', ') || ')' "
5905  " END AS \"%s\"",
5906  gettext_noop("FDW options"));
5907 
5908  appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_user_mappings um\n");
5909 
5910  if (!validateSQLNamePattern(&buf, pattern, false, false,
5911  NULL, "um.srvname", "um.usename", NULL,
5912  NULL, 1))
5913  {
5914  termPQExpBuffer(&buf);
5915  return false;
5916  }
5917 
5918  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5919 
5920  res = PSQLexec(buf.data);
5921  termPQExpBuffer(&buf);
5922  if (!res)
5923  return false;
5924 
5925  myopt.title = _("List of user mappings");
5926  myopt.translate_header = true;
5927 
5928  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5929 
5930  PQclear(res);
5931  return true;
5932 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_header, validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ map_typename_pattern()

static const char * map_typename_pattern ( const char *  pattern)
static

Definition at line 720 of file describe.c.

721 {
722  static const char *const typename_map[] = {
723  /*
724  * These names are accepted by gram.y, although they are neither the
725  * "real" name seen in pg_type nor the canonical name printed by
726  * format_type().
727  */
728  "decimal", "numeric",
729  "float", "double precision",
730  "int", "integer",
731 
732  /*
733  * We also have to map the array names for cases where the canonical
734  * name is different from what pg_type says.
735  */
736  "bool[]", "boolean[]",
737  "decimal[]", "numeric[]",
738  "float[]", "double precision[]",
739  "float4[]", "real[]",
740  "float8[]", "double precision[]",
741  "int[]", "integer[]",
742  "int2[]", "smallint[]",
743  "int4[]", "integer[]",
744  "int8[]", "bigint[]",
745  "time[]", "time without time zone[]",
746  "timetz[]", "time with time zone[]",
747  "timestamp[]", "timestamp without time zone[]",
748  "timestamptz[]", "timestamp with time zone[]",
749  "varbit[]", "bit varying[]",
750  "varchar[]", "character varying[]",
751  NULL
752  };
753 
754  if (pattern == NULL)
755  return NULL;
756  for (int i = 0; typename_map[i] != NULL; i += 2)
757  {
758  if (pg_strcasecmp(pattern, typename_map[i]) == 0)
759  return typename_map[i + 1];
760  }
761  return pattern;
762 }
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36

References i, and pg_strcasecmp().

Referenced by describeFunctions(), describeOperators(), and describeTypes().

◆ objectDescription()

bool objectDescription ( const char *  pattern,
bool  showSystem 
)

Definition at line 1252 of file describe.c.

1253 {
1255  PGresult *res;
1256  printQueryOpt myopt = pset.popt;
1257  static const bool translate_columns[] = {false, false, true, false};
1258 
1259  initPQExpBuffer(&buf);
1260 
1262  "SELECT DISTINCT tt.nspname AS \"%s\", tt.name AS \"%s\", tt.object AS \"%s\", d.description AS \"%s\"\n"
1263  "FROM (\n",
1264  gettext_noop("Schema"),
1265  gettext_noop("Name"),
1266  gettext_noop("Object"),
1267  gettext_noop("Description"));
1268 
1269  /* Table constraint descriptions */
1271  " SELECT pgc.oid as oid, pgc.tableoid AS tableoid,\n"
1272  " n.nspname as nspname,\n"
1273  " CAST(pgc.conname AS pg_catalog.text) as name,"
1274  " CAST('%s' AS pg_catalog.text) as object\n"
1275  " FROM pg_catalog.pg_constraint pgc\n"
1276  " JOIN pg_catalog.pg_class c "
1277  "ON c.oid = pgc.conrelid\n"
1278  " LEFT JOIN pg_catalog.pg_namespace n "
1279  " ON n.oid = c.relnamespace\n",
1280  gettext_noop("table constraint"));
1281 
1282  if (!showSystem && !pattern)
1283  appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
1284  " AND n.nspname <> 'information_schema'\n");
1285 
1286  if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern,
1287  false, "n.nspname", "pgc.conname", NULL,
1288  "pg_catalog.pg_table_is_visible(c.oid)",
1289  NULL, 3))
1290  goto error_return;
1291 
1292  /* Domain constraint descriptions */
1294  "UNION ALL\n"
1295  " SELECT pgc.oid as oid, pgc.tableoid AS tableoid,\n"
1296  " n.nspname as nspname,\n"
1297  " CAST(pgc.conname AS pg_catalog.text) as name,"
1298  " CAST('%s' AS pg_catalog.text) as object\n"
1299  " FROM pg_catalog.pg_constraint pgc\n"
1300  " JOIN pg_catalog.pg_type t "
1301  "ON t.oid = pgc.contypid\n"
1302  " LEFT JOIN pg_catalog.pg_namespace n "
1303  " ON n.oid = t.typnamespace\n",
1304  gettext_noop("domain constraint"));
1305 
1306  if (!showSystem && !pattern)
1307  appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
1308  " AND n.nspname <> 'information_schema'\n");
1309 
1310  if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern,
1311  false, "n.nspname", "pgc.conname", NULL,
1312  "pg_catalog.pg_type_is_visible(t.oid)",
1313  NULL, 3))
1314  goto error_return;
1315 
1316  /* Operator class descriptions */
1318  "UNION ALL\n"
1319  " SELECT o.oid as oid, o.tableoid as tableoid,\n"
1320  " n.nspname as nspname,\n"
1321  " CAST(o.opcname AS pg_catalog.text) as name,\n"
1322  " CAST('%s' AS pg_catalog.text) as object\n"
1323  " FROM pg_catalog.pg_opclass o\n"
1324  " JOIN pg_catalog.pg_am am ON "
1325  "o.opcmethod = am.oid\n"
1326  " JOIN pg_catalog.pg_namespace n ON "
1327  "n.oid = o.opcnamespace\n",
1328  gettext_noop("operator class"));
1329 
1330  if (!showSystem && !pattern)
1331  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
1332  " AND n.nspname <> 'information_schema'\n");
1333 
1334  if (!validateSQLNamePattern(&buf, pattern, true, false,
1335  "n.nspname", "o.opcname", NULL,
1336  "pg_catalog.pg_opclass_is_visible(o.oid)",
1337  NULL, 3))
1338  goto error_return;
1339 
1340  /* Operator family descriptions */
1342  "UNION ALL\n"
1343  " SELECT opf.oid as oid, opf.tableoid as tableoid,\n"
1344  " n.nspname as nspname,\n"
1345  " CAST(opf.opfname AS pg_catalog.text) AS name,\n"
1346  " CAST('%s' AS pg_catalog.text) as object\n"
1347  " FROM pg_catalog.pg_opfamily opf\n"
1348  " JOIN pg_catalog.pg_am am "
1349  "ON opf.opfmethod = am.oid\n"
1350  " JOIN pg_catalog.pg_namespace n "
1351  "ON opf.opfnamespace = n.oid\n",
1352  gettext_noop("operator family"));
1353 
1354  if (!showSystem && !pattern)
1355  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
1356  " AND n.nspname <> 'information_schema'\n");
1357 
1358  if (!validateSQLNamePattern(&buf, pattern, true, false,
1359  "n.nspname", "opf.opfname", NULL,
1360  "pg_catalog.pg_opfamily_is_visible(opf.oid)",
1361  NULL, 3))
1362  goto error_return;
1363 
1364  /* Rule descriptions (ignore rules for views) */
1366  "UNION ALL\n"
1367  " SELECT r.oid as oid, r.tableoid as tableoid,\n"
1368  " n.nspname as nspname,\n"
1369  " CAST(r.rulename AS pg_catalog.text) as name,"
1370  " CAST('%s' AS pg_catalog.text) as object\n"
1371  " FROM pg_catalog.pg_rewrite r\n"
1372  " JOIN pg_catalog.pg_class c ON c.oid = r.ev_class\n"
1373  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
1374  " WHERE r.rulename != '_RETURN'\n",
1375  gettext_noop("rule"));
1376 
1377  if (!showSystem && !pattern)
1378  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
1379  " AND n.nspname <> 'information_schema'\n");
1380 
1381  if (!validateSQLNamePattern(&buf, pattern, true, false,
1382  "n.nspname", "r.rulename", NULL,
1383  "pg_catalog.pg_table_is_visible(c.oid)",
1384  NULL, 3))
1385  goto error_return;
1386 
1387  /* Trigger descriptions */
1389  "UNION ALL\n"
1390  " SELECT t.oid as oid, t.tableoid as tableoid,\n"
1391  " n.nspname as nspname,\n"
1392  " CAST(t.tgname AS pg_catalog.text) as name,"
1393  " CAST('%s' AS pg_catalog.text) as object\n"
1394  " FROM pg_catalog.pg_trigger t\n"
1395  " JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid\n"
1396  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n",
1397  gettext_noop("trigger"));
1398 
1399  if (!showSystem && !pattern)
1400  appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
1401  " AND n.nspname <> 'information_schema'\n");
1402 
1403  if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern, false,
1404  "n.nspname", "t.tgname", NULL,
1405  "pg_catalog.pg_table_is_visible(c.oid)",
1406  NULL, 3))
1407  goto error_return;
1408 
1410  ") AS tt\n"
1411  " JOIN pg_catalog.pg_description d ON (tt.oid = d.objoid AND tt.tableoid = d.classoid AND d.objsubid = 0)\n");
1412 
1413  appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
1414 
1415  res = PSQLexec(buf.data);
1416  termPQExpBuffer(&buf);
1417  if (!res)
1418  return false;
1419 
1420  myopt.title = _("Object descriptions");
1421  myopt.translate_header = true;
1422  myopt.translate_columns = translate_columns;
1423  myopt.n_translate_columns = lengthof(translate_columns);
1424 
1425  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1426 
1427  PQclear(res);
1428  return true;
1429 
1430 error_return:
1431  termPQExpBuffer(&buf);
1432  return false;
1433 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, and validateSQLNamePattern().

Referenced by exec_command_d().

◆ permissionsList()

bool permissionsList ( const char *  pattern,
bool  showSystem 
)

Definition at line 1011 of file describe.c.

1012 {
1014  PGresult *res;
1015  printQueryOpt myopt = pset.popt;
1016  static const bool translate_columns[] = {false, false, true, false, false, false};
1017 
1018  initPQExpBuffer(&buf);
1019 
1020  /*
1021  * we ignore indexes and toast tables since they have no meaningful rights
1022  */
1024  "SELECT n.nspname as \"%s\",\n"
1025  " c.relname as \"%s\",\n"
1026  " CASE c.relkind"
1027  " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'"
1028  " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'"
1029  " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'"
1030  " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'"
1031  " WHEN " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN '%s'"
1032  " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
1033  " END as \"%s\",\n"
1034  " ",
1035  gettext_noop("Schema"),
1036  gettext_noop("Name"),
1037  gettext_noop("table"),
1038  gettext_noop("view"),
1039  gettext_noop("materialized view"),
1040  gettext_noop("sequence"),
1041  gettext_noop("foreign table"),
1042  gettext_noop("partitioned table"),
1043  gettext_noop("Type"));
1044 
1045  printACLColumn(&buf, "c.relacl");
1046 
1047  /*
1048  * The formatting of attacl should match printACLColumn(). However, we
1049  * need no special case for an empty attacl, because the backend always
1050  * optimizes that back to NULL.
1051  */
1053  ",\n pg_catalog.array_to_string(ARRAY(\n"
1054  " SELECT attname || E':\\n ' || pg_catalog.array_to_string(attacl, E'\\n ')\n"
1055  " FROM pg_catalog.pg_attribute a\n"
1056  " WHERE attrelid = c.oid AND NOT attisdropped AND attacl IS NOT NULL\n"
1057  " ), E'\\n') AS \"%s\"",
1058  gettext_noop("Column privileges"));
1059 
1060  if (pset.sversion >= 90500 && pset.sversion < 100000)
1062  ",\n pg_catalog.array_to_string(ARRAY(\n"
1063  " SELECT polname\n"
1064  " || CASE WHEN polcmd != '*' THEN\n"
1065  " E' (' || polcmd::pg_catalog.text || E'):'\n"
1066  " ELSE E':'\n"
1067  " END\n"
1068  " || CASE WHEN polqual IS NOT NULL THEN\n"
1069  " E'\\n (u): ' || pg_catalog.pg_get_expr(polqual, polrelid)\n"
1070  " ELSE E''\n"
1071  " END\n"
1072  " || CASE WHEN polwithcheck IS NOT NULL THEN\n"
1073  " E'\\n (c): ' || pg_catalog.pg_get_expr(polwithcheck, polrelid)\n"
1074  " ELSE E''\n"
1075  " END"
1076  " || CASE WHEN polroles <> '{0}' THEN\n"
1077  " E'\\n to: ' || pg_catalog.array_to_string(\n"
1078  " ARRAY(\n"
1079  " SELECT rolname\n"
1080  " FROM pg_catalog.pg_roles\n"
1081  " WHERE oid = ANY (polroles)\n"
1082  " ORDER BY 1\n"
1083  " ), E', ')\n"
1084  " ELSE E''\n"
1085  " END\n"
1086  " FROM pg_catalog.pg_policy pol\n"
1087  " WHERE polrelid = c.oid), E'\\n')\n"
1088  " AS \"%s\"",
1089  gettext_noop("Policies"));
1090 
1091  if (pset.sversion >= 100000)
1093  ",\n pg_catalog.array_to_string(ARRAY(\n"
1094  " SELECT polname\n"
1095  " || CASE WHEN NOT polpermissive THEN\n"
1096  " E' (RESTRICTIVE)'\n"
1097  " ELSE '' END\n"
1098  " || CASE WHEN polcmd != '*' THEN\n"
1099  " E' (' || polcmd::pg_catalog.text || E'):'\n"
1100  " ELSE E':'\n"
1101  " END\n"
1102  " || CASE WHEN polqual IS NOT NULL THEN\n"
1103  " E'\\n (u): ' || pg_catalog.pg_get_expr(polqual, polrelid)\n"
1104  " ELSE E''\n"
1105  " END\n"
1106  " || CASE WHEN polwithcheck IS NOT NULL THEN\n"
1107  " E'\\n (c): ' || pg_catalog.pg_get_expr(polwithcheck, polrelid)\n"
1108  " ELSE E''\n"
1109  " END"
1110  " || CASE WHEN polroles <> '{0}' THEN\n"
1111  " E'\\n to: ' || pg_catalog.array_to_string(\n"
1112  " ARRAY(\n"
1113  " SELECT rolname\n"
1114  " FROM pg_catalog.pg_roles\n"
1115  " WHERE oid = ANY (polroles)\n"
1116  " ORDER BY 1\n"
1117  " ), E', ')\n"
1118  " ELSE E''\n"
1119  " END\n"
1120  " FROM pg_catalog.pg_policy pol\n"
1121  " WHERE polrelid = c.oid), E'\\n')\n"
1122  " AS \"%s\"",
1123  gettext_noop("Policies"));
1124 
1125  appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_class c\n"
1126  " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
1127  "WHERE c.relkind IN ("
1128  CppAsString2(RELKIND_RELATION) ","
1129  CppAsString2(RELKIND_VIEW) ","
1130  CppAsString2(RELKIND_MATVIEW) ","
1131  CppAsString2(RELKIND_SEQUENCE) ","
1132  CppAsString2(RELKIND_FOREIGN_TABLE) ","
1133  CppAsString2(RELKIND_PARTITIONED_TABLE) ")\n");
1134 
1135  if (!showSystem && !pattern)
1136  appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
1137  " AND n.nspname <> 'information_schema'\n");
1138 
1139  if (!validateSQLNamePattern(&buf, pattern, true, false,
1140  "n.nspname", "c.relname", NULL,
1141  "pg_catalog.pg_table_is_visible(c.oid)",
1142  NULL, 3))
1143  goto error_return;
1144 
1145  appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
1146 
1147  res = PSQLexec(buf.data);
1148  if (!res)
1149  goto error_return;
1150 
1151  printfPQExpBuffer(&buf, _("Access privileges"));
1152  myopt.title = buf.data;
1153  myopt.translate_header = true;
1154  myopt.translate_columns = translate_columns;
1155  myopt.n_translate_columns = lengthof(translate_columns);
1156 
1157  printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1158 
1159  termPQExpBuffer(&buf);
1160  PQclear(res);
1161  return true;
1162 
1163 error_return:
1164  termPQExpBuffer(&buf);
1165  return false;
1166 }

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, res, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::title, printQueryOpt::translate_columns, printQueryOpt::translate_header, and validateSQLNamePattern().

Referenced by exec_command_d(), and exec_command_z().

◆ printACLColumn()

static void printACLColumn ( PQExpBuffer  buf,
const char *  colname 
)
static

Definition at line 6669 of file describe.c.

6670 {
6672  "CASE"
6673  " WHEN pg_catalog.cardinality(%s) = 0 THEN '%s'"
6674  " ELSE pg_catalog.array_to_string(%s, E'\\n')"
6675  " END AS \"%s\"",
6676  colname, gettext_noop("(none)"),
6677  colname, gettext_noop("Access privileges"));
6678 }

References appendPQExpBuffer(), buf, and gettext_noop.

Referenced by describeConfigurationParameters(), describeFunctions(), describeTablespaces(), describeTypes(), listAllDbs(), listDefaultACLs(), listDomains(), listForeignDataWrappers(), listForeignServers(), listLanguages(), listLargeObjects(), listSchemas(), and permissionsList().

◆ validateSQLNamePattern()

static bool validateSQLNamePattern ( PQExpBuffer  buf,
const char *  pattern,
bool  have_where,
bool  force_escape,
const char *  schemavar,
const char *  namevar,
const char *  altnamevar,
const char *  visibilityrule,
bool added_clause,
int  maxparts 
)
static

Definition at line 6174 of file describe.c.

6179 {
6180  PQExpBufferData dbbuf;
6181  int dotcnt;
6182  bool added;
6183 
6184  initPQExpBuffer(&dbbuf);
6185  added = processSQLNamePattern(pset.db, buf, pattern, have_where, force_escape,
6186  schemavar, namevar, altnamevar,
6187  visibilityrule, &dbbuf, &dotcnt);
6188  if (added_clause != NULL)
6189  *added_clause = added;
6190 
6191  if (dotcnt >= maxparts)
6192  {
6193  pg_log_error("improper qualified name (too many dotted names): %s",
6194  pattern);
6195  goto error_return;
6196  }
6197 
6198  if (maxparts > 1 && dotcnt == maxparts - 1)
6199  {
6200  if (PQdb(pset.db) == NULL)
6201  {
6202  pg_log_error("You are currently not connected to a database.");
6203  goto error_return;
6204  }
6205  if (strcmp(PQdb(pset.db), dbbuf.data) != 0)
6206  {
6207  pg_log_error("cross-database references are not implemented: %s",
6208  pattern);
6209  goto error_return;
6210  }
6211  }
6212  termPQExpBuffer(&dbbuf);
6213  return true;
6214 
6215 error_return:
6216  termPQExpBuffer(&dbbuf);
6217  return false;
6218 }
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:7017

References buf, PQExpBufferData::data, _psqlSettings::db, initPQExpBuffer(), pg_log_error, PQdb(), processSQLNamePattern(), pset, and termPQExpBuffer().

Referenced by describeAccessMethods(), describeAggregates(), describeFunctions(), describeOperators(), describePublications(), describeRoleGrants(), describeRoles(), describeSubscriptions(), describeTableDetails(), describeTablespaces(), describeTypes(), listAllDbs(), listCasts(), listCollations(), listConversions(), listDbRoleSettings(), listDefaultACLs(), listDomains(), listEventTriggers(), listExtendedStats(), listExtensionContents(), listExtensions(), listForeignDataWrappers(), listForeignServers(), listForeignTables(), listLanguages(), listOperatorClasses(), listOperatorFamilies(), listOpFamilyFunctions(), listOpFamilyOperators(), listPartitionedTables(), listPublications(), listSchemas(), listTables(), listTSConfigs(), listTSConfigsVerbose(), listTSDictionaries(), listTSParsers(), listTSParsersVerbose(), listTSTemplates(), listUserMappings(), objectDescription(), and permissionsList().