PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
describe.c File Reference
#include "postgres_fe.h"
#include <ctype.h>
#include "catalog/pg_am_d.h"
#include "catalog/pg_amop_d.h"
#include "catalog/pg_attribute_d.h"
#include "catalog/pg_cast_d.h"
#include "catalog/pg_class_d.h"
#include "catalog/pg_collation_d.h"
#include "catalog/pg_constraint_d.h"
#include "catalog/pg_default_acl_d.h"
#include "catalog/pg_proc_d.h"
#include "catalog/pg_publication_d.h"
#include "catalog/pg_statistic_ext_d.h"
#include "catalog/pg_subscription_d.h"
#include "catalog/pg_type_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 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 3846 of file describe.c.

3847{
3848 if (buf->len > 0)
3850
3852}
const char * str
static char * buf
Definition: pg_test_fsync.c:72
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 3646 of file describe.c.

3648{
3649 /* relkinds for which we support tablespaces */
3650 if (relkind == RELKIND_RELATION ||
3651 relkind == RELKIND_MATVIEW ||
3652 relkind == RELKIND_INDEX ||
3653 relkind == RELKIND_PARTITIONED_TABLE ||
3654 relkind == RELKIND_PARTITIONED_INDEX ||
3655 relkind == RELKIND_TOASTVALUE)
3656 {
3657 /*
3658 * We ignore the database default tablespace so that users not using
3659 * tablespaces don't need to know about them.
3660 */
3661 if (tablespace != 0)
3662 {
3663 PGresult *result = NULL;
3665
3668 "SELECT spcname FROM pg_catalog.pg_tablespace\n"
3669 "WHERE oid = '%u';", tablespace);
3670 result = PSQLexec(buf.data);
3671 if (!result)
3672 {
3674 return;
3675 }
3676 /* Should always be the case, but.... */
3677 if (PQntuples(result) > 0)
3678 {
3679 if (newline)
3680 {
3681 /* Add the tablespace as a new footer */
3682 printfPQExpBuffer(&buf, _("Tablespace: \"%s\""),
3683 PQgetvalue(result, 0, 0));
3684 printTableAddFooter(cont, buf.data);
3685 }
3686 else
3687 {
3688 /* Append the tablespace to the latest footer */
3689 printfPQExpBuffer(&buf, "%s", cont->footer->data);
3690
3691 /*-------
3692 translator: before this string there's an index description like
3693 '"foo_pkey" PRIMARY KEY, btree (a)' */
3694 appendPQExpBuffer(&buf, _(", tablespace \"%s\""),
3695 PQgetvalue(result, 0, 0));
3696 printTableSetFooter(cont, buf.data);
3697 }
3698 }
3699 PQclear(result);
3701 }
3702 }
3703}
PGresult * PSQLexec(const char *query)
Definition: common.c:655
#define _(x)
Definition: elog.c:91
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
void PQclear(PGresult *res)
Definition: fe-exec.c:721
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
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:217
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 6480 of file describe.c.

6482{
6483 PGresult *res;
6484 int count = 0;
6485 int i = 0;
6486
6487 res = PSQLexec(buf->data);
6488 if (!res)
6489 return false;
6490 else
6491 count = PQntuples(res);
6492
6493 if (count > 0)
6494 printTableAddFooter(cont, footermsg);
6495
6496 for (i = 0; i < count; i++)
6497 {
6498 if (as_schema)
6499 printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, 0));
6500 else
6501 {
6502 printfPQExpBuffer(buf, " \"%s.%s\"", PQgetvalue(res, i, 0),
6503 PQgetvalue(res, i, 1));
6504
6505 if (!PQgetisnull(res, i, 3))
6506 appendPQExpBuffer(buf, " (%s)", PQgetvalue(res, i, 3));
6507
6508 if (!PQgetisnull(res, i, 2))
6509 appendPQExpBuffer(buf, " WHERE %s", PQgetvalue(res, i, 2));
6510 }
6511
6512 printTableAddFooter(cont, buf->data);
6513 }
6514
6515 PQclear(res);
6516 return true;
6517}
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3901
int i
Definition: isn.c:77

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

Referenced by describePublications().

◆ describeAccessMethods()

bool describeAccessMethods ( const char *  pattern,
bool  verbose 
)

Definition at line 148 of file describe.c.

149{
151 PGresult *res;
152 printQueryOpt myopt = pset.popt;
153 static const bool translate_columns[] = {false, true, false, false};
154
155 if (pset.sversion < 90600)
156 {
157 char sverbuf[32];
158
159 pg_log_error("The server (version %s) does not support access methods.",
161 sverbuf, sizeof(sverbuf)));
162 return true;
163 }
164
166
168 "SELECT amname AS \"%s\",\n"
169 " CASE amtype"
170 " WHEN " CppAsString2(AMTYPE_INDEX) " THEN '%s'"
171 " WHEN " CppAsString2(AMTYPE_TABLE) " THEN '%s'"
172 " END AS \"%s\"",
173 gettext_noop("Name"),
174 gettext_noop("Index"),
175 gettext_noop("Table"),
176 gettext_noop("Type"));
177
178 if (verbose)
179 {
181 ",\n amhandler AS \"%s\",\n"
182 " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"",
183 gettext_noop("Handler"),
184 gettext_noop("Description"));
185 }
186
188 "\nFROM pg_catalog.pg_am\n");
189
190 if (!validateSQLNamePattern(&buf, pattern, false, false,
191 NULL, "amname", NULL,
192 NULL,
193 NULL, 1))
194 {
196 return false;
197 }
198
199 appendPQExpBufferStr(&buf, "ORDER BY 1;");
200
201 res = PSQLexec(buf.data);
203 if (!res)
204 return false;
205
206 myopt.title = _("List of access methods");
207 myopt.translate_header = true;
208 myopt.translate_columns = translate_columns;
209 myopt.n_translate_columns = lengthof(translate_columns);
210
211 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
212
213 PQclear(res);
214 return true;
215}
#define gettext_noop(x)
Definition: c.h:1167
#define CppAsString2(x)
Definition: c.h:363
#define lengthof(array)
Definition: c.h:759
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:6342
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:313
printQueryOpt popt
Definition: settings.h:112
FILE * logfile
Definition: settings.h:149
FILE * queryFout
Definition: settings.h:105
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, CppAsString2, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, pg_log_error, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, _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 78 of file describe.c.

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

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, _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 4710 of file describe.c.

4712{
4714 PGresult *res;
4715 printQueryOpt myopt = pset.popt;
4716
4719 "SELECT s.name AS \"%s\", "
4720 "pg_catalog.current_setting(s.name) AS \"%s\"",
4721 gettext_noop("Parameter"),
4722 gettext_noop("Value"));
4723
4724 if (verbose)
4725 {
4727 ", s.vartype AS \"%s\", s.context AS \"%s\", ",
4728 gettext_noop("Type"),
4729 gettext_noop("Context"));
4730 if (pset.sversion >= 150000)
4731 printACLColumn(&buf, "p.paracl");
4732 else
4733 appendPQExpBuffer(&buf, "NULL AS \"%s\"",
4734 gettext_noop("Access privileges"));
4735 }
4736
4737 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_settings s\n");
4738
4739 if (verbose && pset.sversion >= 150000)
4741 " LEFT JOIN pg_catalog.pg_parameter_acl p\n"
4742 " ON pg_catalog.lower(s.name) = p.parname\n");
4743
4744 if (pattern)
4745 processSQLNamePattern(pset.db, &buf, pattern,
4746 false, false,
4747 NULL, "pg_catalog.lower(s.name)", NULL,
4748 NULL, NULL, NULL);
4749 else
4750 appendPQExpBufferStr(&buf, "WHERE s.source <> 'default' AND\n"
4751 " s.setting IS DISTINCT FROM s.boot_val\n");
4752
4753 appendPQExpBufferStr(&buf, "ORDER BY 1;");
4754
4755 res = PSQLexec(buf.data);
4757 if (!res)
4758 return false;
4759
4760 if (pattern)
4761 myopt.title = _("List of configuration parameters");
4762 else
4763 myopt.title = _("List of non-default configuration parameters");
4764 myopt.translate_header = true;
4765
4766 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4767
4768 PQclear(res);
4769 return true;
4770}
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition: describe.c:6875
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)
PGconn * db
Definition: settings.h:103

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, _psqlSettings::db, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, _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 295 of file describe.c.

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

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, 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, 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 1570 of file describe.c.

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

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, 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 5832 of file describe.c.

5834{
5836 title;
5837 PGresult *res;
5838 printQueryOpt myopt = pset.popt;
5839
5841
5843 "SELECT\n"
5844 " ( SELECT t.alias FROM\n"
5845 " pg_catalog.ts_token_type(c.cfgparser) AS t\n"
5846 " WHERE t.tokid = m.maptokentype ) AS \"%s\",\n"
5847 " pg_catalog.btrim(\n"
5848 " ARRAY( SELECT mm.mapdict::pg_catalog.regdictionary\n"
5849 " FROM pg_catalog.pg_ts_config_map AS mm\n"
5850 " WHERE mm.mapcfg = m.mapcfg AND mm.maptokentype = m.maptokentype\n"
5851 " ORDER BY mapcfg, maptokentype, mapseqno\n"
5852 " ) :: pg_catalog.text,\n"
5853 " '{}') AS \"%s\"\n"
5854 "FROM pg_catalog.pg_ts_config AS c, pg_catalog.pg_ts_config_map AS m\n"
5855 "WHERE c.oid = '%s' AND m.mapcfg = c.oid\n"
5856 "GROUP BY m.mapcfg, m.maptokentype, c.cfgparser\n"
5857 "ORDER BY 1;",
5858 gettext_noop("Token"),
5859 gettext_noop("Dictionaries"),
5860 oid);
5861
5862 res = PSQLexec(buf.data);
5864 if (!res)
5865 return false;
5866
5867 initPQExpBuffer(&title);
5868
5869 if (nspname)
5870 appendPQExpBuffer(&title, _("Text search configuration \"%s.%s\""),
5871 nspname, cfgname);
5872 else
5873 appendPQExpBuffer(&title, _("Text search configuration \"%s\""),
5874 cfgname);
5875
5876 if (pnspname)
5877 appendPQExpBuffer(&title, _("\nParser: \"%s.%s\""),
5878 pnspname, prsname);
5879 else
5880 appendPQExpBuffer(&title, _("\nParser: \"%s\""),
5881 prsname);
5882
5883 myopt.title = title.data;
5884 myopt.footers = NULL;
5885 myopt.topt.default_footer = false;
5886 myopt.translate_header = true;
5887
5888 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5889
5890 termPQExpBuffer(&title);
5891
5892 PQclear(res);
5893 return true;
5894}

References _, appendPQExpBuffer(), buf, PQExpBufferData::data, printTableOpt::default_footer, printQueryOpt::footers, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 5449 of file describe.c.

5450{
5452 PGresult *res;
5453 PQExpBufferData title;
5454 printQueryOpt myopt = pset.popt;
5455 static const bool translate_columns[] = {true, false, false};
5456
5458
5460 "SELECT '%s' AS \"%s\",\n"
5461 " p.prsstart::pg_catalog.regproc AS \"%s\",\n"
5462 " pg_catalog.obj_description(p.prsstart, 'pg_proc') as \"%s\"\n"
5463 " FROM pg_catalog.pg_ts_parser p\n"
5464 " WHERE p.oid = '%s'\n"
5465 "UNION ALL\n"
5466 "SELECT '%s',\n"
5467 " p.prstoken::pg_catalog.regproc,\n"
5468 " pg_catalog.obj_description(p.prstoken, 'pg_proc')\n"
5469 " FROM pg_catalog.pg_ts_parser p\n"
5470 " WHERE p.oid = '%s'\n"
5471 "UNION ALL\n"
5472 "SELECT '%s',\n"
5473 " p.prsend::pg_catalog.regproc,\n"
5474 " pg_catalog.obj_description(p.prsend, 'pg_proc')\n"
5475 " FROM pg_catalog.pg_ts_parser p\n"
5476 " WHERE p.oid = '%s'\n"
5477 "UNION ALL\n"
5478 "SELECT '%s',\n"
5479 " p.prsheadline::pg_catalog.regproc,\n"
5480 " pg_catalog.obj_description(p.prsheadline, 'pg_proc')\n"
5481 " FROM pg_catalog.pg_ts_parser p\n"
5482 " WHERE p.oid = '%s'\n"
5483 "UNION ALL\n"
5484 "SELECT '%s',\n"
5485 " p.prslextype::pg_catalog.regproc,\n"
5486 " pg_catalog.obj_description(p.prslextype, 'pg_proc')\n"
5487 " FROM pg_catalog.pg_ts_parser p\n"
5488 " WHERE p.oid = '%s';",
5489 gettext_noop("Start parse"),
5490 gettext_noop("Method"),
5491 gettext_noop("Function"),
5492 gettext_noop("Description"),
5493 oid,
5494 gettext_noop("Get next token"),
5495 oid,
5496 gettext_noop("End parse"),
5497 oid,
5498 gettext_noop("Get headline"),
5499 oid,
5500 gettext_noop("Get token types"),
5501 oid);
5502
5503 res = PSQLexec(buf.data);
5505 if (!res)
5506 return false;
5507
5508 initPQExpBuffer(&title);
5509 if (nspname)
5510 printfPQExpBuffer(&title, _("Text search parser \"%s.%s\""),
5511 nspname, prsname);
5512 else
5513 printfPQExpBuffer(&title, _("Text search parser \"%s\""), prsname);
5514 myopt.title = title.data;
5515 myopt.footers = NULL;
5516 myopt.topt.default_footer = false;
5517 myopt.translate_header = true;
5518 myopt.translate_columns = translate_columns;
5519 myopt.n_translate_columns = lengthof(translate_columns);
5520
5521 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5522
5523 PQclear(res);
5524
5526
5528 "SELECT t.alias as \"%s\",\n"
5529 " t.description as \"%s\"\n"
5530 "FROM pg_catalog.ts_token_type( '%s'::pg_catalog.oid ) as t\n"
5531 "ORDER BY 1;",
5532 gettext_noop("Token name"),
5533 gettext_noop("Description"),
5534 oid);
5535
5536 res = PSQLexec(buf.data);
5538 if (!res)
5539 {
5540 termPQExpBuffer(&title);
5541 return false;
5542 }
5543
5544 if (nspname)
5545 printfPQExpBuffer(&title, _("Token types for parser \"%s.%s\""),
5546 nspname, prsname);
5547 else
5548 printfPQExpBuffer(&title, _("Token types for parser \"%s\""), prsname);
5549 myopt.title = title.data;
5550 myopt.footers = NULL;
5551 myopt.topt.default_footer = true;
5552 myopt.translate_header = true;
5553 myopt.translate_columns = NULL;
5554 myopt.n_translate_columns = 0;
5555
5556 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5557
5558 termPQExpBuffer(&title);
5559 PQclear(res);
5560 return true;
5561}

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, 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 793 of file describe.c.

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

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

Referenced by exec_command_dfo().

◆ describePublications()

bool describePublications ( const char *  pattern)

Definition at line 6526 of file describe.c.

