Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

PostgreSQL Source Code git master
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 3847 of file describe.c.

3848{
3849 if (buf->len > 0)
3851
3853}
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 3647 of file describe.c.

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

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

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:1195
#define CppAsString2(x)
Definition: c.h:418
#define lengthof(array)
Definition: c.h:787
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:6343
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 4711 of file describe.c.

4713{
4715 PGresult *res;
4716 printQueryOpt myopt = pset.popt;
4717
4720 "SELECT s.name AS \"%s\", "
4721 "pg_catalog.current_setting(s.name) AS \"%s\"",
4722 gettext_noop("Parameter"),
4723 gettext_noop("Value"));
4724
4725 if (verbose)
4726 {
4728 ", s.vartype AS \"%s\", s.context AS \"%s\", ",
4729 gettext_noop("Type"),
4730 gettext_noop("Context"));
4731 if (pset.sversion >= 150000)
4732 printACLColumn(&buf, "p.paracl");
4733 else
4734 appendPQExpBuffer(&buf, "NULL AS \"%s\"",
4735 gettext_noop("Access privileges"));
4736 }
4737
4738 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_settings s\n");
4739
4740 if (verbose && pset.sversion >= 150000)
4742 " LEFT JOIN pg_catalog.pg_parameter_acl p\n"
4743 " ON pg_catalog.lower(s.name) = p.parname\n");
4744
4745 if (pattern)
4746 processSQLNamePattern(pset.db, &buf, pattern,
4747 false, false,
4748 NULL, "pg_catalog.lower(s.name)", NULL,
4749 NULL, NULL, NULL);
4750 else
4751 appendPQExpBufferStr(&buf, "WHERE s.source <> 'default' AND\n"
4752 " s.setting IS DISTINCT FROM s.boot_val\n");
4753
4754 appendPQExpBufferStr(&buf, "ORDER BY 1;");
4755
4756 res = PSQLexec(buf.data);
4758 if (!res)
4759 return false;
4760
4761 if (pattern)
4762 myopt.title = _("List of configuration parameters");
4763 else
4764 myopt.title = _("List of non-default configuration parameters");
4765 myopt.translate_header = true;
4766
4767 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4768
4769 PQclear(res);
4770 return true;
4771}
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition: describe.c:6890
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 const char *df_options = "anptwSx+";
300 bool showAggregate = strchr(functypes, 'a') != NULL;
301 bool showNormal = strchr(functypes, 'n') != NULL;
302 bool showProcedure = strchr(functypes, 'p') != NULL;
303 bool showTrigger = strchr(functypes, 't') != NULL;
304 bool showWindow = strchr(functypes, 'w') != NULL;
305 bool have_where;
307 PGresult *res;
308 printQueryOpt myopt = pset.popt;
309 static const bool translate_columns[] = {false, false, false, false, true, true, true, false, true, true, false, false, false, false};
310
311 /* No "Parallel" column before 9.6 */
312 static const bool translate_columns_pre_96[] = {false, false, false, false, true, true, false, true, true, false, false, false, false};
313
314 if (strlen(functypes) != strspn(functypes, df_options))
315 {
316 pg_log_error("\\df only takes [%s] as options", df_options);
317 return true;
318 }
319
320 if (showProcedure && pset.sversion < 110000)
321 {
322 char sverbuf[32];
323
324 pg_log_error("\\df does not take a \"%c\" option with server version %s",
325 'p',
327 sverbuf, sizeof(sverbuf)));
328 return true;
329 }
330
331 if (!showAggregate && !showNormal && !showProcedure && !showTrigger && !showWindow)
332 {
333 showAggregate = showNormal = showTrigger = showWindow = true;
334 if (pset.sversion >= 110000)
335 showProcedure = true;
336 }
337
339
341 "SELECT n.nspname as \"%s\",\n"
342 " p.proname as \"%s\",\n",
343 gettext_noop("Schema"),
344 gettext_noop("Name"));
345
346 if (pset.sversion >= 110000)
348 " pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n"
349 " pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n"
350 " CASE p.prokind\n"
351 " WHEN " CppAsString2(PROKIND_AGGREGATE) " THEN '%s'\n"
352 " WHEN " CppAsString2(PROKIND_WINDOW) " THEN '%s'\n"
353 " WHEN " CppAsString2(PROKIND_PROCEDURE) " THEN '%s'\n"
354 " ELSE '%s'\n"
355 " END as \"%s\"",
356 gettext_noop("Result data type"),
357 gettext_noop("Argument data types"),
358 /* translator: "agg" is short for "aggregate" */
359 gettext_noop("agg"),
360 gettext_noop("window"),
361 gettext_noop("proc"),
362 gettext_noop("func"),
363 gettext_noop("Type"));
364 else
366 " pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n"
367 " pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n"
368 " CASE\n"
369 " WHEN p.proisagg THEN '%s'\n"
370 " WHEN p.proiswindow THEN '%s'\n"
371 " WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN '%s'\n"
372 " ELSE '%s'\n"
373 " END as \"%s\"",
374 gettext_noop("Result data type"),
375 gettext_noop("Argument data types"),
376 /* translator: "agg" is short for "aggregate" */
377 gettext_noop("agg"),
378 gettext_noop("window"),
379 gettext_noop("trigger"),
380 gettext_noop("func"),
381 gettext_noop("Type"));
382
383 if (verbose)
384 {
386 ",\n CASE\n"
387 " WHEN p.provolatile = "
388 CppAsString2(PROVOLATILE_IMMUTABLE) " THEN '%s'\n"
389 " WHEN p.provolatile = "
390 CppAsString2(PROVOLATILE_STABLE) " THEN '%s'\n"
391 " WHEN p.provolatile = "
392 CppAsString2(PROVOLATILE_VOLATILE) " THEN '%s'\n"
393 " END as \"%s\"",
394 gettext_noop("immutable"),
395 gettext_noop("stable"),
396 gettext_noop("volatile"),
397 gettext_noop("Volatility"));
398 if (pset.sversion >= 90600)
400 ",\n CASE\n"
401 " WHEN p.proparallel = "
402 CppAsString2(PROPARALLEL_RESTRICTED) " THEN '%s'\n"
403 " WHEN p.proparallel = "
404 CppAsString2(PROPARALLEL_SAFE) " THEN '%s'\n"
405 " WHEN p.proparallel = "
406 CppAsString2(PROPARALLEL_UNSAFE) " THEN '%s'\n"
407 " END as \"%s\"",
408 gettext_noop("restricted"),
409 gettext_noop("safe"),
410 gettext_noop("unsafe"),
411 gettext_noop("Parallel"));
413 ",\n pg_catalog.pg_get_userbyid(p.proowner) as \"%s\""
414 ",\n CASE WHEN prosecdef THEN '%s' ELSE '%s' END AS \"%s\""
415 ",\n CASE WHEN p.proleakproof THEN '%s' ELSE '%s' END as \"%s\"",
416 gettext_noop("Owner"),
417 gettext_noop("definer"),
418 gettext_noop("invoker"),
419 gettext_noop("Security"),
420 gettext_noop("yes"),
421 gettext_noop("no"),
422 gettext_noop("Leakproof?"));
423 appendPQExpBufferStr(&buf, ",\n ");
424 printACLColumn(&buf, "p.proacl");
426 ",\n l.lanname as \"%s\"",
427 gettext_noop("Language"));
429 ",\n CASE WHEN l.lanname IN ('internal', 'c') THEN p.prosrc END as \"%s\"",
430 gettext_noop("Internal name"));
432 ",\n pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"",
433 gettext_noop("Description"));
434 }
435
437 "\nFROM pg_catalog.pg_proc p"
438 "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n");
439
440 for (int i = 0; i < num_arg_patterns; i++)
441 {
443 " LEFT JOIN pg_catalog.pg_type t%d ON t%d.oid = p.proargtypes[%d]\n"
444 " LEFT JOIN pg_catalog.pg_namespace nt%d ON nt%d.oid = t%d.typnamespace\n",
445 i, i, i, i, i, i);
446 }
447
448 if (verbose)
450 " LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang\n");
451
452 have_where = false;
453
454 /* filter by function type, if requested */
455 if (showNormal && showAggregate && showProcedure && showTrigger && showWindow)
456 /* Do nothing */ ;
457 else if (showNormal)
458 {
459 if (!showAggregate)
460 {
461 if (have_where)
462 appendPQExpBufferStr(&buf, " AND ");
463 else
464 {
465 appendPQExpBufferStr(&buf, "WHERE ");
466 have_where = true;
467 }
468 if (pset.sversion >= 110000)
469 appendPQExpBufferStr(&buf, "p.prokind <> "
470 CppAsString2(PROKIND_AGGREGATE) "\n");
471 else
472 appendPQExpBufferStr(&buf, "NOT p.proisagg\n");
473 }
474 if (!showProcedure && pset.sversion >= 110000)
475 {
476 if (have_where)
477 appendPQExpBufferStr(&buf, " AND ");
478 else
479 {
480 appendPQExpBufferStr(&buf, "WHERE ");
481 have_where = true;
482 }
483 appendPQExpBufferStr(&buf, "p.prokind <> "
484 CppAsString2(PROKIND_PROCEDURE) "\n");
485 }
486 if (!showTrigger)
487 {
488 if (have_where)
489 appendPQExpBufferStr(&buf, " AND ");
490 else
491 {
492 appendPQExpBufferStr(&buf, "WHERE ");
493 have_where = true;
494 }
495 appendPQExpBufferStr(&buf, "p.prorettype <> 'pg_catalog.trigger'::pg_catalog.regtype\n");
496 }
497 if (!showWindow)
498 {
499 if (have_where)
500 appendPQExpBufferStr(&buf, " AND ");
501 else
502 {
503 appendPQExpBufferStr(&buf, "WHERE ");
504 have_where = true;
505 }
506 if (pset.sversion >= 110000)
507 appendPQExpBufferStr(&buf, "p.prokind <> "
508 CppAsString2(PROKIND_WINDOW) "\n");
509 else
510 appendPQExpBufferStr(&buf, "NOT p.proiswindow\n");
511 }
512 }
513 else
514 {
515 bool needs_or = false;
516
517 appendPQExpBufferStr(&buf, "WHERE (\n ");
518 have_where = true;
519 /* Note: at least one of these must be true ... */
520 if (showAggregate)
521 {
522 if (pset.sversion >= 110000)
523 appendPQExpBufferStr(&buf, "p.prokind = "
524 CppAsString2(PROKIND_AGGREGATE) "\n");
525 else
526 appendPQExpBufferStr(&buf, "p.proisagg\n");
527 needs_or = true;
528 }
529 if (showTrigger)
530 {
531 if (needs_or)
532 appendPQExpBufferStr(&buf, " OR ");
534 "p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype\n");
535 needs_or = true;
536 }
537 if (showProcedure)
538 {
539 if (needs_or)
540 appendPQExpBufferStr(&buf, " OR ");
541 appendPQExpBufferStr(&buf, "p.prokind = "
542 CppAsString2(PROKIND_PROCEDURE) "\n");
543 needs_or = true;
544 }
545 if (showWindow)
546 {
547 if (needs_or)
548 appendPQExpBufferStr(&buf, " OR ");
549 if (pset.sversion >= 110000)
550 appendPQExpBufferStr(&buf, "p.prokind = "
551 CppAsString2(PROKIND_WINDOW) "\n");
552 else
553 appendPQExpBufferStr(&buf, "p.proiswindow\n");
554 }
555 appendPQExpBufferStr(&buf, " )\n");
556 }
557
558 if (!validateSQLNamePattern(&buf, func_pattern, have_where, false,
559 "n.nspname", "p.proname", NULL,
560 "pg_catalog.pg_function_is_visible(p.oid)",
561 NULL, 3))
562 goto error_return;
563
564 for (int i = 0; i < num_arg_patterns; i++)
565 {
566 if (strcmp(arg_patterns[i], "-") != 0)
567 {
568 /*
569 * Match type-name patterns against either internal or external
570 * name, like \dT. Unlike \dT, there seems no reason to
571 * discriminate against arrays or composite types.
572 */
573 char nspname[64];
574 char typname[64];
575 char ft[64];
576 char tiv[64];
577
578 snprintf(nspname, sizeof(nspname), "nt%d.nspname", i);
579 snprintf(typname, sizeof(typname), "t%d.typname", i);
580 snprintf(ft, sizeof(ft),
581 "pg_catalog.format_type(t%d.oid, NULL)", i);
582 snprintf(tiv, sizeof(tiv),
583 "pg_catalog.pg_type_is_visible(t%d.oid)", i);
585 map_typename_pattern(arg_patterns[i]),
586 true, false,
587 nspname, typname, ft, tiv,
588 NULL, 3))
589 goto error_return;
590 }
591 else
592 {
593 /* "-" pattern specifies no such parameter */
594 appendPQExpBuffer(&buf, " AND t%d.typname IS NULL\n", i);
595 }
596 }
597
598 if (!showSystem && !func_pattern)
599 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
600 " AND n.nspname <> 'information_schema'\n");
601
602 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
603
604 res = PSQLexec(buf.data);
606 if (!res)
607 return false;
608
609 myopt.title = _("List of functions");
610 myopt.translate_header = true;
611 if (pset.sversion >= 90600)
612 {
613 myopt.translate_columns = translate_columns;
614 myopt.n_translate_columns = lengthof(translate_columns);
615 }
616 else
617 {
618 myopt.translate_columns = translate_columns_pre_96;
619 myopt.n_translate_columns = lengthof(translate_columns_pre_96);
620 }
621
622 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
623
624 PQclear(res);
625 return true;
626
627error_return:
629 return false;
630}
static const char * map_typename_pattern(const char *pattern)
Definition: describe.c:744
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 1571 of file describe.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