6527{
6529 int i;
6530 PGresult *res;
6531 bool has_pubtruncate;
6532 bool has_pubgencols;
6533 bool has_pubviaroot;
6534
6535 PQExpBufferData title;
6536 printTableContent cont;
6537
6538 if (pset.sversion < 100000)
6539 {
6540 char sverbuf[32];
6541
6542 pg_log_error("The server (version %s) does not support publications.",
6544 sverbuf, sizeof(sverbuf)));
6545 return true;
6546 }
6547
6548 has_pubtruncate = (pset.sversion >= 110000);
6549 has_pubgencols = (pset.sversion >= 180000);
6550 has_pubviaroot = (pset.sversion >= 130000);
6551
6553
6555 "SELECT oid, pubname,\n"
6556 " pg_catalog.pg_get_userbyid(pubowner) AS owner,\n"
6557 " puballtables, pubinsert, pubupdate, pubdelete");
6558 if (has_pubtruncate)
6560 ", pubtruncate");
6561 else
6563 ", false AS pubtruncate");
6564
6565 if (has_pubgencols)
6567 ", (CASE pubgencols\n"
6568 " WHEN '%c' THEN 'none'\n"
6569 " WHEN '%c' THEN 'stored'\n"
6570 " END) AS \"%s\"\n",
6571 PUBLISH_GENCOLS_NONE,
6572 PUBLISH_GENCOLS_STORED,
6573 gettext_noop("Generated columns"));
6574 else
6576 ", 'none' AS pubgencols");
6577
6578 if (has_pubviaroot)
6580 ", pubviaroot");
6581 else
6583 ", false AS pubviaroot");
6584
6586 "\nFROM pg_catalog.pg_publication\n");
6587
6588 if (!validateSQLNamePattern(&buf, pattern, false, false,
6589 NULL, "pubname", NULL,
6590 NULL,
6591 NULL, 1))
6592 {
6594 return false;
6595 }
6596
6597 appendPQExpBufferStr(&buf, "ORDER BY 2;");
6598
6599 res = PSQLexec(buf.data);
6600 if (!res)
6601 {
6603 return false;
6604 }
6605
6606 if (PQntuples(res) == 0)
6607 {
6608 if (!pset.quiet)
6609 {
6610 if (pattern)
6611 pg_log_error("Did not find any publication named \"%s\".",
6612 pattern);
6613 else
6614 pg_log_error("Did not find any publications.");
6615 }
6616
6618 PQclear(res);
6619 return false;
6620 }
6621
6622 for (i = 0; i < PQntuples(res); i++)
6623 {
6624 const char align = 'l';
6625 int ncols = 5;
6626 int nrows = 1;
6627 char *pubid = PQgetvalue(res, i, 0);
6628 char *pubname = PQgetvalue(res, i, 1);
6629 bool puballtables = strcmp(PQgetvalue(res, i, 3), "t") == 0;
6630 printTableOpt myopt = pset.popt.topt;
6631
6632 if (has_pubtruncate)
6633 ncols++;
6634 if (has_pubgencols)
6635 ncols++;
6636 if (has_pubviaroot)
6637 ncols++;
6638
6639 initPQExpBuffer(&title);
6640 printfPQExpBuffer(&title, _("Publication %s"), pubname);
6641 printTableInit(&cont, &myopt, title.data, ncols, nrows);
6642
6643 printTableAddHeader(&cont, gettext_noop("Owner"), true, align);
6644 printTableAddHeader(&cont, gettext_noop("All tables"), true, align);
6645 printTableAddHeader(&cont, gettext_noop("Inserts"), true, align);
6646 printTableAddHeader(&cont, gettext_noop("Updates"), true, align);
6647 printTableAddHeader(&cont, gettext_noop("Deletes"), true, align);
6648 if (has_pubtruncate)
6649 printTableAddHeader(&cont, gettext_noop("Truncates"), true, align);
6650 if (has_pubgencols)
6651 printTableAddHeader(&cont, gettext_noop("Generated columns"), true, align);
6652 if (has_pubviaroot)
6653 printTableAddHeader(&cont, gettext_noop("Via root"), true, align);
6654
6655 printTableAddCell(&cont, PQgetvalue(res, i, 2), false, false);
6656 printTableAddCell(&cont, PQgetvalue(res, i, 3), false, false);
6657 printTableAddCell(&cont, PQgetvalue(res, i, 4), false, false);
6658 printTableAddCell(&cont, PQgetvalue(res, i, 5), false, false);
6659 printTableAddCell(&cont, PQgetvalue(res, i, 6), false, false);
6660 if (has_pubtruncate)
6661 printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false);
6662 if (has_pubgencols)
6663 printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
6664 if (has_pubviaroot)
6665 printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
6666
6667 if (!puballtables)
6668 {
6669 /* Get the tables for the specified publication */
6671 "SELECT n.nspname, c.relname");
6672 if (pset.sversion >= 150000)
6673 {
6675 ", pg_get_expr(pr.prqual, c.oid)");
6677 ", (CASE WHEN pr.prattrs IS NOT NULL THEN\n"
6678 " pg_catalog.array_to_string("
6679 " ARRAY(SELECT attname\n"
6680 " FROM\n"
6681 " pg_catalog.generate_series(0, pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n"
6682 " pg_catalog.pg_attribute\n"
6683 " WHERE attrelid = c.oid AND attnum = prattrs[s]), ', ')\n"
6684 " ELSE NULL END)");
6685 }
6686 else
6688 ", NULL, NULL");
6690 "\nFROM pg_catalog.pg_class c,\n"
6691 " pg_catalog.pg_namespace n,\n"
6692 " pg_catalog.pg_publication_rel pr\n"
6693 "WHERE c.relnamespace = n.oid\n"
6694 " AND c.oid = pr.prrelid\n"
6695 " AND pr.prpubid = '%s'\n"
6696 "ORDER BY 1,2", pubid);
6697 if (!addFooterToPublicationDesc(&buf, _("Tables:"), false, &cont))
6698 goto error_return;
6699
6700 if (pset.sversion >= 150000)
6701 {
6702 /* Get the schemas for the specified publication */
6704 "SELECT n.nspname\n"
6705 "FROM pg_catalog.pg_namespace n\n"
6706 " JOIN pg_catalog.pg_publication_namespace pn ON n.oid = pn.pnnspid\n"
6707 "WHERE pn.pnpubid = '%s'\n"
6708 "ORDER BY 1", pubid);
6709 if (!addFooterToPublicationDesc(&buf, _("Tables from schemas:"),
6710 true, &cont))
6711 goto error_return;
6712 }
6713 }
6714
6715 printTable(&cont, pset.queryFout, false, pset.logfile);
6716 printTableCleanup(&cont);
6717
6718 termPQExpBuffer(&title);
6719 }
6720
6722 PQclear(res);
6723
6724 return true;
6725
6726error_return:
6727 printTableCleanup(&cont);
6728 PQclear(res);
6730 termPQExpBuffer(&title);
6731 return false;
6732}
static bool addFooterToPublicationDesc(PQExpBuffer buf, const char *footermsg, bool as_schema, printTableContent *const cont)
Definition: describe.c:6480

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, _psqlSettings::sversion, termPQExpBuffer(), printQueryOpt::topt, and validateSQLNamePattern().

Referenced by exec_command_d().

◆ describeRoleGrants()

bool describeRoleGrants ( const char *  pattern,
bool  showSystem 
)

Definition at line 3927 of file describe.c.

3928{
3930 PGresult *res;
3931 printQueryOpt myopt = pset.popt;
3932
3935 "SELECT m.rolname AS \"%s\", r.rolname AS \"%s\",\n"
3936 " pg_catalog.concat_ws(', ',\n",
3937 gettext_noop("Role name"),
3938 gettext_noop("Member of"));
3939
3940 if (pset.sversion >= 160000)
3942 " CASE WHEN pam.admin_option THEN 'ADMIN' END,\n"
3943 " CASE WHEN pam.inherit_option THEN 'INHERIT' END,\n"
3944 " CASE WHEN pam.set_option THEN 'SET' END\n");
3945 else
3947 " CASE WHEN pam.admin_option THEN 'ADMIN' END,\n"
3948 " CASE WHEN m.rolinherit THEN 'INHERIT' END,\n"
3949 " 'SET'\n");
3950
3952 " ) AS \"%s\",\n"
3953 " g.rolname AS \"%s\"\n",
3954 gettext_noop("Options"),
3955 gettext_noop("Grantor"));
3956
3958 "FROM pg_catalog.pg_roles m\n"
3959 " JOIN pg_catalog.pg_auth_members pam ON (pam.member = m.oid)\n"
3960 " LEFT JOIN pg_catalog.pg_roles r ON (pam.roleid = r.oid)\n"
3961 " LEFT JOIN pg_catalog.pg_roles g ON (pam.grantor = g.oid)\n");
3962
3963 if (!showSystem && !pattern)
3964 appendPQExpBufferStr(&buf, "WHERE m.rolname !~ '^pg_'\n");
3965
3966 if (!validateSQLNamePattern(&buf, pattern, false, false,
3967 NULL, "m.rolname", NULL, NULL,
3968 NULL, 1))
3969 {
3971 return false;
3972 }
3973
3974 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;\n");
3975
3976 res = PSQLexec(buf.data);
3978 if (!res)
3979 return false;
3980
3981 myopt.title = _("List of role grants");
3982 myopt.translate_header = true;
3983
3984 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
3985
3986 PQclear(res);
3987 return true;
3988}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, _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 3711 of file describe.c.

3712{
3714 PGresult *res;
3715 printTableContent cont;
3716 printTableOpt myopt = pset.popt.topt;
3717 int ncols = 2;
3718 int nrows = 0;
3719 int i;
3720 int conns;
3721 const char align = 'l';
3722 char **attr;
3723
3724 myopt.default_footer = false;
3725
3727
3729 "SELECT r.rolname, r.rolsuper, r.rolinherit,\n"
3730 " r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,\n"
3731 " r.rolconnlimit, r.rolvaliduntil");
3732
3733 if (verbose)
3734 {
3735 appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
3736 ncols++;
3737 }
3738 appendPQExpBufferStr(&buf, "\n, r.rolreplication");
3739
3740 if (pset.sversion >= 90500)
3741 {
3742 appendPQExpBufferStr(&buf, "\n, r.rolbypassrls");
3743 }
3744
3745 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_roles r\n");
3746
3747 if (!showSystem && !pattern)
3748 appendPQExpBufferStr(&buf, "WHERE r.rolname !~ '^pg_'\n");
3749
3750 if (!validateSQLNamePattern(&buf, pattern, false, false,
3751 NULL, "r.rolname", NULL, NULL,
3752 NULL, 1))
3753 {
3755 return false;
3756 }
3757
3758 appendPQExpBufferStr(&buf, "ORDER BY 1;");
3759
3760 res = PSQLexec(buf.data);
3761 if (!res)
3762 return false;
3763
3764 nrows = PQntuples(res);
3765 attr = pg_malloc0((nrows + 1) * sizeof(*attr));
3766
3767 printTableInit(&cont, &myopt, _("List of roles"), ncols, nrows);
3768
3769 printTableAddHeader(&cont, gettext_noop("Role name"), true, align);
3770 printTableAddHeader(&cont, gettext_noop("Attributes"), true, align);
3771
3772 if (verbose)
3773 printTableAddHeader(&cont, gettext_noop("Description"), true, align);
3774
3775 for (i = 0; i < nrows; i++)
3776 {
3777 printTableAddCell(&cont, PQgetvalue(res, i, 0), false, false);
3778
3780 if (strcmp(PQgetvalue(res, i, 1), "t") == 0)
3781 add_role_attribute(&buf, _("Superuser"));
3782
3783 if (strcmp(PQgetvalue(res, i, 2), "t") != 0)
3784 add_role_attribute(&buf, _("No inheritance"));
3785
3786 if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
3787 add_role_attribute(&buf, _("Create role"));
3788
3789 if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
3790 add_role_attribute(&buf, _("Create DB"));
3791
3792 if (strcmp(PQgetvalue(res, i, 5), "t") != 0)
3793 add_role_attribute(&buf, _("Cannot login"));
3794
3795 if (strcmp(PQgetvalue(res, i, (verbose ? 9 : 8)), "t") == 0)
3796 add_role_attribute(&buf, _("Replication"));
3797
3798 if (pset.sversion >= 90500)
3799 if (strcmp(PQgetvalue(res, i, (verbose ? 10 : 9)), "t") == 0)
3800 add_role_attribute(&buf, _("Bypass RLS"));
3801
3802 conns = atoi(PQgetvalue(res, i, 6));
3803 if (conns >= 0)
3804 {
3805 if (buf.len > 0)
3806 appendPQExpBufferChar(&buf, '\n');
3807
3808 if (conns == 0)
3809 appendPQExpBufferStr(&buf, _("No connections"));
3810 else
3811 appendPQExpBuffer(&buf, ngettext("%d connection",
3812 "%d connections",
3813 conns),
3814 conns);
3815 }
3816
3817 if (strcmp(PQgetvalue(res, i, 7), "") != 0)
3818 {
3819 if (buf.len > 0)
3820 appendPQExpBufferChar(&buf, '\n');
3821 appendPQExpBufferStr(&buf, _("Password valid until "));
3823 }
3824
3825 attr[i] = pg_strdup(buf.data);
3826
3827 printTableAddCell(&cont, attr[i], false, false);
3828
3829 if (verbose)
3830 printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
3831 }
3833
3834 printTable(&cont, pset.queryFout, false, pset.logfile);
3835 printTableCleanup(&cont);
3836
3837 for (i = 0; i < nrows; i++)
3838 free(attr[i]);
3839 free(attr);
3840
3841 PQclear(res);
3842 return true;
3843}
#define ngettext(s, p, n)
Definition: c.h:1152
static void add_role_attribute(PQExpBuffer buf, const char *const str)
Definition: describe.c:3846
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, 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 6741 of file describe.c.

6742{
6744 PGresult *res;
6745 printQueryOpt myopt = pset.popt;
6746 static const bool translate_columns[] = {false, false, false, false,
6747 false, false, false, false, false, false, false, false, false, false,
6748 false};
6749
6750 if (pset.sversion < 100000)
6751 {
6752 char sverbuf[32];
6753
6754 pg_log_error("The server (version %s) does not support subscriptions.",
6756 sverbuf, sizeof(sverbuf)));
6757 return true;
6758 }
6759
6761
6763 "SELECT subname AS \"%s\"\n"
6764 ", pg_catalog.pg_get_userbyid(subowner) AS \"%s\"\n"
6765 ", subenabled AS \"%s\"\n"
6766 ", subpublications AS \"%s\"\n",
6767 gettext_noop("Name"),
6768 gettext_noop("Owner"),
6769 gettext_noop("Enabled"),
6770 gettext_noop("Publication"));
6771
6772 if (verbose)
6773 {
6774 /* Binary mode and streaming are only supported in v14 and higher */
6775 if (pset.sversion >= 140000)
6776 {
6778 ", subbinary AS \"%s\"\n",
6779 gettext_noop("Binary"));
6780
6781 if (pset.sversion >= 160000)
6783 ", (CASE substream\n"
6784 " WHEN " CppAsString2(LOGICALREP_STREAM_OFF) " THEN 'off'\n"
6785 " WHEN " CppAsString2(LOGICALREP_STREAM_ON) " THEN 'on'\n"
6786 " WHEN " CppAsString2(LOGICALREP_STREAM_PARALLEL) " THEN 'parallel'\n"
6787 " END) AS \"%s\"\n",
6788 gettext_noop("Streaming"));
6789 else
6791 ", substream AS \"%s\"\n",
6792 gettext_noop("Streaming"));
6793 }
6794
6795 /* Two_phase and disable_on_error are only supported in v15 and higher */
6796 if (pset.sversion >= 150000)
6798 ", subtwophasestate AS \"%s\"\n"
6799 ", subdisableonerr AS \"%s\"\n",
6800 gettext_noop("Two-phase commit"),
6801 gettext_noop("Disable on error"));
6802
6803 if (pset.sversion >= 160000)
6805 ", suborigin AS \"%s\"\n"
6806 ", subpasswordrequired AS \"%s\"\n"
6807 ", subrunasowner AS \"%s\"\n",
6808 gettext_noop("Origin"),
6809 gettext_noop("Password required"),
6810 gettext_noop("Run as owner?"));
6811
6812 if (pset.sversion >= 170000)
6814 ", subfailover AS \"%s\"\n",
6815 gettext_noop("Failover"));
6816
6818 ", subsynccommit AS \"%s\"\n"
6819 ", subconninfo AS \"%s\"\n",
6820 gettext_noop("Synchronous commit"),
6821 gettext_noop("Conninfo"));
6822
6823 /* Skip LSN is only supported in v15 and higher */
6824 if (pset.sversion >= 150000)
6826 ", subskiplsn AS \"%s\"\n",
6827 gettext_noop("Skip LSN"));
6828 }
6829
6830 /* Only display subscriptions in current database. */
6832 "FROM pg_catalog.pg_subscription\n"
6833 "WHERE subdbid = (SELECT oid\n"
6834 " FROM pg_catalog.pg_database\n"
6835 " WHERE datname = pg_catalog.current_database())");
6836
6837 if (!validateSQLNamePattern(&buf, pattern, true, false,
6838 NULL, "subname", NULL,
6839 NULL,
6840 NULL, 1))
6841 {
6843 return false;
6844 }
6845
6846 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6847
6848 res = PSQLexec(buf.data);
6850 if (!res)
6851 return false;
6852
6853 myopt.title = _("List of subscriptions");
6854 myopt.translate_header = true;
6855 myopt.translate_columns = translate_columns;
6856 myopt.n_translate_columns = lengthof(translate_columns);
6857
6858 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6859
6860 PQclear(res);
6861 return true;
6862}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, pg_log_error, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, _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 1487 of file describe.c.

1488{
1490 PGresult *res;
1491 int i;
1492
1494
1496 "SELECT c.oid,\n"
1497 " n.nspname,\n"
1498 " c.relname\n"
1499 "FROM pg_catalog.pg_class c\n"
1500 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n");
1501
1502 if (!showSystem && !pattern)
1503 appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
1504 " AND n.nspname <> 'information_schema'\n");
1505
1506 if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern, false,
1507 "n.nspname", "c.relname", NULL,
1508 "pg_catalog.pg_table_is_visible(c.oid)",
1509 NULL, 3))
1510 {
1512 return false;
1513 }
1514
1515 appendPQExpBufferStr(&buf, "ORDER BY 2, 3;");
1516
1517 res = PSQLexec(buf.data);
1519 if (!res)
1520 return false;
1521
1522 if (PQntuples(res) == 0)
1523 {
1524 if (!pset.quiet)
1525 {
1526 if (pattern)
1527 pg_log_error("Did not find any relation named \"%s\".",
1528 pattern);
1529 else
1530 pg_log_error("Did not find any relations.");
1531 }
1532 PQclear(res);
1533 return false;
1534 }
1535
1536 for (i = 0; i < PQntuples(res); i++)
1537 {
1538 const char *oid;
1539 const char *nspname;
1540 const char *relname;
1541
1542 oid = PQgetvalue(res, i, 0);
1543 nspname = PQgetvalue(res, i, 1);
1544 relname = PQgetvalue(res, i, 2);
1545
1546 if (!describeOneTableDetails(nspname, relname, oid, verbose))
1547 {
1548 PQclear(res);
1549 return false;
1550 }
1551 if (cancel_pressed)
1552 {
1553 PQclear(res);
1554 return false;
1555 }
1556 }
1557
1558 PQclear(res);
1559 return true;
1560}
static bool describeOneTableDetails(const char *schemaname, const char *relationname, const char *oid, bool verbose)
Definition: describe.c:1570
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, termPQExpBuffer(), validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ describeTablespaces()

bool describeTablespaces ( const char *  pattern,
bool  verbose 
)

Definition at line 222 of file describe.c.

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

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 638 of file describe.c.

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

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, map_typename_pattern(), _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 945 of file describe.c.

946{
947 PGresult *res;
949 printQueryOpt myopt = pset.popt;
950
952
954 "SELECT\n"
955 " d.datname as \"%s\",\n"
956 " pg_catalog.pg_get_userbyid(d.datdba) as \"%s\",\n"
957 " pg_catalog.pg_encoding_to_char(d.encoding) as \"%s\",\n",
958 gettext_noop("Name"),
959 gettext_noop("Owner"),
960 gettext_noop("Encoding"));
961 if (pset.sversion >= 150000)
963 " CASE d.datlocprovider "
964 "WHEN " CppAsString2(COLLPROVIDER_BUILTIN) " THEN 'builtin' "
965 "WHEN " CppAsString2(COLLPROVIDER_LIBC) " THEN 'libc' "
966 "WHEN " CppAsString2(COLLPROVIDER_ICU) " THEN 'icu' "
967 "END AS \"%s\",\n",
968 gettext_noop("Locale Provider"));
969 else
971 " 'libc' AS \"%s\",\n",
972 gettext_noop("Locale Provider"));
974 " d.datcollate as \"%s\",\n"
975 " d.datctype as \"%s\",\n",
976 gettext_noop("Collate"),
977 gettext_noop("Ctype"));
978 if (pset.sversion >= 170000)
980 " d.datlocale as \"%s\",\n",
981 gettext_noop("Locale"));
982 else if (pset.sversion >= 150000)
984 " d.daticulocale as \"%s\",\n",
985 gettext_noop("Locale"));
986 else
988 " NULL as \"%s\",\n",
989 gettext_noop("Locale"));
990 if (pset.sversion >= 160000)
992 " d.daticurules as \"%s\",\n",
993 gettext_noop("ICU Rules"));
994 else
996 " NULL as \"%s\",\n",
997 gettext_noop("ICU Rules"));
999 printACLColumn(&buf, "d.datacl");
1000 if (verbose)
1002 ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n"
1003 " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n"
1004 " ELSE 'No Access'\n"
1005 " END as \"%s\""
1006 ",\n t.spcname as \"%s\""
1007 ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"",
1008 gettext_noop("Size"),
1009 gettext_noop("Tablespace"),
1010 gettext_noop("Description"));
1012 "\nFROM pg_catalog.pg_database d\n");
1013 if (verbose)
1015 " JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
1016
1017 if (pattern)
1018 {
1019 if (!validateSQLNamePattern(&buf, pattern, false, false,
1020 NULL, "d.datname", NULL, NULL,
1021 NULL, 1))
1022 {
1024 return false;
1025 }
1026 }
1027
1028 appendPQExpBufferStr(&buf, "ORDER BY 1;");
1029 res = PSQLexec(buf.data);
1031 if (!res)
1032 return false;
1033
1034 myopt.title = _("List of databases");
1035 myopt.translate_header = true;
1036
1037 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1038
1039 PQclear(res);
1040 return true;
1041}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, _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 4954 of file describe.c.

4955{
4957 PGresult *res;
4958 printQueryOpt myopt = pset.popt;
4959 static const bool translate_columns[] = {false, false, false, true, true, false};
4960
4962
4964 "SELECT pg_catalog.format_type(castsource, NULL) AS \"%s\",\n"
4965 " pg_catalog.format_type(casttarget, NULL) AS \"%s\",\n",
4966 gettext_noop("Source type"),
4967 gettext_noop("Target type"));
4968
4969 /*
4970 * We don't attempt to localize '(binary coercible)' or '(with inout)',
4971 * because there's too much risk of gettext translating a function name
4972 * that happens to match some string in the PO database.
4973 */
4975 " CASE WHEN c.castmethod = '%c' THEN '(binary coercible)'\n"
4976 " WHEN c.castmethod = '%c' THEN '(with inout)'\n"
4977 " ELSE p.proname\n"
4978 " END AS \"%s\",\n",
4979 COERCION_METHOD_BINARY,
4980 COERCION_METHOD_INOUT,
4981 gettext_noop("Function"));
4982
4984 " CASE WHEN c.castcontext = '%c' THEN '%s'\n"
4985 " WHEN c.castcontext = '%c' THEN '%s'\n"
4986 " ELSE '%s'\n"
4987 " END AS \"%s\"",
4988 COERCION_CODE_EXPLICIT,
4989 gettext_noop("no"),
4990 COERCION_CODE_ASSIGNMENT,
4991 gettext_noop("in assignment"),
4992 gettext_noop("yes"),
4993 gettext_noop("Implicit?"));
4994
4995 if (verbose)
4997 ",\n CASE WHEN p.proleakproof THEN '%s'\n"
4998 " ELSE '%s'\n"
4999 " END AS \"%s\",\n"
5000 " d.description AS \"%s\"",
5001 gettext_noop("yes"),
5002 gettext_noop("no"),
5003 gettext_noop("Leakproof?"),
5004 gettext_noop("Description"));
5005
5006 /*
5007 * We need a left join to pg_proc for binary casts; the others are just
5008 * paranoia.
5009 */
5011 "\nFROM pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p\n"
5012 " ON c.castfunc = p.oid\n"
5013 " LEFT JOIN pg_catalog.pg_type ts\n"
5014 " ON c.castsource = ts.oid\n"
5015 " LEFT JOIN pg_catalog.pg_namespace ns\n"
5016 " ON ns.oid = ts.typnamespace\n"
5017 " LEFT JOIN pg_catalog.pg_type tt\n"
5018 " ON c.casttarget = tt.oid\n"
5019 " LEFT JOIN pg_catalog.pg_namespace nt\n"
5020 " ON nt.oid = tt.typnamespace\n");
5021
5022 if (verbose)
5024 " LEFT JOIN pg_catalog.pg_description d\n"
5025 " ON d.classoid = c.tableoid AND d.objoid = "
5026 "c.oid AND d.objsubid = 0\n");
5027
5028 appendPQExpBufferStr(&buf, "WHERE ( (true");
5029
5030 /*
5031 * Match name pattern against either internal or external name of either
5032 * castsource or casttarget
5033 */
5034 if (!validateSQLNamePattern(&buf, pattern, true, false,
5035 "ns.nspname", "ts.typname",
5036 "pg_catalog.format_type(ts.oid, NULL)",
5037 "pg_catalog.pg_type_is_visible(ts.oid)",
5038 NULL, 3))
5039 goto error_return;
5040
5041 appendPQExpBufferStr(&buf, ") OR (true");
5042
5043 if (!validateSQLNamePattern(&buf, pattern, true, false,
5044 "nt.nspname", "tt.typname",
5045 "pg_catalog.format_type(tt.oid, NULL)",
5046 "pg_catalog.pg_type_is_visible(tt.oid)",
5047 NULL, 3))
5048 goto error_return;
5049
5050 appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;");
5051
5052 res = PSQLexec(buf.data);
5054 if (!res)
5055 return false;
5056
5057 myopt.title = _("List of casts");
5058 myopt.translate_header = true;
5059 myopt.translate_columns = translate_columns;
5060 myopt.n_translate_columns = lengthof(translate_columns);
5061
5062 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5063
5064 PQclear(res);
5065 return true;
5066
5067error_return:
5069 return false;
5070}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 5078 of file describe.c.

5079{
5081 PGresult *res;
5082 printQueryOpt myopt = pset.popt;
5083 static const bool translate_columns[] = {false, false, false, false, false, false, false, true, false};
5084
5086
5088 "SELECT\n"
5089 " n.nspname AS \"%s\",\n"
5090 " c.collname AS \"%s\",\n",
5091 gettext_noop("Schema"),
5092 gettext_noop("Name"));
5093
5094 if (pset.sversion >= 100000)
5096 " CASE c.collprovider "
5097 "WHEN " CppAsString2(COLLPROVIDER_DEFAULT) " THEN 'default' "
5098 "WHEN " CppAsString2(COLLPROVIDER_BUILTIN) " THEN 'builtin' "
5099 "WHEN " CppAsString2(COLLPROVIDER_LIBC) " THEN 'libc' "
5100 "WHEN " CppAsString2(COLLPROVIDER_ICU) " THEN 'icu' "
5101 "END AS \"%s\",\n",
5102 gettext_noop("Provider"));
5103 else
5105 " 'libc' AS \"%s\",\n",
5106 gettext_noop("Provider"));
5107
5109 " c.collcollate AS \"%s\",\n"
5110 " c.collctype AS \"%s\",\n",
5111 gettext_noop("Collate"),
5112 gettext_noop("Ctype"));
5113
5114 if (pset.sversion >= 170000)
5116 " c.colllocale AS \"%s\",\n",
5117 gettext_noop("Locale"));
5118 else if (pset.sversion >= 150000)
5120 " c.colliculocale AS \"%s\",\n",
5121 gettext_noop("Locale"));
5122 else
5124 " c.collcollate AS \"%s\",\n",
5125 gettext_noop("Locale"));
5126
5127 if (pset.sversion >= 160000)
5129 " c.collicurules AS \"%s\",\n",
5130 gettext_noop("ICU Rules"));
5131 else
5133 " NULL AS \"%s\",\n",
5134 gettext_noop("ICU Rules"));
5135
5136 if (pset.sversion >= 120000)
5138 " CASE WHEN c.collisdeterministic THEN '%s' ELSE '%s' END AS \"%s\"",
5139 gettext_noop("yes"), gettext_noop("no"),
5140 gettext_noop("Deterministic?"));
5141 else
5143 " '%s' AS \"%s\"",
5144 gettext_noop("yes"),
5145 gettext_noop("Deterministic?"));
5146
5147 if (verbose)
5149 ",\n pg_catalog.obj_description(c.oid, 'pg_collation') AS \"%s\"",
5150 gettext_noop("Description"));
5151
5153 "\nFROM pg_catalog.pg_collation c, pg_catalog.pg_namespace n\n"
5154 "WHERE n.oid = c.collnamespace\n");
5155
5156 if (!showSystem && !pattern)
5157 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
5158 " AND n.nspname <> 'information_schema'\n");
5159
5160 /*
5161 * Hide collations that aren't usable in the current database's encoding.
5162 * If you think to change this, note that pg_collation_is_visible rejects
5163 * unusable collations, so you will need to hack name pattern processing
5164 * somehow to avoid inconsistent behavior.
5165 */
5166 appendPQExpBufferStr(&buf, " AND c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))\n");
5167
5168 if (!validateSQLNamePattern(&buf, pattern, true, false,
5169 "n.nspname", "c.collname", NULL,
5170 "pg_catalog.pg_collation_is_visible(c.oid)",
5171 NULL, 3))
5172 {
5174 return false;
5175 }
5176
5177 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5178
5179 res = PSQLexec(buf.data);
5181 if (!res)
5182 return false;
5183
5184 myopt.title = _("List of collations");
5185 myopt.translate_header = true;
5186 myopt.translate_columns = translate_columns;
5187 myopt.n_translate_columns = lengthof(translate_columns);
5188
5189 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5190
5191 PQclear(res);
5192 return true;
5193}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, _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 4630 of file describe.c.

4631{
4633 PGresult *res;
4634 printQueryOpt myopt = pset.popt;
4635 static const bool translate_columns[] =
4636 {false, false, false, false, true, false};
4637
4639
4641 "SELECT n.nspname AS \"%s\",\n"
4642 " c.conname AS \"%s\",\n"
4643 " pg_catalog.pg_encoding_to_char(c.conforencoding) AS \"%s\",\n"
4644 " pg_catalog.pg_encoding_to_char(c.contoencoding) AS \"%s\",\n"
4645 " CASE WHEN c.condefault THEN '%s'\n"
4646 " ELSE '%s' END AS \"%s\"",
4647 gettext_noop("Schema"),
4648 gettext_noop("Name"),
4649 gettext_noop("Source"),
4650 gettext_noop("Destination"),
4651 gettext_noop("yes"), gettext_noop("no"),
4652 gettext_noop("Default?"));
4653
4654 if (verbose)
4656 ",\n d.description AS \"%s\"",
4657 gettext_noop("Description"));
4658
4660 "\nFROM pg_catalog.pg_conversion c\n"
4661 " JOIN pg_catalog.pg_namespace n "
4662 "ON n.oid = c.connamespace\n");
4663
4664 if (verbose)
4666 "LEFT JOIN pg_catalog.pg_description d "
4667 "ON d.classoid = c.tableoid\n"
4668 " AND d.objoid = c.oid "
4669 "AND d.objsubid = 0\n");
4670
4671 appendPQExpBufferStr(&buf, "WHERE true\n");
4672
4673 if (!showSystem && !pattern)
4674 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4675 " AND n.nspname <> 'information_schema'\n");
4676
4677 if (!validateSQLNamePattern(&buf, pattern, true, false,
4678 "n.nspname", "c.conname", NULL,
4679 "pg_catalog.pg_conversion_is_visible(c.oid)",
4680 NULL, 3))
4681 {
4683 return false;
4684 }
4685
4686 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4687
4688 res = PSQLexec(buf.data);
4690 if (!res)
4691 return false;
4692
4693 myopt.title = _("List of conversions");
4694 myopt.translate_header = true;
4695 myopt.translate_columns = translate_columns;
4696 myopt.n_translate_columns = lengthof(translate_columns);
4697
4698 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4699
4700 PQclear(res);
4701 return true;
4702}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 3858 of file describe.c.

3859{
3861 PGresult *res;
3862 printQueryOpt myopt = pset.popt;
3863 bool havewhere;
3864
3866
3867 printfPQExpBuffer(&buf, "SELECT rolname AS \"%s\", datname AS \"%s\",\n"
3868 "pg_catalog.array_to_string(setconfig, E'\\n') AS \"%s\"\n"
3869 "FROM pg_catalog.pg_db_role_setting s\n"
3870 "LEFT JOIN pg_catalog.pg_database d ON d.oid = setdatabase\n"
3871 "LEFT JOIN pg_catalog.pg_roles r ON r.oid = setrole\n",
3872 gettext_noop("Role"),
3873 gettext_noop("Database"),
3874 gettext_noop("Settings"));
3875 if (!validateSQLNamePattern(&buf, pattern, false, false,
3876 NULL, "r.rolname", NULL, NULL, &havewhere, 1))
3877 goto error_return;
3878 if (!validateSQLNamePattern(&buf, pattern2, havewhere, false,
3879 NULL, "d.datname", NULL, NULL,
3880 NULL, 1))
3881 goto error_return;
3882 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
3883
3884 res = PSQLexec(buf.data);
3886 if (!res)
3887 return false;
3888
3889 /*
3890 * Most functions in this file are content to print an empty table when
3891 * there are no matching objects. We intentionally deviate from that
3892 * here, but only in !quiet mode, because of the possibility that the user
3893 * is confused about what the two pattern arguments mean.
3894 */
3895 if (PQntuples(res) == 0 && !pset.quiet)
3896 {
3897 if (pattern && pattern2)
3898 pg_log_error("Did not find any settings for role \"%s\" and database \"%s\".",
3899 pattern, pattern2);
3900 else if (pattern)
3901 pg_log_error("Did not find any settings for role \"%s\".",
3902 pattern);
3903 else
3904 pg_log_error("Did not find any settings.");
3905 }
3906 else
3907 {
3908 myopt.title = _("List of settings");
3909 myopt.translate_header = true;
3910
3911 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
3912 }
3913
3914 PQclear(res);
3915 return true;
3916
3917error_return:
3919 return false;
3920}

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

Referenced by exec_command_d().

◆ listDefaultACLs()

bool listDefaultACLs ( const char *  pattern)

Definition at line 1213 of file describe.c.