7295{
7297 PGresult *res;
7298 printQueryOpt myopt = pset.popt;
7299
7301
7303 "SELECT oid as \"%s\",\n"
7304 " pg_catalog.pg_get_userbyid(lomowner) as \"%s\",\n ",
7305 gettext_noop("ID"),
7306 gettext_noop("Owner"));
7307
7308 if (verbose)
7309 {
7310 printACLColumn(&buf, "lomacl");
7311 appendPQExpBufferStr(&buf, ",\n ");
7312 }
7313
7315 "pg_catalog.obj_description(oid, 'pg_largeobject') as \"%s\"\n"
7316 "FROM pg_catalog.pg_largeobject_metadata\n"
7317 "ORDER BY oid",
7318 gettext_noop("Description"));
7319
7320 res = PSQLexec(buf.data);
7322 if (!res)
7323 return false;
7324
7325 myopt.title = _("Large objects");
7326 myopt.translate_header = true;
7327
7328 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7329
7330 PQclear(res);
7331 return true;
7332}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

6891{
6893 "CASE"
6894 " WHEN pg_catalog.array_length(%s, 1) = 0 THEN '%s'"
6895 " ELSE pg_catalog.array_to_string(%s, E'\\n')"
6896 " END AS \"%s\"",
6897 colname, gettext_noop("(none)"),
6898 colname, gettext_noop("Access privileges"));
6899}

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

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

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