1214{
1216 PGresult *res;
1217 printQueryOpt myopt = pset.popt;
1218 static const bool translate_columns[] = {false, false, true, false};
1219
1221
1223 "SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS \"%s\",\n"
1224 " n.nspname AS \"%s\",\n"
1225 " CASE d.defaclobjtype "
1226 " WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s'"
1227 " WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' END AS \"%s\",\n"
1228 " ",
1229 gettext_noop("Owner"),
1230 gettext_noop("Schema"),
1231 DEFACLOBJ_RELATION,
1232 gettext_noop("table"),
1233 DEFACLOBJ_SEQUENCE,
1234 gettext_noop("sequence"),
1235 DEFACLOBJ_FUNCTION,
1236 gettext_noop("function"),
1237 DEFACLOBJ_TYPE,
1238 gettext_noop("type"),
1239 DEFACLOBJ_NAMESPACE,
1240 gettext_noop("schema"),
1241 DEFACLOBJ_LARGEOBJECT,
1242 gettext_noop("large object"),
1243 gettext_noop("Type"));
1244
1245 printACLColumn(&buf, "d.defaclacl");
1246
1247 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_default_acl d\n"
1248 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.defaclnamespace\n");
1249
1250 if (!validateSQLNamePattern(&buf, pattern, false, false,
1251 NULL,
1252 "n.nspname",
1253 "pg_catalog.pg_get_userbyid(d.defaclrole)",
1254 NULL,
1255 NULL, 3))
1256 goto error_return;
1257
1258 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
1259
1260 res = PSQLexec(buf.data);
1261 if (!res)
1262 goto error_return;
1263
1264 printfPQExpBuffer(&buf, _("Default access privileges"));
1265 myopt.title = buf.data;
1266 myopt.translate_header = true;
1267 myopt.translate_columns = translate_columns;
1268 myopt.n_translate_columns = lengthof(translate_columns);
1269
1270 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1271
1273 PQclear(res);
1274 return true;
1275
1276error_return:
1278 return false;
1279}

References _, appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 4547 of file describe.c.

4548{
4550 PGresult *res;
4551 printQueryOpt myopt = pset.popt;
4552
4554
4556 "SELECT n.nspname as \"%s\",\n"
4557 " t.typname as \"%s\",\n"
4558 " pg_catalog.format_type(t.typbasetype, t.typtypmod) as \"%s\",\n"
4559 " (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type bt\n"
4560 " WHERE c.oid = t.typcollation AND bt.oid = t.typbasetype AND t.typcollation <> bt.typcollation) as \"%s\",\n"
4561 " CASE WHEN t.typnotnull THEN 'not null' END as \"%s\",\n"
4562 " t.typdefault as \"%s\",\n"
4563 " pg_catalog.array_to_string(ARRAY(\n"
4564 " SELECT pg_catalog.pg_get_constraintdef(r.oid, true) FROM pg_catalog.pg_constraint r WHERE t.oid = r.contypid AND r.contype = " CppAsString2(CONSTRAINT_CHECK) " ORDER BY r.conname\n"
4565 " ), ' ') as \"%s\"",
4566 gettext_noop("Schema"),
4567 gettext_noop("Name"),
4568 gettext_noop("Type"),
4569 gettext_noop("Collation"),
4570 gettext_noop("Nullable"),
4571 gettext_noop("Default"),
4572 gettext_noop("Check"));
4573
4574 if (verbose)
4575 {
4576 appendPQExpBufferStr(&buf, ",\n ");
4577 printACLColumn(&buf, "t.typacl");
4579 ",\n d.description as \"%s\"",
4580 gettext_noop("Description"));
4581 }
4582
4584 "\nFROM pg_catalog.pg_type t\n"
4585 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
4586
4587 if (verbose)
4589 " LEFT JOIN pg_catalog.pg_description d "
4590 "ON d.classoid = t.tableoid AND d.objoid = t.oid "
4591 "AND d.objsubid = 0\n");
4592
4593 appendPQExpBufferStr(&buf, "WHERE t.typtype = 'd'\n");
4594
4595 if (!showSystem && !pattern)
4596 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4597 " AND n.nspname <> 'information_schema'\n");
4598
4599 if (!validateSQLNamePattern(&buf, pattern, true, false,
4600 "n.nspname", "t.typname", NULL,
4601 "pg_catalog.pg_type_is_visible(t.oid)",
4602 NULL, 3))
4603 {
4605 return false;
4606 }
4607
4608 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4609
4610 res = PSQLexec(buf.data);
4612 if (!res)
4613 return false;
4614
4615 myopt.title = _("List of domains");
4616 myopt.translate_header = true;
4617
4618 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4619
4620 PQclear(res);
4621 return true;
4622}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 4778 of file describe.c.

4779{
4781 PGresult *res;
4782 printQueryOpt myopt = pset.popt;
4783 static const bool translate_columns[] =
4784 {false, false, false, true, false, false, false};
4785
4786 if (pset.sversion < 90300)
4787 {
4788 char sverbuf[32];
4789
4790 pg_log_error("The server (version %s) does not support event triggers.",
4792 sverbuf, sizeof(sverbuf)));
4793 return true;
4794 }
4795
4797
4799 "SELECT evtname as \"%s\", "
4800 "evtevent as \"%s\", "
4801 "pg_catalog.pg_get_userbyid(e.evtowner) as \"%s\",\n"
4802 " case evtenabled when 'O' then '%s'"
4803 " when 'R' then '%s'"
4804 " when 'A' then '%s'"
4805 " when 'D' then '%s' end as \"%s\",\n"
4806 " e.evtfoid::pg_catalog.regproc as \"%s\", "
4807 "pg_catalog.array_to_string(array(select x"
4808 " from pg_catalog.unnest(evttags) as t(x)), ', ') as \"%s\"",
4809 gettext_noop("Name"),
4810 gettext_noop("Event"),
4811 gettext_noop("Owner"),
4812 gettext_noop("enabled"),
4813 gettext_noop("replica"),
4814 gettext_noop("always"),
4815 gettext_noop("disabled"),
4816 gettext_noop("Enabled"),
4817 gettext_noop("Function"),
4818 gettext_noop("Tags"));
4819 if (verbose)
4821 ",\npg_catalog.obj_description(e.oid, 'pg_event_trigger') as \"%s\"",
4822 gettext_noop("Description"));
4824 "\nFROM pg_catalog.pg_event_trigger e ");
4825
4826 if (!validateSQLNamePattern(&buf, pattern, false, false,
4827 NULL, "evtname", NULL, NULL,
4828 NULL, 1))
4829 {
4831 return false;
4832 }
4833
4834 appendPQExpBufferStr(&buf, "ORDER BY 1");
4835
4836 res = PSQLexec(buf.data);
4838 if (!res)
4839 return false;
4840
4841 myopt.title = _("List of event triggers");
4842 myopt.translate_header = true;
4843 myopt.translate_columns = translate_columns;
4844 myopt.n_translate_columns = lengthof(translate_columns);
4845
4846 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4847
4848 PQclear(res);
4849 return true;
4850}

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, _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 4858 of file describe.c.

4859{
4861 PGresult *res;
4862 printQueryOpt myopt = pset.popt;
4863
4864 if (pset.sversion < 100000)
4865 {
4866 char sverbuf[32];
4867
4868 pg_log_error("The server (version %s) does not support extended statistics.",
4870 sverbuf, sizeof(sverbuf)));
4871 return true;
4872 }
4873
4876 "SELECT \n"
4877 "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text AS \"%s\", \n"
4878 "es.stxname AS \"%s\", \n",
4879 gettext_noop("Schema"),
4880 gettext_noop("Name"));
4881
4882 if (pset.sversion >= 140000)
4884 "pg_catalog.format('%%s FROM %%s', \n"
4885 " pg_catalog.pg_get_statisticsobjdef_columns(es.oid), \n"
4886 " es.stxrelid::pg_catalog.regclass) AS \"%s\"",
4887 gettext_noop("Definition"));
4888 else
4890 "pg_catalog.format('%%s FROM %%s', \n"
4891 " (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(a.attname),', ') \n"
4892 " FROM pg_catalog.unnest(es.stxkeys) s(attnum) \n"
4893 " JOIN pg_catalog.pg_attribute a \n"
4894 " ON (es.stxrelid = a.attrelid \n"
4895 " AND a.attnum = s.attnum \n"
4896 " AND NOT a.attisdropped)), \n"
4897 "es.stxrelid::pg_catalog.regclass) AS \"%s\"",
4898 gettext_noop("Definition"));
4899
4901 ",\nCASE WHEN " CppAsString2(STATS_EXT_NDISTINCT) " = any(es.stxkind) THEN 'defined' \n"
4902 "END AS \"%s\", \n"
4903 "CASE WHEN " CppAsString2(STATS_EXT_DEPENDENCIES) " = any(es.stxkind) THEN 'defined' \n"
4904 "END AS \"%s\"",
4905 gettext_noop("Ndistinct"),
4906 gettext_noop("Dependencies"));
4907
4908 /*
4909 * Include the MCV statistics kind.
4910 */
4911 if (pset.sversion >= 120000)
4912 {
4914 ",\nCASE WHEN " CppAsString2(STATS_EXT_MCV) " = any(es.stxkind) THEN 'defined' \n"
4915 "END AS \"%s\" ",
4916 gettext_noop("MCV"));
4917 }
4918
4920 " \nFROM pg_catalog.pg_statistic_ext es \n");
4921
4922 if (!validateSQLNamePattern(&buf, pattern,
4923 false, false,
4924 "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text", "es.stxname",
4925 NULL, "pg_catalog.pg_statistics_obj_is_visible(es.oid)",
4926 NULL, 3))
4927 {
4929 return false;
4930 }
4931
4932 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4933
4934 res = PSQLexec(buf.data);
4936 if (!res)
4937 return false;
4938
4939 myopt.title = _("List of extended statistics");
4940 myopt.translate_header = true;
4941
4942 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4943
4944 PQclear(res);
4945 return true;
4946}

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

Referenced by exec_command_d().

◆ listExtensionContents()

bool listExtensionContents ( const char *  pattern)

Definition at line 6231 of file describe.c.

6232{
6234 PGresult *res;
6235 int i;
6236
6239 "SELECT e.extname, e.oid\n"
6240 "FROM pg_catalog.pg_extension e\n");
6241
6242 if (!validateSQLNamePattern(&buf, pattern,
6243 false, false,
6244 NULL, "e.extname", NULL,
6245 NULL,
6246 NULL, 1))
6247 {
6249 return false;
6250 }
6251
6252 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6253
6254 res = PSQLexec(buf.data);
6256 if (!res)
6257 return false;
6258
6259 if (PQntuples(res) == 0)
6260 {
6261 if (!pset.quiet)
6262 {
6263 if (pattern)
6264 pg_log_error("Did not find any extension named \"%s\".",
6265 pattern);
6266 else
6267 pg_log_error("Did not find any extensions.");
6268 }
6269 PQclear(res);
6270 return false;
6271 }
6272
6273 for (i = 0; i < PQntuples(res); i++)
6274 {
6275 const char *extname;
6276 const char *oid;
6277
6278 extname = PQgetvalue(res, i, 0);
6279 oid = PQgetvalue(res, i, 1);
6280
6281 if (!listOneExtensionContents(extname, oid))
6282 {
6283 PQclear(res);
6284 return false;
6285 }
6286 if (cancel_pressed)
6287 {
6288 PQclear(res);
6289 return false;
6290 }
6291 }
6292
6293 PQclear(res);
6294 return true;
6295}
static bool listOneExtensionContents(const char *extname, const char *oid)
Definition: describe.c:6298

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

Referenced by exec_command_d().

◆ listExtensions()

bool listExtensions ( const char *  pattern)

Definition at line 6177 of file describe.c.

6178{
6180 PGresult *res;
6181 printQueryOpt myopt = pset.popt;
6182
6185 "SELECT e.extname AS \"%s\", "
6186 "e.extversion AS \"%s\", ae.default_version AS \"%s\","
6187 "n.nspname AS \"%s\", d.description AS \"%s\"\n"
6188 "FROM pg_catalog.pg_extension e "
6189 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace "
6190 "LEFT JOIN pg_catalog.pg_description d ON d.objoid = e.oid "
6191 "LEFT JOIN pg_catalog.pg_available_extensions() ae(name, default_version, comment) ON ae.name = e.extname "
6192 "AND d.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass\n",
6193 gettext_noop("Name"),
6194 gettext_noop("Version"),
6195 gettext_noop("Default version"),
6196 gettext_noop("Schema"),
6197 gettext_noop("Description"));
6198
6199 if (!validateSQLNamePattern(&buf, pattern,
6200 false, false,
6201 NULL, "e.extname", NULL,
6202 NULL,
6203 NULL, 1))
6204 {
6206 return false;
6207 }
6208
6209 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6210
6211 res = PSQLexec(buf.data);
6213 if (!res)
6214 return false;
6215
6216 myopt.title = _("List of installed extensions");
6217 myopt.translate_header = true;
6218
6219 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6220
6221 PQclear(res);
6222 return true;
6223}

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

Referenced by exec_command_d().

◆ listForeignDataWrappers()

bool listForeignDataWrappers ( const char *  pattern,
bool  verbose 
)

Definition at line 5903 of file describe.c.

5904{
5906 PGresult *res;
5907 printQueryOpt myopt = pset.popt;
5908
5911 "SELECT fdw.fdwname AS \"%s\",\n"
5912 " pg_catalog.pg_get_userbyid(fdw.fdwowner) AS \"%s\",\n"
5913 " fdw.fdwhandler::pg_catalog.regproc AS \"%s\",\n"
5914 " fdw.fdwvalidator::pg_catalog.regproc AS \"%s\"",
5915 gettext_noop("Name"),
5916 gettext_noop("Owner"),
5917 gettext_noop("Handler"),
5918 gettext_noop("Validator"));
5919
5920 if (verbose)
5921 {
5922 appendPQExpBufferStr(&buf, ",\n ");
5923 printACLColumn(&buf, "fdwacl");
5925 ",\n CASE WHEN fdwoptions IS NULL THEN '' ELSE "
5926 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
5927 " pg_catalog.quote_ident(option_name) || ' ' || "
5928 " pg_catalog.quote_literal(option_value) FROM "
5929 " pg_catalog.pg_options_to_table(fdwoptions)), ', ') || ')' "
5930 " END AS \"%s\""
5931 ",\n d.description AS \"%s\" ",
5932 gettext_noop("FDW options"),
5933 gettext_noop("Description"));
5934 }
5935
5936 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
5937
5938 if (verbose)
5940 "LEFT JOIN pg_catalog.pg_description d\n"
5941 " ON d.classoid = fdw.tableoid "
5942 "AND d.objoid = fdw.oid AND d.objsubid = 0\n");
5943
5944 if (!validateSQLNamePattern(&buf, pattern, false, false,
5945 NULL, "fdwname", NULL, NULL,
5946 NULL, 1))
5947 {
5949 return false;
5950 }
5951
5952 appendPQExpBufferStr(&buf, "ORDER BY 1;");
5953
5954 res = PSQLexec(buf.data);
5956 if (!res)
5957 return false;
5958
5959 myopt.title = _("List of foreign-data wrappers");
5960 myopt.translate_header = true;
5961
5962 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5963
5964 PQclear(res);
5965 return true;
5966}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 5974 of file describe.c.

5975{
5977 PGresult *res;
5978 printQueryOpt myopt = pset.popt;
5979
5982 "SELECT s.srvname AS \"%s\",\n"
5983 " pg_catalog.pg_get_userbyid(s.srvowner) AS \"%s\",\n"
5984 " f.fdwname AS \"%s\"",
5985 gettext_noop("Name"),
5986 gettext_noop("Owner"),
5987 gettext_noop("Foreign-data wrapper"));
5988
5989 if (verbose)
5990 {
5991 appendPQExpBufferStr(&buf, ",\n ");
5992 printACLColumn(&buf, "s.srvacl");
5994 ",\n"
5995 " s.srvtype AS \"%s\",\n"
5996 " s.srvversion AS \"%s\",\n"
5997 " CASE WHEN srvoptions IS NULL THEN '' ELSE "
5998 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
5999 " pg_catalog.quote_ident(option_name) || ' ' || "
6000 " pg_catalog.quote_literal(option_value) FROM "
6001 " pg_catalog.pg_options_to_table(srvoptions)), ', ') || ')' "
6002 " END AS \"%s\",\n"
6003 " d.description AS \"%s\"",
6004 gettext_noop("Type"),
6005 gettext_noop("Version"),
6006 gettext_noop("FDW options"),
6007 gettext_noop("Description"));
6008 }
6009
6011 "\nFROM pg_catalog.pg_foreign_server s\n"
6012 " JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid=s.srvfdw\n");
6013
6014 if (verbose)
6016 "LEFT JOIN pg_catalog.pg_description d\n "
6017 "ON d.classoid = s.tableoid AND d.objoid = s.oid "
6018 "AND d.objsubid = 0\n");
6019
6020 if (!validateSQLNamePattern(&buf, pattern, false, false,
6021 NULL, "s.srvname", NULL, NULL,
6022 NULL, 1))
6023 {
6025 return false;
6026 }
6027
6028 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6029
6030 res = PSQLexec(buf.data);
6032 if (!res)
6033 return false;
6034
6035 myopt.title = _("List of foreign servers");
6036 myopt.translate_header = true;
6037
6038 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6039
6040 PQclear(res);
6041 return true;
6042}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 6105 of file describe.c.

6106{
6108 PGresult *res;
6109 printQueryOpt myopt = pset.popt;
6110
6113 "SELECT n.nspname AS \"%s\",\n"
6114 " c.relname AS \"%s\",\n"
6115 " s.srvname AS \"%s\"",
6116 gettext_noop("Schema"),
6117 gettext_noop("Table"),
6118 gettext_noop("Server"));
6119
6120 if (verbose)
6122 ",\n CASE WHEN ftoptions IS NULL THEN '' ELSE "
6123 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6124 " pg_catalog.quote_ident(option_name) || ' ' || "
6125 " pg_catalog.quote_literal(option_value) FROM "
6126 " pg_catalog.pg_options_to_table(ftoptions)), ', ') || ')' "
6127 " END AS \"%s\",\n"
6128 " d.description AS \"%s\"",
6129 gettext_noop("FDW options"),
6130 gettext_noop("Description"));
6131
6133 "\nFROM pg_catalog.pg_foreign_table ft\n"
6134 " INNER JOIN pg_catalog.pg_class c"
6135 " ON c.oid = ft.ftrelid\n"
6136 " INNER JOIN pg_catalog.pg_namespace n"
6137 " ON n.oid = c.relnamespace\n"
6138 " INNER JOIN pg_catalog.pg_foreign_server s"
6139 " ON s.oid = ft.ftserver\n");
6140 if (verbose)
6142 " LEFT JOIN pg_catalog.pg_description d\n"
6143 " ON d.classoid = c.tableoid AND "
6144 "d.objoid = c.oid AND d.objsubid = 0\n");
6145
6146 if (!validateSQLNamePattern(&buf, pattern, false, false,
6147 "n.nspname", "c.relname", NULL,
6148 "pg_catalog.pg_table_is_visible(c.oid)",
6149 NULL, 3))
6150 {
6152 return false;
6153 }
6154
6155 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
6156
6157 res = PSQLexec(buf.data);
6159 if (!res)
6160 return false;
6161
6162 myopt.title = _("List of foreign tables");
6163 myopt.translate_header = true;
6164
6165 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6166
6167 PQclear(res);
6168 return true;
6169}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 4471 of file describe.c.

4472{
4474 PGresult *res;
4475 printQueryOpt myopt = pset.popt;
4476
4478
4480 "SELECT l.lanname AS \"%s\",\n"
4481 " pg_catalog.pg_get_userbyid(l.lanowner) as \"%s\",\n"
4482 " l.lanpltrusted AS \"%s\"",
4483 gettext_noop("Name"),
4484 gettext_noop("Owner"),
4485 gettext_noop("Trusted"));
4486
4487 if (verbose)
4488 {
4490 ",\n NOT l.lanispl AS \"%s\",\n"
4491 " l.lanplcallfoid::pg_catalog.regprocedure AS \"%s\",\n"
4492 " l.lanvalidator::pg_catalog.regprocedure AS \"%s\",\n "
4493 "l.laninline::pg_catalog.regprocedure AS \"%s\",\n ",
4494 gettext_noop("Internal language"),
4495 gettext_noop("Call handler"),
4496 gettext_noop("Validator"),
4497 gettext_noop("Inline handler"));
4498 printACLColumn(&buf, "l.lanacl");
4499 }
4500
4502 ",\n d.description AS \"%s\""
4503 "\nFROM pg_catalog.pg_language l\n"
4504 "LEFT JOIN pg_catalog.pg_description d\n"
4505 " ON d.classoid = l.tableoid AND d.objoid = l.oid\n"
4506 " AND d.objsubid = 0\n",
4507 gettext_noop("Description"));
4508
4509 if (pattern)
4510 {
4511 if (!validateSQLNamePattern(&buf, pattern, false, false,
4512 NULL, "l.lanname", NULL, NULL,
4513 NULL, 2))
4514 {
4516 return false;
4517 }
4518 }
4519
4520 if (!showSystem && !pattern)
4521 appendPQExpBufferStr(&buf, "WHERE l.lanplcallfoid != 0\n");
4522
4523
4524 appendPQExpBufferStr(&buf, "ORDER BY 1;");
4525
4526 res = PSQLexec(buf.data);
4528 if (!res)
4529 return false;
4530
4531 myopt.title = _("List of languages");
4532 myopt.translate_header = true;
4533
4534 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4535
4536 PQclear(res);
4537 return true;
4538}

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

Referenced by exec_command_d().

◆ listLargeObjects()

bool listLargeObjects ( bool  verbose)

Definition at line 7279 of file describe.c.

7280{
7282 PGresult *res;
7283 printQueryOpt myopt = pset.popt;
7284
7286
7288 "SELECT oid as \"%s\",\n"
7289 " pg_catalog.pg_get_userbyid(lomowner) as \"%s\",\n ",
7290 gettext_noop("ID"),
7291 gettext_noop("Owner"));
7292
7293 if (verbose)
7294 {
7295 printACLColumn(&buf, "lomacl");
7296 appendPQExpBufferStr(&buf, ",\n ");
7297 }
7298
7300 "pg_catalog.obj_description(oid, 'pg_largeobject') as \"%s\"\n"
7301 "FROM pg_catalog.pg_largeobject_metadata\n"
7302 "ORDER BY oid",
7303 gettext_noop("Description"));
7304
7305 res = PSQLexec(buf.data);
7307 if (!res)
7308 return false;
7309
7310 myopt.title = _("Large objects");
7311 myopt.translate_header = true;
7312
7313 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7314
7315 PQclear(res);
7316 return true;
7317}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 6298 of file describe.c.

6299{
6301 PGresult *res;
6302 PQExpBufferData title;
6303 printQueryOpt myopt = pset.popt;
6304
6307 "SELECT pg_catalog.pg_describe_object(classid, objid, 0) AS \"%s\"\n"
6308 "FROM pg_catalog.pg_depend\n"
6309 "WHERE refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass AND refobjid = '%s' AND deptype = 'e'\n"
6310 "ORDER BY 1;",
6311 gettext_noop("Object description"),
6312 oid);
6313
6314 res = PSQLexec(buf.data);
6316 if (!res)
6317 return false;
6318
6319 initPQExpBuffer(&title);
6320 printfPQExpBuffer(&title, _("Objects in extension \"%s\""), extname);
6321 myopt.title = title.data;
6322 myopt.translate_header = true;
6323
6324 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6325
6326 termPQExpBuffer(&title);
6327 PQclear(res);
6328 return true;
6329}

References _, buf, PQExpBufferData::data, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 6893 of file describe.c.

6895{
6897 PGresult *res;
6898 printQueryOpt myopt = pset.popt;
6899 bool have_where = false;
6900 static const bool translate_columns[] = {false, false, false, false, false, false, false};
6901
6903
6905 "SELECT\n"
6906 " am.amname AS \"%s\",\n"
6907 " pg_catalog.format_type(c.opcintype, NULL) AS \"%s\",\n"
6908 " CASE\n"
6909 " WHEN c.opckeytype <> 0 AND c.opckeytype <> c.opcintype\n"
6910 " THEN pg_catalog.format_type(c.opckeytype, NULL)\n"
6911 " ELSE NULL\n"
6912 " END AS \"%s\",\n"
6913 " CASE\n"
6914 " WHEN pg_catalog.pg_opclass_is_visible(c.oid)\n"
6915 " THEN pg_catalog.format('%%I', c.opcname)\n"
6916 " ELSE pg_catalog.format('%%I.%%I', n.nspname, c.opcname)\n"
6917 " END AS \"%s\",\n"
6918 " (CASE WHEN c.opcdefault\n"
6919 " THEN '%s'\n"
6920 " ELSE '%s'\n"
6921 " END) AS \"%s\"",
6922 gettext_noop("AM"),
6923 gettext_noop("Input type"),
6924 gettext_noop("Storage type"),
6925 gettext_noop("Operator class"),
6926 gettext_noop("yes"),
6927 gettext_noop("no"),
6928 gettext_noop("Default?"));
6929 if (verbose)
6931 ",\n CASE\n"
6932 " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
6933 " THEN pg_catalog.format('%%I', of.opfname)\n"
6934 " ELSE pg_catalog.format('%%I.%%I', ofn.nspname, of.opfname)\n"
6935 " END AS \"%s\",\n"
6936 " pg_catalog.pg_get_userbyid(c.opcowner) AS \"%s\"\n",
6937 gettext_noop("Operator family"),
6938 gettext_noop("Owner"));
6940 "\nFROM pg_catalog.pg_opclass c\n"
6941 " LEFT JOIN pg_catalog.pg_am am on am.oid = c.opcmethod\n"
6942 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.opcnamespace\n"
6943 " LEFT JOIN pg_catalog.pg_type t ON t.oid = c.opcintype\n"
6944 " LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n");
6945 if (verbose)
6947 " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = c.opcfamily\n"
6948 " LEFT JOIN pg_catalog.pg_namespace ofn ON ofn.oid = of.opfnamespace\n");
6949
6950 if (access_method_pattern)
6951 if (!validateSQLNamePattern(&buf, access_method_pattern,
6952 false, false, NULL, "am.amname", NULL, NULL,
6953 &have_where, 1))
6954 goto error_return;
6955 if (type_pattern)
6956 {
6957 /* Match type name pattern against either internal or external name */
6958 if (!validateSQLNamePattern(&buf, type_pattern, have_where, false,
6959 "tn.nspname", "t.typname",
6960 "pg_catalog.format_type(t.oid, NULL)",
6961 "pg_catalog.pg_type_is_visible(t.oid)",
6962 NULL, 3))
6963 goto error_return;
6964 }
6965
6966 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
6967 res = PSQLexec(buf.data);
6969 if (!res)
6970 return false;
6971
6972 myopt.title = _("List of operator classes");
6973 myopt.translate_header = true;
6974 myopt.translate_columns = translate_columns;
6975 myopt.n_translate_columns = lengthof(translate_columns);
6976
6977 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6978
6979 PQclear(res);
6980 return true;
6981
6982error_return:
6984 return false;
6985}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 6994 of file describe.c.

6996{
6998 PGresult *res;
6999 printQueryOpt myopt = pset.popt;
7000 bool have_where = false;
7001 static const bool translate_columns[] = {false, false, false, false};
7002
7004
7006 "SELECT\n"
7007 " am.amname AS \"%s\",\n"
7008 " CASE\n"
7009 " WHEN pg_catalog.pg_opfamily_is_visible(f.oid)\n"
7010 " THEN pg_catalog.format('%%I', f.opfname)\n"
7011 " ELSE pg_catalog.format('%%I.%%I', n.nspname, f.opfname)\n"
7012 " END AS \"%s\",\n"
7013 " (SELECT\n"
7014 " pg_catalog.string_agg(pg_catalog.format_type(oc.opcintype, NULL), ', ')\n"
7015 " FROM pg_catalog.pg_opclass oc\n"
7016 " WHERE oc.opcfamily = f.oid) \"%s\"",
7017 gettext_noop("AM"),
7018 gettext_noop("Operator family"),
7019 gettext_noop("Applicable types"));
7020 if (verbose)
7022 ",\n pg_catalog.pg_get_userbyid(f.opfowner) AS \"%s\"\n",
7023 gettext_noop("Owner"));
7025 "\nFROM pg_catalog.pg_opfamily f\n"
7026 " LEFT JOIN pg_catalog.pg_am am on am.oid = f.opfmethod\n"
7027 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = f.opfnamespace\n");
7028
7029 if (access_method_pattern)
7030 if (!validateSQLNamePattern(&buf, access_method_pattern,
7031 false, false, NULL, "am.amname", NULL, NULL,
7032 &have_where, 1))
7033 goto error_return;
7034 if (type_pattern)
7035 {
7037 " %s EXISTS (\n"
7038 " SELECT 1\n"
7039 " FROM pg_catalog.pg_type t\n"
7040 " JOIN pg_catalog.pg_opclass oc ON oc.opcintype = t.oid\n"
7041 " LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n"
7042 " WHERE oc.opcfamily = f.oid\n",
7043 have_where ? "AND" : "WHERE");
7044 /* Match type name pattern against either internal or external name */
7045 if (!validateSQLNamePattern(&buf, type_pattern, true, false,
7046 "tn.nspname", "t.typname",
7047 "pg_catalog.format_type(t.oid, NULL)",
7048 "pg_catalog.pg_type_is_visible(t.oid)",
7049 NULL, 3))
7050 goto error_return;
7051 appendPQExpBufferStr(&buf, " )\n");
7052 }
7053
7054 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
7055 res = PSQLexec(buf.data);
7057 if (!res)
7058 return false;
7059
7060 myopt.title = _("List of operator families");
7061 myopt.translate_header = true;
7062 myopt.translate_columns = translate_columns;
7063 myopt.n_translate_columns = lengthof(translate_columns);
7064
7065 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7066
7067 PQclear(res);
7068 return true;
7069
7070error_return:
7072 return false;
7073}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 7190 of file describe.c.

7192{
7194 PGresult *res;
7195 printQueryOpt myopt = pset.popt;
7196 bool have_where = false;
7197 static const bool translate_columns[] = {false, false, false, false, false, false};
7198
7200
7202 "SELECT\n"
7203 " am.amname AS \"%s\",\n"
7204 " CASE\n"
7205 " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
7206 " THEN pg_catalog.format('%%I', of.opfname)\n"
7207 " ELSE pg_catalog.format('%%I.%%I', ns.nspname, of.opfname)\n"
7208 " END AS \"%s\",\n"
7209 " pg_catalog.format_type(ap.amproclefttype, NULL) AS \"%s\",\n"
7210 " pg_catalog.format_type(ap.amprocrighttype, NULL) AS \"%s\",\n"
7211 " ap.amprocnum AS \"%s\"\n",
7212 gettext_noop("AM"),
7213 gettext_noop("Operator family"),
7214 gettext_noop("Registered left type"),
7215 gettext_noop("Registered right type"),
7216 gettext_noop("Number"));
7217
7218 if (!verbose)
7220 ", p.proname AS \"%s\"\n",
7221 gettext_noop("Function"));
7222 else
7224 ", ap.amproc::pg_catalog.regprocedure AS \"%s\"\n",
7225 gettext_noop("Function"));
7226
7228 "FROM pg_catalog.pg_amproc ap\n"
7229 " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = ap.amprocfamily\n"
7230 " LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod\n"
7231 " LEFT JOIN pg_catalog.pg_namespace ns ON of.opfnamespace = ns.oid\n"
7232 " LEFT JOIN pg_catalog.pg_proc p ON ap.amproc = p.oid\n");
7233
7234 if (access_method_pattern)
7235 {
7236 if (!validateSQLNamePattern(&buf, access_method_pattern,
7237 false, false, NULL, "am.amname",
7238 NULL, NULL,
7239 &have_where, 1))
7240 goto error_return;
7241 }
7242 if (family_pattern)
7243 {
7244 if (!validateSQLNamePattern(&buf, family_pattern, have_where, false,
7245 "ns.nspname", "of.opfname", NULL, NULL,
7246 NULL, 3))
7247 goto error_return;
7248 }
7249
7250 appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
7251 " ap.amproclefttype = ap.amprocrighttype DESC,\n"
7252 " 3, 4, 5;");
7253
7254 res = PSQLexec(buf.data);
7256 if (!res)
7257 return false;
7258
7259 myopt.title = _("List of support functions of operator families");
7260 myopt.translate_header = true;
7261 myopt.translate_columns = translate_columns;
7262 myopt.n_translate_columns = lengthof(translate_columns);
7263
7264 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7265
7266 PQclear(res);
7267 return true;
7268
7269error_return:
7271 return false;
7272}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 7083 of file describe.c.

7085{
7087 PGresult *res;
7088 printQueryOpt myopt = pset.popt;
7089 bool have_where = false;
7090
7091 static const bool translate_columns[] = {false, false, false, false, false, false, true};
7092
7094
7096 "SELECT\n"
7097 " am.amname AS \"%s\",\n"
7098 " CASE\n"
7099 " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
7100 " THEN pg_catalog.format('%%I', of.opfname)\n"
7101 " ELSE pg_catalog.format('%%I.%%I', nsf.nspname, of.opfname)\n"
7102 " END AS \"%s\",\n"
7103 " o.amopopr::pg_catalog.regoperator AS \"%s\"\n,"
7104 " o.amopstrategy AS \"%s\",\n"
7105 " CASE o.amoppurpose\n"
7106 " WHEN " CppAsString2(AMOP_ORDER) " THEN '%s'\n"
7107 " WHEN " CppAsString2(AMOP_SEARCH) " THEN '%s'\n"
7108 " END AS \"%s\"\n",
7109 gettext_noop("AM"),
7110 gettext_noop("Operator family"),
7111 gettext_noop("Operator"),
7112 gettext_noop("Strategy"),
7113 gettext_noop("ordering"),
7114 gettext_noop("search"),
7115 gettext_noop("Purpose"));
7116
7117 if (verbose)
7119 ", ofs.opfname AS \"%s\",\n"
7120 " CASE\n"
7121 " WHEN p.proleakproof THEN '%s'\n"
7122 " ELSE '%s'\n"
7123 " END AS \"%s\"\n",
7124 gettext_noop("Sort opfamily"),
7125 gettext_noop("yes"),
7126 gettext_noop("no"),
7127 gettext_noop("Leakproof?"));
7129 "FROM pg_catalog.pg_amop o\n"
7130 " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = o.amopfamily\n"
7131 " LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod AND am.oid = o.amopmethod\n"
7132 " LEFT JOIN pg_catalog.pg_namespace nsf ON of.opfnamespace = nsf.oid\n");
7133 if (verbose)
7135 " LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n"
7136 " LEFT JOIN pg_catalog.pg_operator op ON op.oid = o.amopopr\n"
7137 " LEFT JOIN pg_catalog.pg_proc p ON p.oid = op.oprcode\n");
7138
7139 if (access_method_pattern)
7140 {
7141 if (!validateSQLNamePattern(&buf, access_method_pattern,
7142 false, false, NULL, "am.amname",
7143 NULL, NULL,
7144 &have_where, 1))
7145 goto error_return;
7146 }
7147
7148 if (family_pattern)
7149 {
7150 if (!validateSQLNamePattern(&buf, family_pattern, have_where, false,
7151 "nsf.nspname", "of.opfname", NULL, NULL,
7152 NULL, 3))
7153 goto error_return;
7154 }
7155
7156 appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
7157 " o.amoplefttype = o.amoprighttype DESC,\n"
7158 " pg_catalog.format_type(o.amoplefttype, NULL),\n"
7159 " pg_catalog.format_type(o.amoprighttype, NULL),\n"
7160 " o.amopstrategy;");
7161
7162 res = PSQLexec(buf.data);
7164 if (!res)
7165 return false;
7166
7167 myopt.title = _("List of operators of operator families");
7168 myopt.translate_header = true;
7169 myopt.translate_columns = translate_columns;
7170 myopt.n_translate_columns = lengthof(translate_columns);
7171
7172 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7173
7174 PQclear(res);
7175 return true;
7176
7177error_return:
7179 return false;
7180}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 4261 of file describe.c.

4262{
4263 bool showTables = strchr(reltypes, 't') != NULL;
4264 bool showIndexes = strchr(reltypes, 'i') != NULL;
4265 bool showNested = strchr(reltypes, 'n') != NULL;
4267 PQExpBufferData title;
4268 PGresult *res;
4269 printQueryOpt myopt = pset.popt;
4270 bool translate_columns[] = {false, false, false, false, false, false, false, false, false, false};
4271 const char *tabletitle;
4272 bool mixed_output = false;
4273
4274 /*
4275 * Note: Declarative table partitioning is only supported as of Pg 10.0.
4276 */
4277 if (pset.sversion < 100000)
4278 {
4279 char sverbuf[32];
4280
4281 pg_log_error("The server (version %s) does not support declarative table partitioning.",
4283 sverbuf, sizeof(sverbuf)));
4284 return true;
4285 }
4286
4287 /* If no relation kind was selected, show them all */
4288 if (!showTables && !showIndexes)
4289 showTables = showIndexes = true;
4290
4291 if (showIndexes && !showTables)
4292 tabletitle = _("List of partitioned indexes"); /* \dPi */
4293 else if (showTables && !showIndexes)
4294 tabletitle = _("List of partitioned tables"); /* \dPt */
4295 else
4296 {
4297 /* show all kinds */
4298 tabletitle = _("List of partitioned relations");
4299 mixed_output = true;
4300 }
4301
4303
4305 "SELECT n.nspname as \"%s\",\n"
4306 " c.relname as \"%s\",\n"
4307 " pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"",
4308 gettext_noop("Schema"),
4309 gettext_noop("Name"),
4310 gettext_noop("Owner"));
4311
4312 if (mixed_output)
4313 {
4315 ",\n CASE c.relkind"
4316 " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
4317 " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
4318 " END as \"%s\"",
4319 gettext_noop("partitioned table"),
4320 gettext_noop("partitioned index"),
4321 gettext_noop("Type"));
4322
4323 translate_columns[3] = true;
4324 }
4325
4326 if (showNested || pattern)
4328 ",\n inh.inhparent::pg_catalog.regclass as \"%s\"",
4329 gettext_noop("Parent name"));
4330
4331 if (showIndexes)
4333 ",\n c2.oid::pg_catalog.regclass as \"%s\"",
4334 gettext_noop("Table"));
4335
4336 if (verbose)
4337 {
4338 /*
4339 * Table access methods were introduced in v12, and can be set on
4340 * partitioned tables since v17.
4341 */
4342 appendPQExpBuffer(&buf, ",\n am.amname as \"%s\"",
4343 gettext_noop("Access method"));
4344
4345 if (showNested)
4346 {
4348 ",\n s.dps as \"%s\"",
4349 gettext_noop("Leaf partition size"));
4351 ",\n s.tps as \"%s\"",
4352 gettext_noop("Total size"));
4353 }
4354 else
4355 /* Sizes of all partitions are considered in this case. */
4357 ",\n s.tps as \"%s\"",
4358 gettext_noop("Total size"));
4359
4361 ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"",
4362 gettext_noop("Description"));
4363 }
4364
4366 "\nFROM pg_catalog.pg_class c"
4367 "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace");
4368
4369 if (showIndexes)
4371 "\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid"
4372 "\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid");
4373
4374 if (showNested || pattern)
4376 "\n LEFT JOIN pg_catalog.pg_inherits inh ON c.oid = inh.inhrelid");
4377
4378 if (verbose)
4379 {
4381 "\n LEFT JOIN pg_catalog.pg_am am ON c.relam = am.oid");
4382
4383 if (pset.sversion < 120000)
4384 {
4386 ",\n LATERAL (WITH RECURSIVE d\n"
4387 " AS (SELECT inhrelid AS oid, 1 AS level\n"
4388 " FROM pg_catalog.pg_inherits\n"
4389 " WHERE inhparent = c.oid\n"
4390 " UNION ALL\n"
4391 " SELECT inhrelid, level + 1\n"
4392 " FROM pg_catalog.pg_inherits i\n"
4393 " JOIN d ON i.inhparent = d.oid)\n"
4394 " SELECT pg_catalog.pg_size_pretty(sum(pg_catalog.pg_table_size("
4395 "d.oid))) AS tps,\n"
4396 " pg_catalog.pg_size_pretty(sum("
4397 "\n CASE WHEN d.level = 1"
4398 " THEN pg_catalog.pg_table_size(d.oid) ELSE 0 END)) AS dps\n"
4399 " FROM d) s");
4400 }
4401 else
4402 {
4403 /* PostgreSQL 12 has pg_partition_tree function */
4405 ",\n LATERAL (SELECT pg_catalog.pg_size_pretty(sum("
4406 "\n CASE WHEN ppt.isleaf AND ppt.level = 1"
4407 "\n THEN pg_catalog.pg_table_size(ppt.relid)"
4408 " ELSE 0 END)) AS dps"
4409 ",\n pg_catalog.pg_size_pretty(sum("
4410 "pg_catalog.pg_table_size(ppt.relid))) AS tps"
4411 "\n FROM pg_catalog.pg_partition_tree(c.oid) ppt) s");
4412 }
4413 }
4414
4415 appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
4416 if (showTables)
4417 appendPQExpBufferStr(&buf, CppAsString2(RELKIND_PARTITIONED_TABLE) ",");
4418 if (showIndexes)
4419 appendPQExpBufferStr(&buf, CppAsString2(RELKIND_PARTITIONED_INDEX) ",");
4420 appendPQExpBufferStr(&buf, "''"); /* dummy */
4421 appendPQExpBufferStr(&buf, ")\n");
4422
4423 appendPQExpBufferStr(&buf, !showNested && !pattern ?
4424 " AND NOT c.relispartition\n" : "");
4425
4426 if (!pattern)
4427 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4428 " AND n.nspname !~ '^pg_toast'\n"
4429 " AND n.nspname <> 'information_schema'\n");
4430
4431 if (!validateSQLNamePattern(&buf, pattern, true, false,
4432 "n.nspname", "c.relname", NULL,
4433 "pg_catalog.pg_table_is_visible(c.oid)",
4434 NULL, 3))
4435 {
4437 return false;
4438 }
4439
4440 appendPQExpBuffer(&buf, "ORDER BY \"Schema\", %s%s\"Name\";",
4441 mixed_output ? "\"Type\" DESC, " : "",
4442 showNested || pattern ? "\"Parent name\" NULLS FIRST, " : "");
4443
4444 res = PSQLexec(buf.data);
4446 if (!res)
4447 return false;
4448
4449 initPQExpBuffer(&title);
4450 appendPQExpBufferStr(&title, tabletitle);
4451
4452 myopt.title = title.data;
4453 myopt.translate_header = true;
4454 myopt.translate_columns = translate_columns;
4455 myopt.n_translate_columns = lengthof(translate_columns);
4456
4457 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4458
4459 termPQExpBuffer(&title);
4460
4461 PQclear(res);
4462 return true;
4463}

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, _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 6395 of file describe.c.

6396{
6398 PGresult *res;
6399 printQueryOpt myopt = pset.popt;
6400 static const bool translate_columns[] = {false, false, false, false, false, false, false, false, false};
6401
6402 if (pset.sversion < 100000)
6403 {
6404 char sverbuf[32];
6405
6406 pg_log_error("The server (version %s) does not support publications.",
6408 sverbuf, sizeof(sverbuf)));
6409 return true;
6410 }
6411
6413
6415 "SELECT pubname AS \"%s\",\n"
6416 " pg_catalog.pg_get_userbyid(pubowner) AS \"%s\",\n"
6417 " puballtables AS \"%s\",\n"
6418 " pubinsert AS \"%s\",\n"
6419 " pubupdate AS \"%s\",\n"
6420 " pubdelete AS \"%s\"",
6421 gettext_noop("Name"),
6422 gettext_noop("Owner"),
6423 gettext_noop("All tables"),
6424 gettext_noop("Inserts"),
6425 gettext_noop("Updates"),
6426 gettext_noop("Deletes"));
6427 if (pset.sversion >= 110000)
6429 ",\n pubtruncate AS \"%s\"",
6430 gettext_noop("Truncates"));
6431 if (pset.sversion >= 180000)
6433 ",\n (CASE pubgencols\n"
6434 " WHEN '%c' THEN 'none'\n"
6435 " WHEN '%c' THEN 'stored'\n"
6436 " END) AS \"%s\"",
6437 PUBLISH_GENCOLS_NONE,
6438 PUBLISH_GENCOLS_STORED,
6439 gettext_noop("Generated columns"));
6440 if (pset.sversion >= 130000)
6442 ",\n pubviaroot AS \"%s\"",
6443 gettext_noop("Via root"));
6444
6446 "\nFROM pg_catalog.pg_publication\n");
6447
6448 if (!validateSQLNamePattern(&buf, pattern, false, false,
6449 NULL, "pubname", NULL,
6450 NULL,
6451 NULL, 1))
6452 {
6454 return false;
6455 }
6456
6457 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6458
6459 res = PSQLexec(buf.data);
6461 if (!res)
6462 return false;
6463
6464 myopt.title = _("List of publications");
6465 myopt.translate_header = true;
6466 myopt.translate_columns = translate_columns;
6467 myopt.n_translate_columns = lengthof(translate_columns);
6468
6469 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6470
6471 PQclear(res);
6472
6473 return true;
6474}

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, _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 5201 of file describe.c.

5202{
5204 PGresult *res;
5205 printQueryOpt myopt = pset.popt;
5206 int pub_schema_tuples = 0;
5207 char **footers = NULL;
5208
5211 "SELECT n.nspname AS \"%s\",\n"
5212 " pg_catalog.pg_get_userbyid(n.nspowner) AS \"%s\"",
5213 gettext_noop("Name"),
5214 gettext_noop("Owner"));
5215
5216 if (verbose)
5217 {
5218 appendPQExpBufferStr(&buf, ",\n ");
5219 printACLColumn(&buf, "n.nspacl");
5221 ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"",
5222 gettext_noop("Description"));
5223 }
5224
5226 "\nFROM pg_catalog.pg_namespace n\n");
5227
5228 if (!showSystem && !pattern)
5230 "WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'\n");
5231
5232 if (!validateSQLNamePattern(&buf, pattern,
5233 !showSystem && !pattern, false,
5234 NULL, "n.nspname", NULL,
5235 NULL,
5236 NULL, 2))
5237 goto error_return;
5238
5239 appendPQExpBufferStr(&buf, "ORDER BY 1;");
5240
5241 res = PSQLexec(buf.data);
5242 if (!res)
5243 goto error_return;
5244
5245 myopt.title = _("List of schemas");
5246 myopt.translate_header = true;
5247
5248 if (pattern && pset.sversion >= 150000)
5249 {
5250 PGresult *result;
5251 int i;
5252
5254 "SELECT pubname \n"
5255 "FROM pg_catalog.pg_publication p\n"
5256 " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
5257 " JOIN pg_catalog.pg_namespace n ON n.oid = pn.pnnspid \n"
5258 "WHERE n.nspname = '%s'\n"
5259 "ORDER BY 1",
5260 pattern);
5261 result = PSQLexec(buf.data);
5262 if (!result)
5263 goto error_return;
5264 else
5265 pub_schema_tuples = PQntuples(result);
5266
5267 if (pub_schema_tuples > 0)
5268 {
5269 /*
5270 * Allocate memory for footers. Size of footers will be 1 (for
5271 * storing "Publications:" string) + publication schema mapping
5272 * count + 1 (for storing NULL).
5273 */
5274 footers = (char **) pg_malloc((1 + pub_schema_tuples + 1) * sizeof(char *));
5275 footers[0] = pg_strdup(_("Publications:"));
5276
5277 /* Might be an empty set - that's ok */
5278 for (i = 0; i < pub_schema_tuples; i++)
5279 {
5280 printfPQExpBuffer(&buf, " \"%s\"",
5281 PQgetvalue(result, i, 0));
5282
5283 footers[i + 1] = pg_strdup(buf.data);
5284 }
5285
5286 footers[i + 1] = NULL;
5287 myopt.footers = footers;
5288 }
5289
5290 PQclear(result);
5291 }
5292
5293 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5294
5296 PQclear(res);
5297
5298 /* Free the memory allocated for the footer */
5299 if (footers)
5300 {
5301 char **footer = NULL;
5302
5303 for (footer = footers; *footer; footer++)
5304 pg_free(*footer);
5305
5306 pg_free(footers);
5307 }
5308
5309 return true;
5310
5311error_return:
5313 return false;
5314}
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
void pg_free(void *ptr)
Definition: fe_memutils.c:105

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, _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 4006 of file describe.c.

4007{
4008 bool showTables = strchr(tabtypes, 't') != NULL;
4009 bool showIndexes = strchr(tabtypes, 'i') != NULL;
4010 bool showViews = strchr(tabtypes, 'v') != NULL;
4011 bool showMatViews = strchr(tabtypes, 'm') != NULL;
4012 bool showSeq = strchr(tabtypes, 's') != NULL;
4013 bool showForeign = strchr(tabtypes, 'E') != NULL;
4014
4015 int ntypes;
4017 PGresult *res;
4018 printQueryOpt myopt = pset.popt;
4019 int cols_so_far;
4020 bool translate_columns[] = {false, false, true, false, false, false, false, false, false};
4021
4022 /* Count the number of explicitly-requested relation types */
4023 ntypes = showTables + showIndexes + showViews + showMatViews +
4024 showSeq + showForeign;
4025 /* If none, we default to \dtvmsE (but see also command.c) */
4026 if (ntypes == 0)
4027 showTables = showViews = showMatViews = showSeq = showForeign = true;
4028
4030
4032 "SELECT n.nspname as \"%s\",\n"
4033 " c.relname as \"%s\",\n"
4034 " CASE c.relkind"
4035 " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'"
4036 " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'"
4037 " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'"
4038 " WHEN " CppAsString2(RELKIND_INDEX) " THEN '%s'"
4039 " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'"
4040 " WHEN " CppAsString2(RELKIND_TOASTVALUE) " THEN '%s'"
4041 " WHEN " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN '%s'"
4042 " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
4043 " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
4044 " END as \"%s\",\n"
4045 " pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"",
4046 gettext_noop("Schema"),
4047 gettext_noop("Name"),
4048 gettext_noop("table"),
4049 gettext_noop("view"),
4050 gettext_noop("materialized view"),
4051 gettext_noop("index"),
4052 gettext_noop("sequence"),
4053 gettext_noop("TOAST table"),
4054 gettext_noop("foreign table"),
4055 gettext_noop("partitioned table"),
4056 gettext_noop("partitioned index"),
4057 gettext_noop("Type"),
4058 gettext_noop("Owner"));
4059 cols_so_far = 4;
4060
4061 if (showIndexes)
4062 {
4064 ",\n c2.relname as \"%s\"",
4065 gettext_noop("Table"));
4066 cols_so_far++;
4067 }
4068
4069 if (verbose)
4070 {
4071 /*
4072 * Show whether a relation is permanent, temporary, or unlogged.
4073 */
4075 ",\n CASE c.relpersistence "
4076 "WHEN " CppAsString2(RELPERSISTENCE_PERMANENT) " THEN '%s' "
4077 "WHEN " CppAsString2(RELPERSISTENCE_TEMP) " THEN '%s' "
4078 "WHEN " CppAsString2(RELPERSISTENCE_UNLOGGED) " THEN '%s' "
4079 "END as \"%s\"",
4080 gettext_noop("permanent"),
4081 gettext_noop("temporary"),
4082 gettext_noop("unlogged"),
4083 gettext_noop("Persistence"));
4084 translate_columns[cols_so_far] = true;
4085
4086 /*
4087 * We don't bother to count cols_so_far below here, as there's no need
4088 * to; this might change with future additions to the output columns.
4089 */
4090
4091 /*
4092 * Access methods exist for tables, materialized views and indexes.
4093 * This has been introduced in PostgreSQL 12 for tables.
4094 */
4095 if (pset.sversion >= 120000 && !pset.hide_tableam &&
4096 (showTables || showMatViews || showIndexes))
4098 ",\n am.amname as \"%s\"",
4099 gettext_noop("Access method"));
4100
4102 ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\""
4103 ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"",
4104 gettext_noop("Size"),
4105 gettext_noop("Description"));
4106 }
4107
4109 "\nFROM pg_catalog.pg_class c"
4110 "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace");
4111
4112 if (pset.sversion >= 120000 && !pset.hide_tableam &&
4113 (showTables || showMatViews || showIndexes))
4115 "\n LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam");
4116
4117 if (showIndexes)
4119 "\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid"
4120 "\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid");
4121
4122 appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
4123 if (showTables)
4124 {
4125 appendPQExpBufferStr(&buf, CppAsString2(RELKIND_RELATION) ","
4126 CppAsString2(RELKIND_PARTITIONED_TABLE) ",");
4127 /* with 'S' or a pattern, allow 't' to match TOAST tables too */
4128 if (showSystem || pattern)
4129 appendPQExpBufferStr(&buf, CppAsString2(RELKIND_TOASTVALUE) ",");
4130 }
4131 if (showViews)
4132 appendPQExpBufferStr(&buf, CppAsString2(RELKIND_VIEW) ",");
4133 if (showMatViews)
4134 appendPQExpBufferStr(&buf, CppAsString2(RELKIND_MATVIEW) ",");
4135 if (showIndexes)
4136 appendPQExpBufferStr(&buf, CppAsString2(RELKIND_INDEX) ","
4137 CppAsString2(RELKIND_PARTITIONED_INDEX) ",");
4138 if (showSeq)
4139 appendPQExpBufferStr(&buf, CppAsString2(RELKIND_SEQUENCE) ",");
4140 if (showSystem || pattern)
4141 appendPQExpBufferStr(&buf, "'s',"); /* was RELKIND_SPECIAL */
4142 if (showForeign)
4143 appendPQExpBufferStr(&buf, CppAsString2(RELKIND_FOREIGN_TABLE) ",");
4144
4145 appendPQExpBufferStr(&buf, "''"); /* dummy */
4146 appendPQExpBufferStr(&buf, ")\n");
4147
4148 if (!showSystem && !pattern)
4149 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4150 " AND n.nspname !~ '^pg_toast'\n"
4151 " AND n.nspname <> 'information_schema'\n");
4152
4153 if (!validateSQLNamePattern(&buf, pattern, true, false,
4154 "n.nspname", "c.relname", NULL,
4155 "pg_catalog.pg_table_is_visible(c.oid)",
4156 NULL, 3))
4157 {
4159 return false;
4160 }
4161
4162 appendPQExpBufferStr(&buf, "ORDER BY 1,2;");
4163
4164 res = PSQLexec(buf.data);
4166 if (!res)
4167 return false;
4168
4169 /*
4170 * Most functions in this file are content to print an empty table when
4171 * there are no matching objects. We intentionally deviate from that
4172 * here, but only in !quiet mode, for historical reasons.
4173 */
4174 if (PQntuples(res) == 0 && !pset.quiet)
4175 {
4176 if (pattern)
4177 {
4178 if (ntypes != 1)
4179 pg_log_error("Did not find any relations named \"%s\".",
4180 pattern);
4181 else if (showTables)
4182 pg_log_error("Did not find any tables named \"%s\".",
4183 pattern);
4184 else if (showIndexes)
4185 pg_log_error("Did not find any indexes named \"%s\".",
4186 pattern);
4187 else if (showViews)
4188 pg_log_error("Did not find any views named \"%s\".",
4189 pattern);
4190 else if (showMatViews)
4191 pg_log_error("Did not find any materialized views named \"%s\".",
4192 pattern);
4193 else if (showSeq)
4194 pg_log_error("Did not find any sequences named \"%s\".",
4195 pattern);
4196 else if (showForeign)
4197 pg_log_error("Did not find any foreign tables named \"%s\".",
4198 pattern);
4199 else /* should not get here */
4200 pg_log_error_internal("Did not find any ??? named \"%s\".",
4201 pattern);
4202 }
4203 else
4204 {
4205 if (ntypes != 1)
4206 pg_log_error("Did not find any relations.");
4207 else if (showTables)
4208 pg_log_error("Did not find any tables.");
4209 else if (showIndexes)
4210 pg_log_error("Did not find any indexes.");
4211 else if (showViews)
4212 pg_log_error("Did not find any views.");
4213 else if (showMatViews)
4214 pg_log_error("Did not find any materialized views.");
4215 else if (showSeq)
4216 pg_log_error("Did not find any sequences.");
4217 else if (showForeign)
4218 pg_log_error("Did not find any foreign tables.");
4219 else /* should not get here */
4220 pg_log_error_internal("Did not find any ??? relations.");
4221 }
4222 }
4223 else
4224 {
4225 myopt.title =
4226 (ntypes != 1) ? _("List of relations") :
4227 (showTables) ? _("List of tables") :
4228 (showIndexes) ? _("List of indexes") :
4229 (showViews) ? _("List of views") :
4230 (showMatViews) ? _("List of materialized views") :
4231 (showSeq) ? _("List of sequences") :
4232 (showForeign) ? _("List of foreign tables") :
4233 "List of ???"; /* should not get here */
4234 myopt.translate_header = true;
4235 myopt.translate_columns = translate_columns;
4236 myopt.n_translate_columns = lengthof(translate_columns);
4237
4238 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4239 }
4240
4241 PQclear(res);
4242 return true;
4243}
#define pg_log_error_internal(...)
Definition: logging.h:160

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, gettext_noop, _psqlSettings::hide_tableam, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, pg_log_error, pg_log_error_internal, _psqlSettings::popt, PQclear(), PQntuples(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::quiet, _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 5699 of file describe.c.

5700{
5702 PGresult *res;
5703 printQueryOpt myopt = pset.popt;
5704
5705 if (verbose)
5706 return listTSConfigsVerbose(pattern);
5707
5709
5711 "SELECT\n"
5712 " n.nspname as \"%s\",\n"
5713 " c.cfgname as \"%s\",\n"
5714 " pg_catalog.obj_description(c.oid, 'pg_ts_config') as \"%s\"\n"
5715 "FROM pg_catalog.pg_ts_config c\n"
5716 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace\n",
5717 gettext_noop("Schema"),
5718 gettext_noop("Name"),
5719 gettext_noop("Description")
5720 );
5721
5722 if (!validateSQLNamePattern(&buf, pattern, false, false,
5723 "n.nspname", "c.cfgname", NULL,
5724 "pg_catalog.pg_ts_config_is_visible(c.oid)",
5725 NULL, 3))
5726 {
5728 return false;
5729 }
5730
5731 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5732
5733 res = PSQLexec(buf.data);
5735 if (!res)
5736 return false;
5737
5738 myopt.title = _("List of text search configurations");
5739 myopt.translate_header = true;
5740
5741 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5742
5743 PQclear(res);
5744 return true;
5745}
static bool listTSConfigsVerbose(const char *pattern)
Definition: describe.c:5748

References _, appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), listTSConfigsVerbose(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 5748 of file describe.c.

5749{
5751 PGresult *res;
5752 int i;
5753
5755
5757 "SELECT c.oid, c.cfgname,\n"
5758 " n.nspname,\n"
5759 " p.prsname,\n"
5760 " np.nspname as pnspname\n"
5761 "FROM pg_catalog.pg_ts_config c\n"
5762 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace,\n"
5763 " pg_catalog.pg_ts_parser p\n"
5764 " LEFT JOIN pg_catalog.pg_namespace np ON np.oid = p.prsnamespace\n"
5765 "WHERE p.oid = c.cfgparser\n"
5766 );
5767
5768 if (!validateSQLNamePattern(&buf, pattern, true, false,
5769 "n.nspname", "c.cfgname", NULL,
5770 "pg_catalog.pg_ts_config_is_visible(c.oid)",
5771 NULL, 3))
5772 {
5774 return false;
5775 }
5776
5777 appendPQExpBufferStr(&buf, "ORDER BY 3, 2;");
5778
5779 res = PSQLexec(buf.data);
5781 if (!res)
5782 return false;
5783
5784 if (PQntuples(res) == 0)
5785 {
5786 if (!pset.quiet)
5787 {
5788 if (pattern)
5789 pg_log_error("Did not find any text search configuration named \"%s\".",
5790 pattern);
5791 else
5792 pg_log_error("Did not find any text search configurations.");
5793 }
5794 PQclear(res);
5795 return false;
5796 }
5797
5798 for (i = 0; i < PQntuples(res); i++)
5799 {
5800 const char *oid;
5801 const char *cfgname;
5802 const char *nspname = NULL;
5803 const char *prsname;
5804 const char *pnspname = NULL;
5805
5806 oid = PQgetvalue(res, i, 0);
5807 cfgname = PQgetvalue(res, i, 1);
5808 if (!PQgetisnull(res, i, 2))
5809 nspname = PQgetvalue(res, i, 2);
5810 prsname = PQgetvalue(res, i, 3);
5811 if (!PQgetisnull(res, i, 4))
5812 pnspname = PQgetvalue(res, i, 4);
5813
5814 if (!describeOneTSConfig(oid, nspname, cfgname, pnspname, prsname))
5815 {
5816 PQclear(res);
5817 return false;
5818 }
5819
5820 if (cancel_pressed)
5821 {
5822 PQclear(res);
5823 return false;
5824 }
5825 }
5826
5827 PQclear(res);
5828 return true;
5829}
static bool describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname, const char *pnspname, const char *prsname)
Definition: describe.c:5832

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

Referenced by listTSConfigs().

◆ listTSDictionaries()

bool listTSDictionaries ( const char *  pattern,
bool  verbose 
)

Definition at line 5569 of file describe.c.

5570{
5572 PGresult *res;
5573 printQueryOpt myopt = pset.popt;
5574
5576
5578 "SELECT\n"
5579 " n.nspname as \"%s\",\n"
5580 " d.dictname as \"%s\",\n",
5581 gettext_noop("Schema"),
5582 gettext_noop("Name"));
5583
5584 if (verbose)
5585 {
5587 " ( SELECT COALESCE(nt.nspname, '(null)')::pg_catalog.text || '.' || t.tmplname FROM\n"
5588 " pg_catalog.pg_ts_template t\n"
5589 " LEFT JOIN pg_catalog.pg_namespace nt ON nt.oid = t.tmplnamespace\n"
5590 " WHERE d.dicttemplate = t.oid ) AS \"%s\",\n"
5591 " d.dictinitoption as \"%s\",\n",
5592 gettext_noop("Template"),
5593 gettext_noop("Init options"));
5594 }
5595
5597 " pg_catalog.obj_description(d.oid, 'pg_ts_dict') as \"%s\"\n",
5598 gettext_noop("Description"));
5599
5600 appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_dict d\n"
5601 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace\n");
5602
5603 if (!validateSQLNamePattern(&buf, pattern, false, false,
5604 "n.nspname", "d.dictname", NULL,
5605 "pg_catalog.pg_ts_dict_is_visible(d.oid)",
5606 NULL, 3))
5607 {
5609 return false;
5610 }
5611
5612 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5613
5614 res = PSQLexec(buf.data);
5616 if (!res)
5617 return false;
5618
5619 myopt.title = _("List of text search dictionaries");
5620 myopt.translate_header = true;
5621
5622 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5623
5624 PQclear(res);
5625 return true;
5626}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 5322 of file describe.c.

5323{
5325 PGresult *res;
5326 printQueryOpt myopt = pset.popt;
5327
5328 if (verbose)
5329 return listTSParsersVerbose(pattern);
5330
5332
5334 "SELECT\n"
5335 " n.nspname as \"%s\",\n"
5336 " p.prsname as \"%s\",\n"
5337 " pg_catalog.obj_description(p.oid, 'pg_ts_parser') as \"%s\"\n"
5338 "FROM pg_catalog.pg_ts_parser p\n"
5339 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n",
5340 gettext_noop("Schema"),
5341 gettext_noop("Name"),
5342 gettext_noop("Description")
5343 );
5344
5345 if (!validateSQLNamePattern(&buf, pattern, false, false,
5346 "n.nspname", "p.prsname", NULL,
5347 "pg_catalog.pg_ts_parser_is_visible(p.oid)",
5348 NULL, 3))
5349 {
5351 return false;
5352 }
5353
5354 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5355
5356 res = PSQLexec(buf.data);
5358 if (!res)
5359 return false;
5360
5361 myopt.title = _("List of text search parsers");
5362 myopt.translate_header = true;
5363
5364 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5365
5366 PQclear(res);
5367 return true;
5368}
static bool listTSParsersVerbose(const char *pattern)
Definition: describe.c:5374

References _, appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), listTSParsersVerbose(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 5374 of file describe.c.

5375{
5377 PGresult *res;
5378 int i;
5379
5381
5383 "SELECT p.oid,\n"
5384 " n.nspname,\n"
5385 " p.prsname\n"
5386 "FROM pg_catalog.pg_ts_parser p\n"
5387 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n"
5388 );
5389
5390 if (!validateSQLNamePattern(&buf, pattern, false, false,
5391 "n.nspname", "p.prsname", NULL,
5392 "pg_catalog.pg_ts_parser_is_visible(p.oid)",
5393 NULL, 3))
5394 {
5396 return false;
5397 }
5398
5399 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5400
5401 res = PSQLexec(buf.data);
5403 if (!res)
5404 return false;
5405
5406 if (PQntuples(res) == 0)
5407 {
5408 if (!pset.quiet)
5409 {
5410 if (pattern)
5411 pg_log_error("Did not find any text search parser named \"%s\".",
5412 pattern);
5413 else
5414 pg_log_error("Did not find any text search parsers.");
5415 }
5416 PQclear(res);
5417 return false;
5418 }
5419
5420 for (i = 0; i < PQntuples(res); i++)
5421 {
5422 const char *oid;
5423 const char *nspname = NULL;
5424 const char *prsname;
5425
5426 oid = PQgetvalue(res, i, 0);
5427 if (!PQgetisnull(res, i, 1))
5428 nspname = PQgetvalue(res, i, 1);
5429 prsname = PQgetvalue(res, i, 2);
5430
5431 if (!describeOneTSParser(oid, nspname, prsname))
5432 {
5433 PQclear(res);
5434 return false;
5435 }
5436
5437 if (cancel_pressed)
5438 {
5439 PQclear(res);
5440 return false;
5441 }
5442 }
5443
5444 PQclear(res);
5445 return true;
5446}
static bool describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
Definition: describe.c:5449

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

Referenced by listTSParsers().

◆ listTSTemplates()

bool listTSTemplates ( const char *  pattern,
bool  verbose 
)

Definition at line 5634 of file describe.c.

5635{
5637 PGresult *res;
5638 printQueryOpt myopt = pset.popt;
5639
5641
5642 if (verbose)
5644 "SELECT\n"
5645 " n.nspname AS \"%s\",\n"
5646 " t.tmplname AS \"%s\",\n"
5647 " t.tmplinit::pg_catalog.regproc AS \"%s\",\n"
5648 " t.tmpllexize::pg_catalog.regproc AS \"%s\",\n"
5649 " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
5650 gettext_noop("Schema"),
5651 gettext_noop("Name"),
5652 gettext_noop("Init"),
5653 gettext_noop("Lexize"),
5654 gettext_noop("Description"));
5655 else
5657 "SELECT\n"
5658 " n.nspname AS \"%s\",\n"
5659 " t.tmplname AS \"%s\",\n"
5660 " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
5661 gettext_noop("Schema"),
5662 gettext_noop("Name"),
5663 gettext_noop("Description"));
5664
5665 appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_template t\n"
5666 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.tmplnamespace\n");
5667
5668 if (!validateSQLNamePattern(&buf, pattern, false, false,
5669 "n.nspname", "t.tmplname", NULL,
5670 "pg_catalog.pg_ts_template_is_visible(t.oid)",
5671 NULL, 3))
5672 {
5674 return false;
5675 }
5676
5677 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5678
5679 res = PSQLexec(buf.data);
5681 if (!res)
5682 return false;
5683
5684 myopt.title = _("List of text search templates");
5685 myopt.translate_header = true;
5686
5687 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5688
5689 PQclear(res);
5690 return true;
5691}

References _, appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 6050 of file describe.c.

6051{
6053 PGresult *res;
6054 printQueryOpt myopt = pset.popt;
6055
6058 "SELECT um.srvname AS \"%s\",\n"
6059 " um.usename AS \"%s\"",
6060 gettext_noop("Server"),
6061 gettext_noop("User name"));
6062
6063 if (verbose)
6065 ",\n CASE WHEN umoptions IS NULL THEN '' ELSE "
6066 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6067 " pg_catalog.quote_ident(option_name) || ' ' || "
6068 " pg_catalog.quote_literal(option_value) FROM "
6069 " pg_catalog.pg_options_to_table(umoptions)), ', ') || ')' "
6070 " END AS \"%s\"",
6071 gettext_noop("FDW options"));
6072
6073 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_user_mappings um\n");
6074
6075 if (!validateSQLNamePattern(&buf, pattern, false, false,
6076 NULL, "um.srvname", "um.usename", NULL,
6077 NULL, 1))
6078 {
6080 return false;
6081 }
6082
6083 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
6084
6085 res = PSQLexec(buf.data);
6087 if (!res)
6088 return false;
6089
6090 myopt.title = _("List of user mappings");
6091 myopt.translate_header = true;
6092
6093 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6094
6095 PQclear(res);
6096 return true;
6097}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 743 of file describe.c.

744{
745 static const char *const typename_map[] = {
746 /*
747 * These names are accepted by gram.y, although they are neither the
748 * "real" name seen in pg_type nor the canonical name printed by
749 * format_type().
750 */
751 "decimal", "numeric",
752 "float", "double precision",
753 "int", "integer",
754
755 /*
756 * We also have to map the array names for cases where the canonical
757 * name is different from what pg_type says.
758 */
759 "bool[]", "boolean[]",
760 "decimal[]", "numeric[]",
761 "float[]", "double precision[]",
762 "float4[]", "real[]",
763 "float8[]", "double precision[]",
764 "int[]", "integer[]",
765 "int2[]", "smallint[]",
766 "int4[]", "integer[]",
767 "int8[]", "bigint[]",
768 "time[]", "time without time zone[]",
769 "timetz[]", "time with time zone[]",
770 "timestamp[]", "timestamp without time zone[]",
771 "timestamptz[]", "timestamp with time zone[]",
772 "varbit[]", "bit varying[]",
773 "varchar[]", "character varying[]",
774 NULL
775 };
776
777 if (pattern == NULL)
778 return NULL;
779 for (int i = 0; typename_map[i] != NULL; i += 2)
780 {
781 if (pg_strcasecmp(pattern, typename_map[i]) == 0)
782 return typename_map[i + 1];
783 }
784 return pattern;
785}
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 1294 of file describe.c.

1295{
1297 PGresult *res;
1298 printQueryOpt myopt = pset.popt;
1299 static const bool translate_columns[] = {false, false, true, false};
1300
1302
1304 "SELECT DISTINCT tt.nspname AS \"%s\", tt.name AS \"%s\", tt.object AS \"%s\", d.description AS \"%s\"\n"
1305 "FROM (\n",
1306 gettext_noop("Schema"),
1307 gettext_noop("Name"),
1308 gettext_noop("Object"),
1309 gettext_noop("Description"));
1310
1311 /* Table constraint descriptions */
1313 " SELECT pgc.oid as oid, pgc.tableoid AS tableoid,\n"
1314 " n.nspname as nspname,\n"
1315 " CAST(pgc.conname AS pg_catalog.text) as name,"
1316 " CAST('%s' AS pg_catalog.text) as object\n"
1317 " FROM pg_catalog.pg_constraint pgc\n"
1318 " JOIN pg_catalog.pg_class c "
1319 "ON c.oid = pgc.conrelid\n"
1320 " LEFT JOIN pg_catalog.pg_namespace n "
1321 " ON n.oid = c.relnamespace\n",
1322 gettext_noop("table constraint"));
1323
1324 if (!showSystem && !pattern)
1325 appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
1326 " AND n.nspname <> 'information_schema'\n");
1327
1328 if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern,
1329 false, "n.nspname", "pgc.conname", NULL,
1330 "pg_catalog.pg_table_is_visible(c.oid)",
1331 NULL, 3))
1332 goto error_return;
1333
1334 /* Domain constraint descriptions */
1336 "UNION ALL\n"
1337 " SELECT pgc.oid as oid, pgc.tableoid AS tableoid,\n"
1338 " n.nspname as nspname,\n"
1339 " CAST(pgc.conname AS pg_catalog.text) as name,"
1340 " CAST('%s' AS pg_catalog.text) as object\n"
1341 " FROM pg_catalog.pg_constraint pgc\n"
1342 " JOIN pg_catalog.pg_type t "
1343 "ON t.oid = pgc.contypid\n"
1344 " LEFT JOIN pg_catalog.pg_namespace n "
1345 " ON n.oid = t.typnamespace\n",
1346 gettext_noop("domain constraint"));
1347
1348 if (!showSystem && !pattern)
1349 appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
1350 " AND n.nspname <> 'information_schema'\n");
1351
1352 if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern,
1353 false, "n.nspname", "pgc.conname", NULL,
1354 "pg_catalog.pg_type_is_visible(t.oid)",
1355 NULL, 3))
1356 goto error_return;
1357
1358 /* Operator class descriptions */
1360 "UNION ALL\n"
1361 " SELECT o.oid as oid, o.tableoid as tableoid,\n"
1362 " n.nspname as nspname,\n"
1363 " CAST(o.opcname AS pg_catalog.text) as name,\n"
1364 " CAST('%s' AS pg_catalog.text) as object\n"
1365 " FROM pg_catalog.pg_opclass o\n"
1366 " JOIN pg_catalog.pg_am am ON "
1367 "o.opcmethod = am.oid\n"
1368 " JOIN pg_catalog.pg_namespace n ON "
1369 "n.oid = o.opcnamespace\n",
1370 gettext_noop("operator class"));
1371
1372 if (!showSystem && !pattern)
1373 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
1374 " AND n.nspname <> 'information_schema'\n");
1375
1376 if (!validateSQLNamePattern(&buf, pattern, true, false,
1377 "n.nspname", "o.opcname", NULL,
1378 "pg_catalog.pg_opclass_is_visible(o.oid)",
1379 NULL, 3))
1380 goto error_return;
1381
1382 /* Operator family descriptions */
1384 "UNION ALL\n"
1385 " SELECT opf.oid as oid, opf.tableoid as tableoid,\n"
1386 " n.nspname as nspname,\n"
1387 " CAST(opf.opfname AS pg_catalog.text) AS name,\n"
1388 " CAST('%s' AS pg_catalog.text) as object\n"
1389 " FROM pg_catalog.pg_opfamily opf\n"
1390 " JOIN pg_catalog.pg_am am "
1391 "ON opf.opfmethod = am.oid\n"
1392 " JOIN pg_catalog.pg_namespace n "
1393 "ON opf.opfnamespace = n.oid\n",
1394 gettext_noop("operator family"));
1395
1396 if (!showSystem && !pattern)
1397 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
1398 " AND n.nspname <> 'information_schema'\n");
1399
1400 if (!validateSQLNamePattern(&buf, pattern, true, false,
1401 "n.nspname", "opf.opfname", NULL,
1402 "pg_catalog.pg_opfamily_is_visible(opf.oid)",
1403 NULL, 3))
1404 goto error_return;
1405
1406 /* Rule descriptions (ignore rules for views) */
1408 "UNION ALL\n"
1409 " SELECT r.oid as oid, r.tableoid as tableoid,\n"
1410 " n.nspname as nspname,\n"
1411 " CAST(r.rulename AS pg_catalog.text) as name,"
1412 " CAST('%s' AS pg_catalog.text) as object\n"
1413 " FROM pg_catalog.pg_rewrite r\n"
1414 " JOIN pg_catalog.pg_class c ON c.oid = r.ev_class\n"
1415 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
1416 " WHERE r.rulename != '_RETURN'\n",
1417 gettext_noop("rule"));
1418
1419 if (!showSystem && !pattern)
1420 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
1421 " AND n.nspname <> 'information_schema'\n");
1422
1423 if (!validateSQLNamePattern(&buf, pattern, true, false,
1424 "n.nspname", "r.rulename", NULL,
1425 "pg_catalog.pg_table_is_visible(c.oid)",
1426 NULL, 3))
1427 goto error_return;
1428
1429 /* Trigger descriptions */
1431 "UNION ALL\n"
1432 " SELECT t.oid as oid, t.tableoid as tableoid,\n"
1433 " n.nspname as nspname,\n"
1434 " CAST(t.tgname AS pg_catalog.text) as name,"
1435 " CAST('%s' AS pg_catalog.text) as object\n"
1436 " FROM pg_catalog.pg_trigger t\n"
1437 " JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid\n"
1438 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n",
1439 gettext_noop("trigger"));
1440
1441 if (!showSystem && !pattern)
1442 appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
1443 " AND n.nspname <> 'information_schema'\n");
1444
1445 if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern, false,
1446 "n.nspname", "t.tgname", NULL,
1447 "pg_catalog.pg_table_is_visible(c.oid)",
1448 NULL, 3))
1449 goto error_return;
1450
1452 ") AS tt\n"
1453 " JOIN pg_catalog.pg_description d ON (tt.oid = d.objoid AND tt.tableoid = d.classoid AND d.objsubid = 0)\n");
1454
1455 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
1456
1457 res = PSQLexec(buf.data);
1459 if (!res)
1460 return false;
1461
1462 myopt.title = _("Object descriptions");
1463 myopt.translate_header = true;
1464 myopt.translate_columns = translate_columns;
1465 myopt.n_translate_columns = lengthof(translate_columns);
1466
1467 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1468
1469 PQclear(res);
1470 return true;
1471
1472error_return:
1474 return false;
1475}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, printQueryOpt::n_translate_columns, _psqlSettings::popt, PQclear(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, 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 1049 of file describe.c.

1050{
1052 PGresult *res;
1053 printQueryOpt myopt = pset.popt;
1054 static const bool translate_columns[] = {false, false, true, false, false, false};
1055
1057
1058 /*
1059 * we ignore indexes and toast tables since they have no meaningful rights
1060 */
1062 "SELECT n.nspname as \"%s\",\n"
1063 " c.relname as \"%s\",\n"
1064 " CASE c.relkind"
1065 " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'"
1066 " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'"
1067 " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'"
1068 " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'"
1069 " WHEN " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN '%s'"
1070 " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
1071 " END as \"%s\",\n"
1072 " ",
1073 gettext_noop("Schema"),
1074 gettext_noop("Name"),
1075 gettext_noop("table"),
1076 gettext_noop("view"),
1077 gettext_noop("materialized view"),
1078 gettext_noop("sequence"),
1079 gettext_noop("foreign table"),
1080 gettext_noop("partitioned table"),
1081 gettext_noop("Type"));
1082
1083 printACLColumn(&buf, "c.relacl");
1084
1085 /*
1086 * The formatting of attacl should match printACLColumn(). However, we
1087 * need no special case for an empty attacl, because the backend always
1088 * optimizes that back to NULL.
1089 */
1091 ",\n pg_catalog.array_to_string(ARRAY(\n"
1092 " SELECT attname || E':\\n ' || pg_catalog.array_to_string(attacl, E'\\n ')\n"
1093 " FROM pg_catalog.pg_attribute a\n"
1094 " WHERE attrelid = c.oid AND NOT attisdropped AND attacl IS NOT NULL\n"
1095 " ), E'\\n') AS \"%s\"",
1096 gettext_noop("Column privileges"));
1097
1098 if (pset.sversion >= 90500 && pset.sversion < 100000)
1100 ",\n pg_catalog.array_to_string(ARRAY(\n"
1101 " SELECT polname\n"
1102 " || CASE WHEN polcmd != '*' THEN\n"
1103 " E' (' || polcmd::pg_catalog.text || E'):'\n"
1104 " ELSE E':'\n"
1105 " END\n"
1106 " || CASE WHEN polqual IS NOT NULL THEN\n"
1107 " E'\\n (u): ' || pg_catalog.pg_get_expr(polqual, polrelid)\n"
1108 " ELSE E''\n"
1109 " END\n"
1110 " || CASE WHEN polwithcheck IS NOT NULL THEN\n"
1111 " E'\\n (c): ' || pg_catalog.pg_get_expr(polwithcheck, polrelid)\n"
1112 " ELSE E''\n"
1113 " END"
1114 " || CASE WHEN polroles <> '{0}' THEN\n"
1115 " E'\\n to: ' || pg_catalog.array_to_string(\n"
1116 " ARRAY(\n"
1117 " SELECT rolname\n"
1118 " FROM pg_catalog.pg_roles\n"
1119 " WHERE oid = ANY (polroles)\n"
1120 " ORDER BY 1\n"
1121 " ), E', ')\n"
1122 " ELSE E''\n"
1123 " END\n"
1124 " FROM pg_catalog.pg_policy pol\n"
1125 " WHERE polrelid = c.oid), E'\\n')\n"
1126 " AS \"%s\"",
1127 gettext_noop("Policies"));
1128
1129 if (pset.sversion >= 100000)
1131 ",\n pg_catalog.array_to_string(ARRAY(\n"
1132 " SELECT polname\n"
1133 " || CASE WHEN NOT polpermissive THEN\n"
1134 " E' (RESTRICTIVE)'\n"
1135 " ELSE '' END\n"
1136 " || CASE WHEN polcmd != '*' THEN\n"
1137 " E' (' || polcmd::pg_catalog.text || E'):'\n"
1138 " ELSE E':'\n"
1139 " END\n"
1140 " || CASE WHEN polqual IS NOT NULL THEN\n"
1141 " E'\\n (u): ' || pg_catalog.pg_get_expr(polqual, polrelid)\n"
1142 " ELSE E''\n"
1143 " END\n"
1144 " || CASE WHEN polwithcheck IS NOT NULL THEN\n"
1145 " E'\\n (c): ' || pg_catalog.pg_get_expr(polwithcheck, polrelid)\n"
1146 " ELSE E''\n"
1147 " END"
1148 " || CASE WHEN polroles <> '{0}' THEN\n"
1149 " E'\\n to: ' || pg_catalog.array_to_string(\n"
1150 " ARRAY(\n"
1151 " SELECT rolname\n"
1152 " FROM pg_catalog.pg_roles\n"
1153 " WHERE oid = ANY (polroles)\n"
1154 " ORDER BY 1\n"
1155 " ), E', ')\n"
1156 " ELSE E''\n"
1157 " END\n"
1158 " FROM pg_catalog.pg_policy pol\n"
1159 " WHERE polrelid = c.oid), E'\\n')\n"
1160 " AS \"%s\"",
1161 gettext_noop("Policies"));
1162
1163 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_class c\n"
1164 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
1165 "WHERE c.relkind IN ("
1166 CppAsString2(RELKIND_RELATION) ","
1167 CppAsString2(RELKIND_VIEW) ","
1168 CppAsString2(RELKIND_MATVIEW) ","
1169 CppAsString2(RELKIND_SEQUENCE) ","
1170 CppAsString2(RELKIND_FOREIGN_TABLE) ","
1171 CppAsString2(RELKIND_PARTITIONED_TABLE) ")\n");
1172
1173 if (!showSystem && !pattern)
1174 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
1175 " AND n.nspname <> 'information_schema'\n");
1176
1177 if (!validateSQLNamePattern(&buf, pattern, true, false,
1178 "n.nspname", "c.relname", NULL,
1179 "pg_catalog.pg_table_is_visible(c.oid)",
1180 NULL, 3))
1181 goto error_return;
1182
1183 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
1184
1185 res = PSQLexec(buf.data);
1186 if (!res)
1187 goto error_return;
1188
1189 printfPQExpBuffer(&buf, _("Access privileges"));
1190 myopt.title = buf.data;
1191 myopt.translate_header = true;
1192 myopt.translate_columns = translate_columns;
1193 myopt.n_translate_columns = lengthof(translate_columns);
1194
1195 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1196
1198 PQclear(res);
1199 return true;
1200
1201error_return:
1203 return false;
1204}

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, _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 6875 of file describe.c.

6876{
6878 "CASE"
6879 " WHEN pg_catalog.array_length(%s, 1) = 0 THEN '%s'"
6880 " ELSE pg_catalog.array_to_string(%s, E'\\n')"
6881 " END AS \"%s\"",
6882 colname, gettext_noop("(none)"),
6883 colname, gettext_noop("Access privileges"));
6884}

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 6342 of file describe.c.

6347{
6348 PQExpBufferData dbbuf;
6349 int dotcnt;
6350 bool added;
6351
6352 initPQExpBuffer(&dbbuf);
6353 added = processSQLNamePattern(pset.db, buf, pattern, have_where, force_escape,
6354 schemavar, namevar, altnamevar,
6355 visibilityrule, &dbbuf, &dotcnt);
6356 if (added_clause != NULL)
6357 *added_clause = added;
6358
6359 if (dotcnt >= maxparts)
6360 {
6361 pg_log_error("improper qualified name (too many dotted names): %s",
6362 pattern);
6363 goto error_return;
6364 }
6365
6366 if (maxparts > 1 && dotcnt == maxparts - 1)
6367 {
6368 if (PQdb(pset.db) == NULL)
6369 {
6370 pg_log_error("You are currently not connected to a database.");
6371 goto error_return;
6372 }
6373 if (strcmp(PQdb(pset.db), dbbuf.data) != 0)
6374 {
6375 pg_log_error("cross-database references are not implemented: %s",
6376 pattern);
6377 goto error_return;
6378 }
6379 }
6380 termPQExpBuffer(&dbbuf);
6381 return true;
6382
6383error_return:
6384 termPQExpBuffer(&dbbuf);
6385 return false;
6386}
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:7447

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().