PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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_propgraph_element_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 charmap_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 verbose)
 
bool listCasts (const char *pattern, bool verbose)
 
bool listCollations (const char *pattern, bool verbose, bool showSystem)
 
bool listSchemas (const char *pattern, bool verbose, bool showSystem)
 
bool listTSParsers (const char *pattern, bool verbose)
 
bool listTSDictionaries (const char *pattern, bool verbose)
 
bool listTSTemplates (const char *pattern, bool verbose)
 
bool listTSConfigs (const char *pattern, bool verbose)
 
bool listForeignDataWrappers (const char *pattern, bool verbose)
 
bool listForeignServers (const char *pattern, bool verbose)
 
bool listUserMappings (const char *pattern, bool verbose)
 
bool listForeignTables (const char *pattern, bool verbose)
 
bool listExtensions (const char *pattern)
 
bool listExtensionContents (const char *pattern)
 
bool listPublications (const char *pattern)
 
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 3920 of file describe.c.

3921{
3922 if (buf->len > 0)
3924
3926}
const char * str
static char buf[DEFAULT_XLOG_SEG_SIZE]
void appendPQExpBufferStr(PQExpBuffer str, const char *data)

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

3724{
3725 /* relkinds for which we support tablespaces */
3726 if (relkind == RELKIND_RELATION ||
3727 relkind == RELKIND_MATVIEW ||
3728 relkind == RELKIND_INDEX ||
3729 relkind == RELKIND_PARTITIONED_TABLE ||
3730 relkind == RELKIND_PARTITIONED_INDEX ||
3731 relkind == RELKIND_TOASTVALUE)
3732 {
3733 /*
3734 * We ignore the database default tablespace so that users not using
3735 * tablespaces don't need to know about them.
3736 */
3737 if (tablespace != 0)
3738 {
3739 PGresult *result = NULL;
3741
3743 printfPQExpBuffer(&buf, "/* %s */\n",
3744 _("Get tablespace information for this relation"));
3746 "SELECT spcname FROM pg_catalog.pg_tablespace\n"
3747 "WHERE oid = '%u';", tablespace);
3748 result = PSQLexec(buf.data);
3749 if (!result)
3750 {
3752 return;
3753 }
3754 /* Should always be the case, but.... */
3755 if (PQntuples(result) > 0)
3756 {
3757 if (newline)
3758 {
3759 /* Add the tablespace as a new footer */
3760 printfPQExpBuffer(&buf, _("Tablespace: \"%s\""),
3761 PQgetvalue(result, 0, 0));
3763 }
3764 else
3765 {
3766 /* Append the tablespace to the latest footer */
3767 printfPQExpBuffer(&buf, "%s", cont->footer->data);
3768
3769 /*-------
3770 translator: before this string there's an index description like
3771 '"foo_pkey" PRIMARY KEY, btree (a)' */
3772 appendPQExpBuffer(&buf, _(", tablespace \"%s\""),
3773 PQgetvalue(result, 0, 0));
3775 }
3776 }
3777 PQclear(result);
3779 }
3780 }
3781}
PGresult * PSQLexec(const char *query)
Definition common.c:657
uint32 result
#define _(x)
Definition elog.c:96
void printTableSetFooter(printTableContent *const content, const char *footer)
Definition print.c:3372
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition print.c:3347
#define newline
#define PQgetvalue
#define PQclear
#define PQntuples
static char * tablespace
Definition pgbench.c:217
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void initPQExpBuffer(PQExpBuffer str)
Definition pqexpbuffer.c:90
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void termPQExpBuffer(PQExpBuffer str)
static int fb(int x)

References _, appendPQExpBuffer(), buf, fb(), initPQExpBuffer(), newline, PQclear, PQgetvalue, PQntuples, printfPQExpBuffer(), printTableAddFooter(), printTableSetFooter(), PSQLexec(), result, 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 6575 of file describe.c.

6577{
6578 PGresult *res;
6579 int count = 0;
6580 int i = 0;
6581
6582 res = PSQLexec(buf->data);
6583 if (!res)
6584 return false;
6585 else
6586 count = PQntuples(res);
6587
6588 if (count > 0)
6590
6591 for (i = 0; i < count; i++)
6592 {
6593 if (as_schema)
6594 printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, 0));
6595 else
6596 {
6597 printfPQExpBuffer(buf, " \"%s.%s\"", PQgetvalue(res, i, 0),
6598 PQgetvalue(res, i, 1));
6599
6600 if (!PQgetisnull(res, i, 3))
6601 appendPQExpBuffer(buf, " (%s)", PQgetvalue(res, i, 3));
6602
6603 if (!PQgetisnull(res, i, 2))
6604 appendPQExpBuffer(buf, " WHERE %s", PQgetvalue(res, i, 2));
6605 }
6606
6608 }
6609
6610 PQclear(res);
6611 return true;
6612}
int i
Definition isn.c:77
#define PQgetisnull

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

Referenced by describePublications().

◆ describeAccessMethods()

bool describeAccessMethods ( const char pattern,
bool  verbose 
)

Definition at line 150 of file describe.c.

151{
153 PGresult *res;
155 static const bool translate_columns[] = {false, true, false, false};
156
158
159 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching access methods"));
161 "SELECT amname AS \"%s\",\n"
162 " CASE amtype"
163 " WHEN " CppAsString2(AMTYPE_INDEX) " THEN '%s'"
164 " WHEN " CppAsString2(AMTYPE_TABLE) " THEN '%s'"
165 " END AS \"%s\"",
166 gettext_noop("Name"),
167 gettext_noop("Index"),
168 gettext_noop("Table"),
169 gettext_noop("Type"));
170
171 if (verbose)
172 {
174 ",\n amhandler AS \"%s\",\n"
175 " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"",
176 gettext_noop("Handler"),
177 gettext_noop("Description"));
178 }
179
181 "\nFROM pg_catalog.pg_am\n");
182
183 if (!validateSQLNamePattern(&buf, pattern, false, false,
184 NULL, "amname", NULL,
185 NULL,
186 NULL, 1))
187 {
189 return false;
190 }
191
192 appendPQExpBufferStr(&buf, "ORDER BY 1;");
193
194 res = PSQLexec(buf.data);
196 if (!res)
197 return false;
198
199 myopt.title = _("List of access methods");
200 myopt.translate_header = true;
201 myopt.translate_columns = translate_columns;
202 myopt.n_translate_columns = lengthof(translate_columns);
203
204 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
205
206 PQclear(res);
207 return true;
208}
#define gettext_noop(x)
Definition c.h:1325
#define CppAsString2(x)
Definition c.h:565
#define lengthof(array)
Definition c.h:932
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:6439
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition print.c:3760
static int verbose
PsqlSettings pset
Definition startup.c:33
printQueryOpt popt
Definition settings.h:112
FILE * logfile
Definition settings.h:149
FILE * queryFout
Definition settings.h:105

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, fb(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, _psqlSettings::popt, PQclear, printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, termPQExpBuffer(), validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ describeAggregates()

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

Definition at line 79 of file describe.c.

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

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

Referenced by exec_command_d().

◆ describeConfigurationParameters()

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

Definition at line 4791 of file describe.c.

4793{
4795 PGresult *res;
4797
4799
4800 printfPQExpBuffer(&buf, "/* %s */\n",
4801 _("Get matching configuration parameters"));
4803 "SELECT s.name AS \"%s\", "
4804 "pg_catalog.current_setting(s.name) AS \"%s\"",
4805 gettext_noop("Parameter"),
4806 gettext_noop("Value"));
4807
4808 if (verbose)
4809 {
4811 ", s.vartype AS \"%s\", s.context AS \"%s\", ",
4812 gettext_noop("Type"),
4813 gettext_noop("Context"));
4814 if (pset.sversion >= 150000)
4815 printACLColumn(&buf, "p.paracl");
4816 else
4817 appendPQExpBuffer(&buf, "NULL AS \"%s\"",
4818 gettext_noop("Access privileges"));
4819 }
4820
4821 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_settings s\n");
4822
4823 if (verbose && pset.sversion >= 150000)
4825 " LEFT JOIN pg_catalog.pg_parameter_acl p\n"
4826 " ON pg_catalog.lower(s.name) = p.parname\n");
4827
4828 if (pattern)
4829 processSQLNamePattern(pset.db, &buf, pattern,
4830 false, false,
4831 NULL, "pg_catalog.lower(s.name)", NULL,
4832 NULL, NULL, NULL);
4833 else
4834 appendPQExpBufferStr(&buf, "WHERE s.source <> 'default' AND\n"
4835 " s.setting IS DISTINCT FROM s.boot_val\n");
4836
4837 appendPQExpBufferStr(&buf, "ORDER BY 1;");
4838
4839 res = PSQLexec(buf.data);
4841 if (!res)
4842 return false;
4843
4844 if (pattern)
4845 myopt.title = _("List of configuration parameters");
4846 else
4847 myopt.title = _("List of non-default configuration parameters");
4848 myopt.translate_header = true;
4849
4850 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4851
4852 PQclear(res);
4853 return true;
4854}
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition describe.c:7042
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, fb(), gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear, printACLColumn(), printfPQExpBuffer(), printQuery(), processSQLNamePattern(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), 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 289 of file describe.c.

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

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, fb(), formatPGVersionNumber(), gettext_noop, i, initPQExpBuffer(), lengthof, _psqlSettings::logfile, map_typename_pattern(), pg_log_error, _psqlSettings::popt, PQclear, printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, snprintf, _psqlSettings::sversion, termPQExpBuffer(), 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 1535 of file describe.c.

1539{
1540 bool retval = false;
1542 PGresult *res = NULL;
1545 bool printTableInitialized = false;
1546 int i;
1547 char *view_def = NULL;
1548 char *headers[12];
1549 PQExpBufferData title;
1551 int cols;
1552 int attname_col = -1, /* column indexes in "res" */
1553 atttype_col = -1,
1554 attrdef_col = -1,
1555 attnotnull_col = -1,
1556 attcoll_col = -1,
1557 attidentity_col = -1,
1558 attgenerated_col = -1,
1559 isindexkey_col = -1,
1560 indexdef_col = -1,
1561 fdwopts_col = -1,
1562 attstorage_col = -1,
1563 attcompression_col = -1,
1564 attstattarget_col = -1,
1565 attdescr_col = -1;
1566 int numrows;
1567 struct
1568 {
1569 int16 checks;
1570 char relkind;
1571 bool hasindex;
1572 bool hasrules;
1573 bool hastriggers;
1574 bool rowsecurity;
1575 bool forcerowsecurity;
1576 bool hasoids;
1577 bool ispartition;
1579 char *reloptions;
1580 char *reloftype;
1581 char relpersistence;
1582 char relreplident;
1583 char *relam;
1584 } tableinfo;
1585 bool show_column_details = false;
1586
1587 myopt.default_footer = false;
1588 /* This output looks confusing in expanded mode. */
1589 myopt.expanded = false;
1590
1592 initPQExpBuffer(&title);
1594
1595 /* Get general table info */
1596 printfPQExpBuffer(&buf, "/* %s */\n",
1597 _("Get general information about one relation"));
1598 if (pset.sversion >= 120000)
1599 {
1601 "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
1602 "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
1603 "false AS relhasoids, c.relispartition, %s, c.reltablespace, "
1604 "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
1605 "c.relpersistence, c.relreplident, am.amname\n"
1606 "FROM pg_catalog.pg_class c\n "
1607 "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
1608 "LEFT JOIN pg_catalog.pg_am am ON (c.relam = am.oid)\n"
1609 "WHERE c.oid = '%s';",
1610 (verbose ?
1611 "pg_catalog.array_to_string(c.reloptions || "
1612 "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
1613 : "''"),
1614 oid);
1615 }
1616 else
1617 {
1619 "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
1620 "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
1621 "c.relhasoids, c.relispartition, %s, c.reltablespace, "
1622 "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
1623 "c.relpersistence, c.relreplident\n"
1624 "FROM pg_catalog.pg_class c\n "
1625 "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
1626 "WHERE c.oid = '%s';",
1627 (verbose ?
1628 "pg_catalog.array_to_string(c.reloptions || "
1629 "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
1630 : "''"),
1631 oid);
1632 }
1633
1634 res = PSQLexec(buf.data);
1635 if (!res)
1636 goto error_return;
1637
1638 /* Did we get anything? */
1639 if (PQntuples(res) == 0)
1640 {
1641 if (!pset.quiet)
1642 pg_log_error("Did not find any relation with OID %s.", oid);
1643 goto error_return;
1644 }
1645
1646 tableinfo.checks = atoi(PQgetvalue(res, 0, 0));
1647 tableinfo.relkind = *(PQgetvalue(res, 0, 1));
1648 tableinfo.hasindex = strcmp(PQgetvalue(res, 0, 2), "t") == 0;
1649 tableinfo.hasrules = strcmp(PQgetvalue(res, 0, 3), "t") == 0;
1650 tableinfo.hastriggers = strcmp(PQgetvalue(res, 0, 4), "t") == 0;
1651 tableinfo.rowsecurity = strcmp(PQgetvalue(res, 0, 5), "t") == 0;
1652 tableinfo.forcerowsecurity = strcmp(PQgetvalue(res, 0, 6), "t") == 0;
1653 tableinfo.hasoids = strcmp(PQgetvalue(res, 0, 7), "t") == 0;
1654 tableinfo.ispartition = strcmp(PQgetvalue(res, 0, 8), "t") == 0;
1655 tableinfo.reloptions = pg_strdup(PQgetvalue(res, 0, 9));
1656 tableinfo.tablespace = atooid(PQgetvalue(res, 0, 10));
1657 tableinfo.reloftype = (strcmp(PQgetvalue(res, 0, 11), "") != 0) ?
1658 pg_strdup(PQgetvalue(res, 0, 11)) : NULL;
1659 tableinfo.relpersistence = *(PQgetvalue(res, 0, 12));
1660 tableinfo.relreplident = *(PQgetvalue(res, 0, 13));
1661 if (pset.sversion >= 120000)
1662 tableinfo.relam = PQgetisnull(res, 0, 14) ?
1663 NULL : pg_strdup(PQgetvalue(res, 0, 14));
1664 else
1665 tableinfo.relam = NULL;
1666 PQclear(res);
1667 res = NULL;
1668
1669 /*
1670 * If it's a sequence, deal with it here separately.
1671 */
1672 if (tableinfo.relkind == RELKIND_SEQUENCE)
1673 {
1674 PGresult *result = NULL;
1676 char *footers[3] = {NULL, NULL, NULL};
1677
1678 printfPQExpBuffer(&buf, "/* %s */\n", _("Get sequence information"));
1680 "SELECT pg_catalog.format_type(seqtypid, NULL) AS \"%s\",\n"
1681 " seqstart AS \"%s\",\n"
1682 " seqmin AS \"%s\",\n"
1683 " seqmax AS \"%s\",\n"
1684 " seqincrement AS \"%s\",\n"
1685 " CASE WHEN seqcycle THEN '%s' ELSE '%s' END AS \"%s\",\n"
1686 " seqcache AS \"%s\"\n",
1687 gettext_noop("Type"),
1688 gettext_noop("Start"),
1689 gettext_noop("Minimum"),
1690 gettext_noop("Maximum"),
1691 gettext_noop("Increment"),
1692 gettext_noop("yes"),
1693 gettext_noop("no"),
1694 gettext_noop("Cycles?"),
1695 gettext_noop("Cache"));
1697 "FROM pg_catalog.pg_sequence\n"
1698 "WHERE seqrelid = '%s';",
1699 oid);
1700
1701 res = PSQLexec(buf.data);
1702 if (!res)
1703 goto error_return;
1704
1705 /* Get the column that owns this sequence */
1706 printfPQExpBuffer(&buf, "/* %s */\n",
1707 _("Get the column that owns this sequence"));
1708 appendPQExpBuffer(&buf, "SELECT pg_catalog.quote_ident(nspname) || '.' ||"
1709 "\n pg_catalog.quote_ident(relname) || '.' ||"
1710 "\n pg_catalog.quote_ident(attname),"
1711 "\n d.deptype"
1712 "\nFROM pg_catalog.pg_class c"
1713 "\nINNER JOIN pg_catalog.pg_depend d ON c.oid=d.refobjid"
1714 "\nINNER JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace"
1715 "\nINNER JOIN pg_catalog.pg_attribute a ON ("
1716 "\n a.attrelid=c.oid AND"
1717 "\n a.attnum=d.refobjsubid)"
1718 "\nWHERE d.classid='pg_catalog.pg_class'::pg_catalog.regclass"
1719 "\n AND d.refclassid='pg_catalog.pg_class'::pg_catalog.regclass"
1720 "\n AND d.objid='%s'"
1721 "\n AND d.deptype IN ('a', 'i')",
1722 oid);
1723
1724 result = PSQLexec(buf.data);
1725
1726 /*
1727 * If we get no rows back, don't show anything (obviously). We should
1728 * never get more than one row back, but if we do, just ignore it and
1729 * don't print anything.
1730 */
1731 if (!result)
1732 goto error_return;
1733 else if (PQntuples(result) == 1)
1734 {
1735 switch (PQgetvalue(result, 0, 1)[0])
1736 {
1737 case 'a':
1738 footers[0] = psprintf(_("Owned by: %s"),
1739 PQgetvalue(result, 0, 0));
1740 break;
1741 case 'i':
1742 footers[0] = psprintf(_("Sequence for identity column: %s"),
1743 PQgetvalue(result, 0, 0));
1744 break;
1745 }
1746 }
1747 PQclear(result);
1748
1749 /* Print any publications */
1750 if (pset.sversion >= 190000)
1751 {
1752 printfPQExpBuffer(&buf, "/* %s */\n",
1753 _("Get publications containing this sequence"));
1754 appendPQExpBuffer(&buf, "SELECT pubname FROM pg_catalog.pg_publication p"
1755 "\nWHERE p.puballsequences"
1756 "\n AND pg_catalog.pg_relation_is_publishable('%s')"
1757 "\nORDER BY 1",
1758 oid);
1759
1760 result = PSQLexec(buf.data);
1761 if (result)
1762 {
1763 int nrows = PQntuples(result);
1764
1765 if (nrows > 0)
1766 {
1767 printfPQExpBuffer(&tmpbuf, _("Included in publications:"));
1768 for (i = 0; i < nrows; i++)
1769 appendPQExpBuffer(&tmpbuf, "\n \"%s\"", PQgetvalue(result, i, 0));
1770
1771 /* Store in the first available footer slot */
1772 if (footers[0] == NULL)
1773 footers[0] = pg_strdup(tmpbuf.data);
1774 else
1775 footers[1] = pg_strdup(tmpbuf.data);
1776
1778 }
1779
1780 PQclear(result);
1781 }
1782 }
1783
1784 if (tableinfo.relpersistence == RELPERSISTENCE_UNLOGGED)
1785 printfPQExpBuffer(&title, _("Unlogged sequence \"%s.%s\""),
1786 schemaname, relationname);
1787 else
1788 printfPQExpBuffer(&title, _("Sequence \"%s.%s\""),
1789 schemaname, relationname);
1790
1791 myopt.footers = footers;
1792 myopt.topt.default_footer = false;
1793 myopt.title = title.data;
1794 myopt.translate_header = true;
1795
1796 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1797
1798 pg_free(footers[0]);
1799 pg_free(footers[1]);
1800
1801 retval = true;
1802 goto error_return; /* not an error, just return early */
1803 }
1804
1805 /*
1806 * If it's a property graph, deal with it here separately.
1807 */
1808 if (tableinfo.relkind == RELKIND_PROPGRAPH)
1809 {
1810 printQueryOpt popt = pset.popt;
1811 char *footers[3] = {NULL, NULL, NULL};
1812
1813 printfPQExpBuffer(&buf, "/* %s */\n", _("Get property graph information"));
1815 "SELECT e.pgealias AS \"%s\","
1816 "\n pg_catalog.quote_ident(n.nspname) || '.' ||"
1817 "\n pg_catalog.quote_ident(c.relname) AS \"%s\","
1818 "\n case e.pgekind when " CppAsString2(PGEKIND_VERTEX) " then 'vertex'"
1819 "\n when " CppAsString2(PGEKIND_EDGE) " then 'edge' end AS \"%s\","
1820 "\n s.pgealias as \"%s\","
1821 "\n d.pgealias as \"%s\""
1822 "\n FROM pg_catalog.pg_propgraph_element e"
1823 "\n INNER JOIN pg_catalog.pg_class c ON c.oid = e.pgerelid"
1824 "\n INNER JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid"
1825 "\n LEFT JOIN pg_catalog.pg_propgraph_element s ON e.pgesrcvertexid = s.oid"
1826 "\n LEFT JOIN pg_catalog.pg_propgraph_element d ON e.pgedestvertexid = d.oid"
1827 "\n WHERE e.pgepgid = '%s'"
1828 "\n ORDER BY e.pgealias",
1829 gettext_noop("Element Alias"),
1830 gettext_noop("Element Table"),
1831 gettext_noop("Element Kind"),
1832 gettext_noop("Source Vertex Alias"),
1833 gettext_noop("Destination Vertex Alias"),
1834 oid);
1835
1836 res = PSQLexec(buf.data);
1837 if (!res)
1838 goto error_return;
1839
1840 printfPQExpBuffer(&title, _("Property Graph \"%s.%s\""),
1841 schemaname, relationname);
1842
1843 /* Add property graph definition in verbose mode */
1844 if (verbose)
1845 {
1847
1848 printfPQExpBuffer(&buf, "/* %s */\n", _("Get property graph definition"));
1850 "SELECT pg_catalog.pg_get_propgraphdef('%s'::pg_catalog.oid);",
1851 oid);
1852 result = PSQLexec(buf.data);
1853
1854 if (result)
1855 {
1856 if (PQntuples(result) > 0)
1857 {
1858 footers[0] = pg_strdup(_("Property graph definition:"));
1859 footers[1] = pg_strdup(PQgetvalue(result, 0, 0));
1860 }
1861 PQclear(result);
1862 }
1863 }
1864
1865 popt.footers = footers;
1866 popt.topt.default_footer = false;
1867 popt.title = title.data;
1868 popt.translate_header = true;
1869
1870 printQuery(res, &popt, pset.queryFout, false, pset.logfile);
1871
1872 pg_free(footers[0]);
1873 pg_free(footers[1]);
1874
1875 retval = true;
1876 goto error_return; /* not an error, just return early */
1877 }
1878
1879 /* Identify whether we should print collation, nullable, default vals */
1880 if (tableinfo.relkind == RELKIND_RELATION ||
1881 tableinfo.relkind == RELKIND_VIEW ||
1882 tableinfo.relkind == RELKIND_MATVIEW ||
1883 tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
1884 tableinfo.relkind == RELKIND_COMPOSITE_TYPE ||
1886 show_column_details = true;
1887
1888 /*
1889 * Get per-column info
1890 *
1891 * Since the set of query columns we need varies depending on relkind and
1892 * server version, we compute all the column numbers on-the-fly. Column
1893 * number variables for columns not fetched are left as -1; this avoids
1894 * duplicative test logic below.
1895 */
1896 cols = 0;
1897 printfPQExpBuffer(&buf, "/* %s */\n",
1898 _("Get per-column information for one relation"));
1899 appendPQExpBufferStr(&buf, "SELECT a.attname");
1900 attname_col = cols++;
1901 appendPQExpBufferStr(&buf, ",\n pg_catalog.format_type(a.atttypid, a.atttypmod)");
1902 atttype_col = cols++;
1903
1905 {
1906 /* use "pretty" mode for expression to avoid excessive parentheses */
1908 ",\n (SELECT pg_catalog.pg_get_expr(d.adbin, d.adrelid, true)"
1909 "\n FROM pg_catalog.pg_attrdef d"
1910 "\n WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef)"
1911 ",\n a.attnotnull");
1912 attrdef_col = cols++;
1913 attnotnull_col = cols++;
1914 appendPQExpBufferStr(&buf, ",\n (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type t\n"
1915 " WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation) AS attcollation");
1916 attcoll_col = cols++;
1917 appendPQExpBufferStr(&buf, ",\n a.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 ||
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 ||
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 ||
1967 tableinfo.relkind == RELKIND_MATVIEW ||
1968 tableinfo.relkind == RELKIND_FOREIGN_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 ||
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;
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;
2040 printfPQExpBuffer(&title, _("Composite type \"%s.%s\""),
2041 schemaname, relationname);
2042 break;
2044 printfPQExpBuffer(&title, _("Foreign table \"%s.%s\""),
2045 schemaname, relationname);
2046 break;
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");
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 */
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
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
2139
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)
2183 false, false);
2184
2185 /* Column comments, if the relkind supports this feature */
2186 if (attdescr_col >= 0)
2188 false, false);
2189 }
2190
2191 /* Make footers */
2192
2193 if (tableinfo.ispartition)
2194 {
2195 /* Footer information for a partition child table */
2197
2198 printfPQExpBuffer(&buf, "/* %s */\n",
2199 _("Get partitioning information for this partition"));
2201 "SELECT inhparent::pg_catalog.regclass,\n"
2202 " pg_catalog.pg_get_expr(c.relpartbound, c.oid),\n ");
2203
2205 pset.sversion >= 140000 ? "inhdetachpending" :
2206 "false as inhdetachpending");
2207
2208 /* If verbose, also request the partition constraint definition */
2209 if (verbose)
2211 ",\n pg_catalog.pg_get_partition_constraintdef(c.oid)");
2213 "\nFROM pg_catalog.pg_class c"
2214 " JOIN pg_catalog.pg_inherits i"
2215 " ON c.oid = inhrelid"
2216 "\nWHERE c.oid = '%s';", oid);
2217 result = PSQLexec(buf.data);
2218 if (!result)
2219 goto error_return;
2220
2221 if (PQntuples(result) > 0)
2222 {
2223 char *parent_name = PQgetvalue(result, 0, 0);
2224 char *partdef = PQgetvalue(result, 0, 1);
2225 char *detached = PQgetvalue(result, 0, 2);
2226
2227 printfPQExpBuffer(&tmpbuf, _("Partition of: %s %s%s"), parent_name,
2228 partdef,
2229 strcmp(detached, "t") == 0 ? " DETACH PENDING" : "");
2231
2232 if (verbose)
2233 {
2234 char *partconstraintdef = NULL;
2235
2236 if (!PQgetisnull(result, 0, 3))
2238 /* If there isn't any constraint, show that explicitly */
2239 if (partconstraintdef == NULL || partconstraintdef[0] == '\0')
2240 printfPQExpBuffer(&tmpbuf, _("No partition constraint"));
2241 else
2242 printfPQExpBuffer(&tmpbuf, _("Partition constraint: %s"),
2245 }
2246 }
2247 PQclear(result);
2248 }
2249
2250 if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
2251 {
2252 /* Footer information for a partitioned table (partitioning parent) */
2254
2255 printfPQExpBuffer(&buf, "/* %s */\n",
2256 _("Get partitioning information for this table"));
2258 "SELECT pg_catalog.pg_get_partkeydef('%s'::pg_catalog.oid);",
2259 oid);
2260 result = PSQLexec(buf.data);
2261 if (!result)
2262 goto error_return;
2263
2264 if (PQntuples(result) == 1)
2265 {
2266 char *partkeydef = PQgetvalue(result, 0, 0);
2267
2268 printfPQExpBuffer(&tmpbuf, _("Partition key: %s"), partkeydef);
2270 }
2271 PQclear(result);
2272 }
2273
2274 if (tableinfo.relkind == RELKIND_TOASTVALUE)
2275 {
2276 /* For a TOAST table, print name of owning table */
2278
2279 printfPQExpBuffer(&buf, "/* %s */\n",
2280 _("Get the table that owns this TOAST table"));
2282 "SELECT n.nspname, c.relname\n"
2283 "FROM pg_catalog.pg_class c"
2284 " JOIN pg_catalog.pg_namespace n"
2285 " ON n.oid = c.relnamespace\n"
2286 "WHERE reltoastrelid = '%s';", oid);
2287 result = PSQLexec(buf.data);
2288 if (!result)
2289 goto error_return;
2290
2291 if (PQntuples(result) == 1)
2292 {
2293 char *schemaname = PQgetvalue(result, 0, 0);
2294 char *relname = PQgetvalue(result, 0, 1);
2295
2296 printfPQExpBuffer(&tmpbuf, _("Owning table: \"%s.%s\""),
2297 schemaname, relname);
2299 }
2300 PQclear(result);
2301 }
2302
2303 if (tableinfo.relkind == RELKIND_INDEX ||
2305 {
2306 /* Footer information about an index */
2308
2309 printfPQExpBuffer(&buf, "/* %s */\n", _("Get index details"));
2311 "SELECT i.indisunique, i.indisprimary, i.indisclustered, "
2312 "i.indisvalid,\n"
2313 " (NOT i.indimmediate) AND "
2314 "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
2315 "WHERE conrelid = i.indrelid AND "
2316 "conindid = i.indexrelid AND "
2317 "contype IN (" CppAsString2(CONSTRAINT_PRIMARY) ","
2320 "condeferrable) AS condeferrable,\n"
2321 " (NOT i.indimmediate) AND "
2322 "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
2323 "WHERE conrelid = i.indrelid AND "
2324 "conindid = i.indexrelid AND "
2325 "contype IN (" CppAsString2(CONSTRAINT_PRIMARY) ","
2328 "condeferred) AS condeferred,\n");
2329
2330 appendPQExpBufferStr(&buf, "i.indisreplident,\n");
2331
2332 if (pset.sversion >= 150000)
2333 appendPQExpBufferStr(&buf, "i.indnullsnotdistinct,\n");
2334 else
2335 appendPQExpBufferStr(&buf, "false AS indnullsnotdistinct,\n");
2336
2337 appendPQExpBuffer(&buf, " a.amname, c2.relname, "
2338 "pg_catalog.pg_get_expr(i.indpred, i.indrelid, true)\n"
2339 "FROM pg_catalog.pg_index i, pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_am a\n"
2340 "WHERE i.indexrelid = c.oid AND c.oid = '%s' AND c.relam = a.oid\n"
2341 "AND i.indrelid = c2.oid;",
2342 oid);
2343
2344 result = PSQLexec(buf.data);
2345 if (!result)
2346 goto error_return;
2347 else if (PQntuples(result) != 1)
2348 {
2349 PQclear(result);
2350 goto error_return;
2351 }
2352 else
2353 {
2354 char *indisunique = PQgetvalue(result, 0, 0);
2355 char *indisprimary = PQgetvalue(result, 0, 1);
2356 char *indisclustered = PQgetvalue(result, 0, 2);
2357 char *indisvalid = PQgetvalue(result, 0, 3);
2358 char *deferrable = PQgetvalue(result, 0, 4);
2359 char *deferred = PQgetvalue(result, 0, 5);
2360 char *indisreplident = PQgetvalue(result, 0, 6);
2361 char *indnullsnotdistinct = PQgetvalue(result, 0, 7);
2362 char *indamname = PQgetvalue(result, 0, 8);
2363 char *indtable = PQgetvalue(result, 0, 9);
2364 char *indpred = PQgetvalue(result, 0, 10);
2365
2366 if (strcmp(indisprimary, "t") == 0)
2367 printfPQExpBuffer(&tmpbuf, _("primary key, "));
2368 else if (strcmp(indisunique, "t") == 0)
2369 {
2370 if (strcmp(indnullsnotdistinct, "t") == 0)
2371 printfPQExpBuffer(&tmpbuf, _("unique nulls not distinct, "));
2372 else
2373 printfPQExpBuffer(&tmpbuf, _("unique, "));
2374 }
2375 else
2377
2378 /* we assume here that index and table are in same schema */
2379 /*- translator: the first %s is an index AM name (eg. btree) */
2380 appendPQExpBuffer(&tmpbuf, _("%s, for table \"%s.%s\""),
2381 indamname, schemaname, indtable);
2382
2383 if (strlen(indpred))
2384 appendPQExpBuffer(&tmpbuf, _(", predicate (%s)"), indpred);
2385
2386 if (strcmp(indisclustered, "t") == 0)
2387 appendPQExpBufferStr(&tmpbuf, _(", clustered"));
2388
2389 if (strcmp(indisvalid, "t") != 0)
2390 appendPQExpBufferStr(&tmpbuf, _(", invalid"));
2391
2392 if (strcmp(deferrable, "t") == 0)
2393 appendPQExpBufferStr(&tmpbuf, _(", deferrable"));
2394
2395 if (strcmp(deferred, "t") == 0)
2396 appendPQExpBufferStr(&tmpbuf, _(", initially deferred"));
2397
2398 if (strcmp(indisreplident, "t") == 0)
2399 appendPQExpBufferStr(&tmpbuf, _(", replica identity"));
2400
2402
2403 /*
2404 * If it's a partitioned index, we'll print the tablespace below
2405 */
2406 if (tableinfo.relkind == RELKIND_INDEX)
2408 tableinfo.tablespace, true);
2409 }
2410
2411 PQclear(result);
2412 }
2413 /* If you add relkinds here, see also "Finish printing..." stanza below */
2414 else if (tableinfo.relkind == RELKIND_RELATION ||
2415 tableinfo.relkind == RELKIND_MATVIEW ||
2416 tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
2419 tableinfo.relkind == RELKIND_TOASTVALUE)
2420 {
2421 /* Footer information about a table */
2422 PGresult *result = NULL;
2423 int tuples = 0;
2424
2425 /* print indexes */
2426 if (tableinfo.hasindex)
2427 {
2428 printfPQExpBuffer(&buf, "/* %s */\n", _("Get indexes for this table"));
2430 "SELECT c2.relname, i.indisprimary, i.indisunique, "
2431 "i.indisclustered, i.indisvalid, "
2432 "pg_catalog.pg_get_indexdef(i.indexrelid, 0, true),\n "
2433 "pg_catalog.pg_get_constraintdef(con.oid, true), "
2434 "contype, condeferrable, condeferred");
2435 appendPQExpBufferStr(&buf, ", i.indisreplident");
2436 appendPQExpBufferStr(&buf, ", c2.reltablespace");
2437 if (pset.sversion >= 180000)
2438 appendPQExpBufferStr(&buf, ", con.conperiod");
2439 else
2440 appendPQExpBufferStr(&buf, ", false AS conperiod");
2442 "\nFROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i\n"
2443 " LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN ("
2447 "WHERE c.oid = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
2448 "ORDER BY i.indisprimary DESC, c2.relname;",
2449 oid);
2450 result = PSQLexec(buf.data);
2451 if (!result)
2452 goto error_return;
2453 else
2454 tuples = PQntuples(result);
2455
2456 if (tuples > 0)
2457 {
2458 printTableAddFooter(&cont, _("Indexes:"));
2459 for (i = 0; i < tuples; i++)
2460 {
2461 /* untranslated index name */
2462 printfPQExpBuffer(&buf, " \"%s\"",
2463 PQgetvalue(result, i, 0));
2464
2465 /*
2466 * If exclusion constraint or PK/UNIQUE constraint WITHOUT
2467 * OVERLAPS, print the constraintdef
2468 */
2469 if (strcmp(PQgetvalue(result, i, 7), "x") == 0 ||
2470 strcmp(PQgetvalue(result, i, 12), "t") == 0)
2471 {
2472 appendPQExpBuffer(&buf, " %s",
2473 PQgetvalue(result, i, 6));
2474 }
2475 else
2476 {
2477 const char *indexdef;
2478 const char *usingpos;
2479
2480 /* Label as primary key or unique (but not both) */
2481 if (strcmp(PQgetvalue(result, i, 1), "t") == 0)
2482 appendPQExpBufferStr(&buf, " PRIMARY KEY,");
2483 else if (strcmp(PQgetvalue(result, i, 2), "t") == 0)
2484 {
2485 if (strcmp(PQgetvalue(result, i, 7), "u") == 0)
2486 appendPQExpBufferStr(&buf, " UNIQUE CONSTRAINT,");
2487 else
2488 appendPQExpBufferStr(&buf, " UNIQUE,");
2489 }
2490
2491 /* Everything after "USING" is echoed verbatim */
2492 indexdef = PQgetvalue(result, i, 5);
2493 usingpos = strstr(indexdef, " USING ");
2494 if (usingpos)
2495 indexdef = usingpos + 7;
2496 appendPQExpBuffer(&buf, " %s", indexdef);
2497
2498 /* Need these for deferrable PK/UNIQUE indexes */
2499 if (strcmp(PQgetvalue(result, i, 8), "t") == 0)
2500 appendPQExpBufferStr(&buf, " DEFERRABLE");
2501
2502 if (strcmp(PQgetvalue(result, i, 9), "t") == 0)
2503 appendPQExpBufferStr(&buf, " INITIALLY DEFERRED");
2504 }
2505
2506 /* Add these for all cases */
2507 if (strcmp(PQgetvalue(result, i, 3), "t") == 0)
2508 appendPQExpBufferStr(&buf, " CLUSTER");
2509
2510 if (strcmp(PQgetvalue(result, i, 4), "t") != 0)
2511 appendPQExpBufferStr(&buf, " INVALID");
2512
2513 if (strcmp(PQgetvalue(result, i, 10), "t") == 0)
2514 appendPQExpBufferStr(&buf, " REPLICA IDENTITY");
2515
2517
2518 /* Print tablespace of the index on the same line */
2520 atooid(PQgetvalue(result, i, 11)),
2521 false);
2522 }
2523 }
2524 PQclear(result);
2525 }
2526
2527 /* print table (and column) check constraints */
2528 if (tableinfo.checks)
2529 {
2530 printfPQExpBuffer(&buf, "/* %s */\n",
2531 _("Get check constraints for this table"));
2533 "SELECT r.conname, "
2534 "pg_catalog.pg_get_constraintdef(r.oid, true)\n"
2535 "FROM pg_catalog.pg_constraint r\n"
2536 "WHERE r.conrelid = '%s' "
2537 "AND r.contype = " CppAsString2(CONSTRAINT_CHECK) "\n"
2538 "ORDER BY 1;",
2539 oid);
2540 result = PSQLexec(buf.data);
2541 if (!result)
2542 goto error_return;
2543 else
2544 tuples = PQntuples(result);
2545
2546 if (tuples > 0)
2547 {
2548 printTableAddFooter(&cont, _("Check constraints:"));
2549 for (i = 0; i < tuples; i++)
2550 {
2551 /* untranslated constraint name and def */
2552 printfPQExpBuffer(&buf, " \"%s\" %s",
2553 PQgetvalue(result, i, 0),
2554 PQgetvalue(result, i, 1));
2555
2557 }
2558 }
2559 PQclear(result);
2560 }
2561
2562 /* Print foreign-key constraints */
2563 printfPQExpBuffer(&buf, "/* %s */\n",
2564 _("Get foreign key constraints for this table"));
2565 if (pset.sversion >= 120000 &&
2566 (tableinfo.ispartition || tableinfo.relkind == RELKIND_PARTITIONED_TABLE))
2567 {
2568 /*
2569 * Put the constraints defined in this table first, followed by
2570 * the constraints defined in ancestor partitioned tables.
2571 */
2573 "SELECT conrelid = '%s'::pg_catalog.regclass AS sametable,\n"
2574 " conname,\n"
2575 " pg_catalog.pg_get_constraintdef(oid, true) AS condef,\n"
2576 " conrelid::pg_catalog.regclass AS ontable\n"
2577 " FROM pg_catalog.pg_constraint,\n"
2578 " pg_catalog.pg_partition_ancestors('%s')\n"
2579 " WHERE conrelid = relid AND contype = " CppAsString2(CONSTRAINT_FOREIGN) " AND conparentid = 0\n"
2580 "ORDER BY sametable DESC, conname;",
2581 oid, oid);
2582 }
2583 else
2584 {
2586 "SELECT true as sametable, conname,\n"
2587 " pg_catalog.pg_get_constraintdef(r.oid, true) as condef,\n"
2588 " conrelid::pg_catalog.regclass AS ontable\n"
2589 "FROM pg_catalog.pg_constraint r\n"
2590 "WHERE r.conrelid = '%s' AND r.contype = " CppAsString2(CONSTRAINT_FOREIGN) "\n",
2591 oid);
2592
2593 if (pset.sversion >= 120000)
2594 appendPQExpBufferStr(&buf, " AND conparentid = 0\n");
2595 appendPQExpBufferStr(&buf, "ORDER BY conname");
2596 }
2597
2598 result = PSQLexec(buf.data);
2599 if (!result)
2600 goto error_return;
2601 else
2602 tuples = PQntuples(result);
2603
2604 if (tuples > 0)
2605 {
2606 int i_sametable = PQfnumber(result, "sametable"),
2607 i_conname = PQfnumber(result, "conname"),
2608 i_condef = PQfnumber(result, "condef"),
2609 i_ontable = PQfnumber(result, "ontable");
2610
2611 printTableAddFooter(&cont, _("Foreign-key constraints:"));
2612 for (i = 0; i < tuples; i++)
2613 {
2614 /*
2615 * Print untranslated constraint name and definition. Use a
2616 * "TABLE tab" prefix when the constraint is defined in a
2617 * parent partitioned table.
2618 */
2619 if (strcmp(PQgetvalue(result, i, i_sametable), "f") == 0)
2620 printfPQExpBuffer(&buf, " TABLE \"%s\" CONSTRAINT \"%s\" %s",
2624 else
2625 printfPQExpBuffer(&buf, " \"%s\" %s",
2628
2630 }
2631 }
2632 PQclear(result);
2633
2634 /* print incoming foreign-key references */
2635 printfPQExpBuffer(&buf, "/* %s */\n",
2636 _("Get foreign keys referencing this table"));
2637 if (pset.sversion >= 120000)
2638 {
2640 "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n"
2641 " pg_catalog.pg_get_constraintdef(oid, true) AS condef\n"
2642 " FROM pg_catalog.pg_constraint c\n"
2643 " WHERE confrelid IN (SELECT pg_catalog.pg_partition_ancestors('%s')\n"
2644 " UNION ALL VALUES ('%s'::pg_catalog.regclass))\n"
2645 " AND contype = " CppAsString2(CONSTRAINT_FOREIGN) " AND conparentid = 0\n"
2646 "ORDER BY conname;",
2647 oid, oid);
2648 }
2649 else
2650 {
2652 "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n"
2653 " pg_catalog.pg_get_constraintdef(oid, true) AS condef\n"
2654 " FROM pg_catalog.pg_constraint\n"
2655 " WHERE confrelid = %s AND contype = " CppAsString2(CONSTRAINT_FOREIGN) "\n"
2656 "ORDER BY conname;",
2657 oid);
2658 }
2659
2660 result = PSQLexec(buf.data);
2661 if (!result)
2662 goto error_return;
2663 else
2664 tuples = PQntuples(result);
2665
2666 if (tuples > 0)
2667 {
2668 int i_conname = PQfnumber(result, "conname"),
2669 i_ontable = PQfnumber(result, "ontable"),
2670 i_condef = PQfnumber(result, "condef");
2671
2672 printTableAddFooter(&cont, _("Referenced by:"));
2673 for (i = 0; i < tuples; i++)
2674 {
2675 printfPQExpBuffer(&buf, " TABLE \"%s\" CONSTRAINT \"%s\" %s",
2679
2681 }
2682 }
2683 PQclear(result);
2684
2685 /* print any row-level policies */
2686 printfPQExpBuffer(&buf, "/* %s */\n",
2687 _("Get row-level policies for this table"));
2688 appendPQExpBufferStr(&buf, "SELECT pol.polname,");
2690 " pol.polpermissive,\n");
2692 " 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"
2693 " pg_catalog.pg_get_expr(pol.polqual, pol.polrelid),\n"
2694 " pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid),\n"
2695 " CASE pol.polcmd\n"
2696 " WHEN 'r' THEN 'SELECT'\n"
2697 " WHEN 'a' THEN 'INSERT'\n"
2698 " WHEN 'w' THEN 'UPDATE'\n"
2699 " WHEN 'd' THEN 'DELETE'\n"
2700 " END AS cmd\n"
2701 "FROM pg_catalog.pg_policy pol\n"
2702 "WHERE pol.polrelid = '%s' ORDER BY 1;",
2703 oid);
2704
2705 result = PSQLexec(buf.data);
2706 if (!result)
2707 goto error_return;
2708 else
2709 tuples = PQntuples(result);
2710
2711 /*
2712 * Handle cases where RLS is enabled and there are policies, or there
2713 * aren't policies, or RLS isn't enabled but there are policies
2714 */
2715 if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples > 0)
2716 printTableAddFooter(&cont, _("Policies:"));
2717
2718 if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples > 0)
2719 printTableAddFooter(&cont, _("Policies (forced row security enabled):"));
2720
2721 if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples == 0)
2722 printTableAddFooter(&cont, _("Policies (row security enabled): (none)"));
2723
2724 if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples == 0)
2725 printTableAddFooter(&cont, _("Policies (forced row security enabled): (none)"));
2726
2727 if (!tableinfo.rowsecurity && tuples > 0)
2728 printTableAddFooter(&cont, _("Policies (row security disabled):"));
2729
2730 /* Might be an empty set - that's ok */
2731 for (i = 0; i < tuples; i++)
2732 {
2733 printfPQExpBuffer(&buf, " POLICY \"%s\"",
2734 PQgetvalue(result, i, 0));
2735
2736 if (*(PQgetvalue(result, i, 1)) == 'f')
2737 appendPQExpBufferStr(&buf, " AS RESTRICTIVE");
2738
2739 if (!PQgetisnull(result, i, 5))
2740 appendPQExpBuffer(&buf, " FOR %s",
2741 PQgetvalue(result, i, 5));
2742
2743 if (!PQgetisnull(result, i, 2))
2744 {
2745 appendPQExpBuffer(&buf, "\n TO %s",
2746 PQgetvalue(result, i, 2));
2747 }
2748
2749 if (!PQgetisnull(result, i, 3))
2750 appendPQExpBuffer(&buf, "\n USING (%s)",
2751 PQgetvalue(result, i, 3));
2752
2753 if (!PQgetisnull(result, i, 4))
2754 appendPQExpBuffer(&buf, "\n WITH CHECK (%s)",
2755 PQgetvalue(result, i, 4));
2756
2758 }
2759 PQclear(result);
2760
2761 /* print any extended statistics */
2762 if (pset.sversion >= 140000)
2763 {
2764 printfPQExpBuffer(&buf, "/* %s */\n",
2765 _("Get extended statistics for this table"));
2767 "SELECT oid, "
2768 "stxrelid::pg_catalog.regclass, "
2769 "stxnamespace::pg_catalog.regnamespace::pg_catalog.text AS nsp, "
2770 "stxname,\n"
2771 "pg_catalog.pg_get_statisticsobjdef_columns(oid) AS columns,\n"
2772 " " CppAsString2(STATS_EXT_NDISTINCT) " = any(stxkind) AS ndist_enabled,\n"
2773 " " CppAsString2(STATS_EXT_DEPENDENCIES) " = any(stxkind) AS deps_enabled,\n"
2774 " " CppAsString2(STATS_EXT_MCV) " = any(stxkind) AS mcv_enabled,\n"
2775 "stxstattarget\n"
2776 "FROM pg_catalog.pg_statistic_ext\n"
2777 "WHERE stxrelid = '%s'\n"
2778 "ORDER BY nsp, stxname;",
2779 oid);
2780
2781 result = PSQLexec(buf.data);
2782 if (!result)
2783 goto error_return;
2784 else
2785 tuples = PQntuples(result);
2786
2787 if (tuples > 0)
2788 {
2789 printTableAddFooter(&cont, _("Statistics objects:"));
2790
2791 for (i = 0; i < tuples; i++)
2792 {
2793 bool gotone = false;
2794 bool has_ndistinct;
2795 bool has_dependencies;
2796 bool has_mcv;
2797 bool has_all;
2798 bool has_some;
2799
2800 has_ndistinct = (strcmp(PQgetvalue(result, i, 5), "t") == 0);
2801 has_dependencies = (strcmp(PQgetvalue(result, i, 6), "t") == 0);
2802 has_mcv = (strcmp(PQgetvalue(result, i, 7), "t") == 0);
2803
2804 printfPQExpBuffer(&buf, " ");
2805
2806 /* statistics object name (qualified with namespace) */
2807 appendPQExpBuffer(&buf, "\"%s.%s\"",
2808 PQgetvalue(result, i, 2),
2809 PQgetvalue(result, i, 3));
2810
2811 /*
2812 * When printing kinds we ignore expression statistics,
2813 * which are used only internally and can't be specified
2814 * by user. We don't print the kinds when none are
2815 * specified (in which case it has to be statistics on a
2816 * single expr) or when all are specified (in which case
2817 * we assume it's expanded by CREATE STATISTICS).
2818 */
2821
2822 if (has_some && !has_all)
2823 {
2824 appendPQExpBufferStr(&buf, " (");
2825
2826 /* options */
2827 if (has_ndistinct)
2828 {
2829 appendPQExpBufferStr(&buf, "ndistinct");
2830 gotone = true;
2831 }
2832
2833 if (has_dependencies)
2834 {
2835 appendPQExpBuffer(&buf, "%sdependencies", gotone ? ", " : "");
2836 gotone = true;
2837 }
2838
2839 if (has_mcv)
2840 {
2841 appendPQExpBuffer(&buf, "%smcv", gotone ? ", " : "");
2842 }
2843
2845 }
2846
2847 appendPQExpBuffer(&buf, " ON %s FROM %s",
2848 PQgetvalue(result, i, 4),
2849 PQgetvalue(result, i, 1));
2850
2851 /* Show the stats target if it's not default */
2852 if (!PQgetisnull(result, i, 8) &&
2853 strcmp(PQgetvalue(result, i, 8), "-1") != 0)
2854 appendPQExpBuffer(&buf, "; STATISTICS %s",
2855 PQgetvalue(result, i, 8));
2856
2858 }
2859 }
2860 PQclear(result);
2861 }
2862 else
2863 {
2864 printfPQExpBuffer(&buf, "/* %s */\n",
2865 _("Get extended statistics for this table"));
2867 "SELECT oid, "
2868 "stxrelid::pg_catalog.regclass, "
2869 "stxnamespace::pg_catalog.regnamespace AS nsp, "
2870 "stxname,\n"
2871 " (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(attname),', ')\n"
2872 " FROM pg_catalog.unnest(stxkeys) s(attnum)\n"
2873 " JOIN pg_catalog.pg_attribute a ON (stxrelid = a.attrelid AND\n"
2874 " a.attnum = s.attnum AND NOT attisdropped)) AS columns,\n"
2875 " " CppAsString2(STATS_EXT_NDISTINCT) " = any(stxkind) AS ndist_enabled,\n"
2876 " " CppAsString2(STATS_EXT_DEPENDENCIES) " = any(stxkind) AS deps_enabled,\n"
2877 " " CppAsString2(STATS_EXT_MCV) " = any(stxkind) AS mcv_enabled,\n");
2878
2879 if (pset.sversion >= 130000)
2880 appendPQExpBufferStr(&buf, " stxstattarget\n");
2881 else
2882 appendPQExpBufferStr(&buf, " -1 AS stxstattarget\n");
2883 appendPQExpBuffer(&buf, "FROM pg_catalog.pg_statistic_ext\n"
2884 "WHERE stxrelid = '%s'\n"
2885 "ORDER BY 1;",
2886 oid);
2887
2888 result = PSQLexec(buf.data);
2889 if (!result)
2890 goto error_return;
2891 else
2892 tuples = PQntuples(result);
2893
2894 if (tuples > 0)
2895 {
2896 printTableAddFooter(&cont, _("Statistics objects:"));
2897
2898 for (i = 0; i < tuples; i++)
2899 {
2900 bool gotone = false;
2901
2902 printfPQExpBuffer(&buf, " ");
2903
2904 /* statistics object name (qualified with namespace) */
2905 appendPQExpBuffer(&buf, "\"%s.%s\" (",
2906 PQgetvalue(result, i, 2),
2907 PQgetvalue(result, i, 3));
2908
2909 /* options */
2910 if (strcmp(PQgetvalue(result, i, 5), "t") == 0)
2911 {
2912 appendPQExpBufferStr(&buf, "ndistinct");
2913 gotone = true;
2914 }
2915
2916 if (strcmp(PQgetvalue(result, i, 6), "t") == 0)
2917 {
2918 appendPQExpBuffer(&buf, "%sdependencies", gotone ? ", " : "");
2919 gotone = true;
2920 }
2921
2922 if (strcmp(PQgetvalue(result, i, 7), "t") == 0)
2923 {
2924 appendPQExpBuffer(&buf, "%smcv", gotone ? ", " : "");
2925 }
2926
2927 appendPQExpBuffer(&buf, ") ON %s FROM %s",
2928 PQgetvalue(result, i, 4),
2929 PQgetvalue(result, i, 1));
2930
2931 /* Show the stats target if it's not default */
2932 if (strcmp(PQgetvalue(result, i, 8), "-1") != 0)
2933 appendPQExpBuffer(&buf, "; STATISTICS %s",
2934 PQgetvalue(result, i, 8));
2935
2937 }
2938 }
2939 PQclear(result);
2940 }
2941
2942 /* print rules */
2943 if (tableinfo.hasrules && tableinfo.relkind != RELKIND_MATVIEW)
2944 {
2945 printfPQExpBuffer(&buf, "/* %s */\n",
2946 _("Get rules for this relation"));
2948 "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
2949 "ev_enabled\n"
2950 "FROM pg_catalog.pg_rewrite r\n"
2951 "WHERE r.ev_class = '%s' ORDER BY 1;",
2952 oid);
2953 result = PSQLexec(buf.data);
2954 if (!result)
2955 goto error_return;
2956 else
2957 tuples = PQntuples(result);
2958
2959 if (tuples > 0)
2960 {
2961 bool have_heading;
2962 int category;
2963
2964 for (category = 0; category < 4; category++)
2965 {
2966 have_heading = false;
2967
2968 for (i = 0; i < tuples; i++)
2969 {
2970 const char *ruledef;
2971 bool list_rule = false;
2972
2973 switch (category)
2974 {
2975 case 0:
2976 if (*PQgetvalue(result, i, 2) == 'O')
2977 list_rule = true;
2978 break;
2979 case 1:
2980 if (*PQgetvalue(result, i, 2) == 'D')
2981 list_rule = true;
2982 break;
2983 case 2:
2984 if (*PQgetvalue(result, i, 2) == 'A')
2985 list_rule = true;
2986 break;
2987 case 3:
2988 if (*PQgetvalue(result, i, 2) == 'R')
2989 list_rule = true;
2990 break;
2991 }
2992 if (!list_rule)
2993 continue;
2994
2995 if (!have_heading)
2996 {
2997 switch (category)
2998 {
2999 case 0:
3000 printfPQExpBuffer(&buf, _("Rules:"));
3001 break;
3002 case 1:
3003 printfPQExpBuffer(&buf, _("Disabled rules:"));
3004 break;
3005 case 2:
3006 printfPQExpBuffer(&buf, _("Rules firing always:"));
3007 break;
3008 case 3:
3009 printfPQExpBuffer(&buf, _("Rules firing on replica only:"));
3010 break;
3011 }
3013 have_heading = true;
3014 }
3015
3016 /* Everything after "CREATE RULE" is echoed verbatim */
3017 ruledef = PQgetvalue(result, i, 1);
3018 ruledef += 12;
3019 printfPQExpBuffer(&buf, " %s", ruledef);
3021 }
3022 }
3023 }
3024 PQclear(result);
3025 }
3026
3027 /* print any publications */
3028 printfPQExpBuffer(&buf, "/* %s */\n",
3029 _("Get publications that publish this table"));
3030 if (pset.sversion >= 150000)
3031 {
3033 "SELECT pubname\n"
3034 " , NULL\n"
3035 " , NULL\n"
3036 "FROM pg_catalog.pg_publication p\n"
3037 " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
3038 " JOIN pg_catalog.pg_class pc ON pc.relnamespace = pn.pnnspid\n"
3039 "WHERE pc.oid ='%s' and pg_catalog.pg_relation_is_publishable('%s')\n"
3040 "UNION\n"
3041 "SELECT pubname\n"
3042 " , pg_catalog.pg_get_expr(pr.prqual, c.oid)\n"
3043 " , (CASE WHEN pr.prattrs IS NOT NULL THEN\n"
3044 " (SELECT pg_catalog.string_agg(attname, ', ')\n"
3045 " FROM pg_catalog.generate_series(0, pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n"
3046 " pg_catalog.pg_attribute\n"
3047 " WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n"
3048 " ELSE NULL END) "
3049 "FROM pg_catalog.pg_publication p\n"
3050 " JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
3051 " JOIN pg_catalog.pg_class c ON c.oid = pr.prrelid\n"
3052 "WHERE pr.prrelid = '%s'\n"
3053
3054 /*
3055 * Don't print the same publication multiple times when the
3056 * published table is also covered by a published schema.
3057 */
3058 " AND NOT EXISTS (\n"
3059 " SELECT 1\n"
3060 " FROM pg_catalog.pg_publication_namespace pn\n"
3061 " WHERE pn.pnpubid = p.oid\n"
3062 " AND pn.pnnspid = c.relnamespace)\n",
3063 oid, oid, oid);
3064
3065 if (pset.sversion >= 190000)
3066 {
3067 /*
3068 * Skip entries where this relation appears in the
3069 * publication's EXCEPT list.
3070 */
3072 " AND NOT pr.prexcept\n"
3073 "UNION\n"
3074 "SELECT pubname\n"
3075 " , NULL\n"
3076 " , NULL\n"
3077 "FROM pg_catalog.pg_publication p\n"
3078 "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
3079 " AND NOT EXISTS (\n"
3080 " SELECT 1\n"
3081 " FROM pg_catalog.pg_publication_rel pr\n"
3082 " WHERE pr.prpubid = p.oid AND\n"
3083 " (pr.prrelid = '%s' OR pr.prrelid = pg_catalog.pg_partition_root('%s')))\n"
3084 "ORDER BY 1;",
3085 oid, oid, oid);
3086 }
3087 else
3088 {
3090 "UNION\n"
3091 "SELECT pubname\n"
3092 " , NULL\n"
3093 " , NULL\n"
3094 "FROM pg_catalog.pg_publication p\n"
3095 "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
3096 "ORDER BY 1;",
3097 oid);
3098 }
3099 }
3100 else
3101 {
3103 "SELECT pubname\n"
3104 " , NULL\n"
3105 " , NULL\n"
3106 "FROM pg_catalog.pg_publication p\n"
3107 "JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
3108 "WHERE pr.prrelid = '%s'\n"
3109 "UNION ALL\n"
3110 "SELECT pubname\n"
3111 " , NULL\n"
3112 " , NULL\n"
3113 "FROM pg_catalog.pg_publication p\n"
3114 "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
3115 "ORDER BY 1;",
3116 oid, oid);
3117 }
3118
3119 result = PSQLexec(buf.data);
3120 if (!result)
3121 goto error_return;
3122 else
3123 tuples = PQntuples(result);
3124
3125 if (tuples > 0)
3126 printTableAddFooter(&cont, _("Included in publications:"));
3127
3128 /* Might be an empty set - that's ok */
3129 for (i = 0; i < tuples; i++)
3130 {
3131 printfPQExpBuffer(&buf, " \"%s\"",
3132 PQgetvalue(result, i, 0));
3133
3134 /* column list (if any) */
3135 if (!PQgetisnull(result, i, 2))
3136 appendPQExpBuffer(&buf, " (%s)",
3137 PQgetvalue(result, i, 2));
3138
3139 /* row filter (if any) */
3140 if (!PQgetisnull(result, i, 1))
3141 appendPQExpBuffer(&buf, " WHERE %s",
3142 PQgetvalue(result, i, 1));
3143
3145 }
3146 PQclear(result);
3147
3148 /* Print publications where the table is in the EXCEPT clause */
3149 if (pset.sversion >= 190000)
3150 {
3151 printfPQExpBuffer(&buf, "/* %s */\n",
3152 _("Get publications that exclude this table"));
3154 "SELECT pubname\n"
3155 "FROM pg_catalog.pg_publication p\n"
3156 "JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
3157 "WHERE (pr.prrelid = '%s' OR pr.prrelid = pg_catalog.pg_partition_root('%s'))\n"
3158 "AND pr.prexcept\n"
3159 "ORDER BY 1;", oid, oid);
3160
3161 result = PSQLexec(buf.data);
3162 if (!result)
3163 goto error_return;
3164 else
3165 tuples = PQntuples(result);
3166
3167 if (tuples > 0)
3168 printTableAddFooter(&cont, _("Excluded from publications:"));
3169
3170 /* Might be an empty set - that's ok */
3171 for (i = 0; i < tuples; i++)
3172 {
3173 printfPQExpBuffer(&buf, " \"%s\"", PQgetvalue(result, i, 0));
3174
3176 }
3177 PQclear(result);
3178 }
3179
3180 /*
3181 * If verbose, print NOT NULL constraints.
3182 */
3183 if (verbose)
3184 {
3185 printfPQExpBuffer(&buf, "/* %s */\n",
3186 _("Get not-null constraints for this table"));
3188 "SELECT c.conname, a.attname, c.connoinherit,\n"
3189 " c.conislocal, c.coninhcount <> 0,\n"
3190 " c.convalidated\n"
3191 "FROM pg_catalog.pg_constraint c JOIN\n"
3192 " pg_catalog.pg_attribute a ON\n"
3193 " (a.attrelid = c.conrelid AND a.attnum = c.conkey[1])\n"
3194 "WHERE c.contype = " CppAsString2(CONSTRAINT_NOTNULL) " AND\n"
3195 " c.conrelid = '%s'::pg_catalog.regclass\n"
3196 "ORDER BY a.attnum",
3197 oid);
3198
3199 result = PSQLexec(buf.data);
3200 if (!result)
3201 goto error_return;
3202 else
3203 tuples = PQntuples(result);
3204
3205 if (tuples > 0)
3206 printTableAddFooter(&cont, _("Not-null constraints:"));
3207
3208 /* Might be an empty set - that's ok */
3209 for (i = 0; i < tuples; i++)
3210 {
3211 bool islocal = PQgetvalue(result, i, 3)[0] == 't';
3212 bool inherited = PQgetvalue(result, i, 4)[0] == 't';
3213 bool validated = PQgetvalue(result, i, 5)[0] == 't';
3214
3215 printfPQExpBuffer(&buf, " \"%s\" NOT NULL \"%s\"%s%s",
3216 PQgetvalue(result, i, 0),
3217 PQgetvalue(result, i, 1),
3218 PQgetvalue(result, i, 2)[0] == 't' ?
3219 " NO INHERIT" :
3220 islocal && inherited ? _(" (local, inherited)") :
3221 inherited ? _(" (inherited)") : "",
3222 !validated ? " NOT VALID" : "");
3223
3225 }
3226 PQclear(result);
3227 }
3228 }
3229
3230 /* Get view_def if table is a view or materialized view */
3231 if ((tableinfo.relkind == RELKIND_VIEW ||
3232 tableinfo.relkind == RELKIND_MATVIEW) && verbose)
3233 {
3235
3236 printfPQExpBuffer(&buf, "/* %s */\n", _("Get view's definition"));
3238 "SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid, true);",
3239 oid);
3240 result = PSQLexec(buf.data);
3241 if (!result)
3242 goto error_return;
3243
3244 if (PQntuples(result) > 0)
3246
3247 PQclear(result);
3248 }
3249
3250 if (view_def)
3251 {
3252 PGresult *result = NULL;
3253
3254 /* Footer information about a view */
3255 printTableAddFooter(&cont, _("View definition:"));
3257
3258 /* print rules */
3259 if (tableinfo.hasrules)
3260 {
3261 printfPQExpBuffer(&buf, "/* %s */\n", _("Get rules for this view"));
3263 "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true))\n"
3264 "FROM pg_catalog.pg_rewrite r\n"
3265 "WHERE r.ev_class = '%s' AND r.rulename != '_RETURN' ORDER BY 1;",
3266 oid);
3267 result = PSQLexec(buf.data);
3268 if (!result)
3269 goto error_return;
3270
3271 if (PQntuples(result) > 0)
3272 {
3273 printTableAddFooter(&cont, _("Rules:"));
3274 for (i = 0; i < PQntuples(result); i++)
3275 {
3276 const char *ruledef;
3277
3278 /* Everything after "CREATE RULE" is echoed verbatim */
3279 ruledef = PQgetvalue(result, i, 1);
3280 ruledef += 12;
3281
3282 printfPQExpBuffer(&buf, " %s", ruledef);
3284 }
3285 }
3286 PQclear(result);
3287 }
3288 }
3289
3290 /*
3291 * Print triggers next, if any (but only user-defined triggers). This
3292 * could apply to either a table or a view.
3293 */
3294 if (tableinfo.hastriggers)
3295 {
3297 int tuples;
3298
3299 printfPQExpBuffer(&buf, "/* %s */\n",
3300 _("Get triggers for this relation"));
3302 "SELECT t.tgname, "
3303 "pg_catalog.pg_get_triggerdef(t.oid, true), "
3304 "t.tgenabled, t.tgisinternal,\n");
3305
3306 /*
3307 * Detect whether each trigger is inherited, and if so, get the name
3308 * of the topmost table it's inherited from. We have no easy way to
3309 * do that pre-v13, for lack of the tgparentid column. Even with
3310 * tgparentid, a straightforward search for the topmost parent would
3311 * require a recursive CTE, which seems unduly expensive. We cheat a
3312 * bit by assuming parent triggers will match by tgname; then, joining
3313 * with pg_partition_ancestors() allows the planner to make use of
3314 * pg_trigger_tgrelid_tgname_index if it wishes. We ensure we find
3315 * the correct topmost parent by stopping at the first-in-partition-
3316 * ancestry-order trigger that has tgparentid = 0. (There might be
3317 * unrelated, non-inherited triggers with the same name further up the
3318 * stack, so this is important.)
3319 */
3320 if (pset.sversion >= 130000)
3322 " CASE WHEN t.tgparentid != 0 THEN\n"
3323 " (SELECT u.tgrelid::pg_catalog.regclass\n"
3324 " FROM pg_catalog.pg_trigger AS u,\n"
3325 " pg_catalog.pg_partition_ancestors(t.tgrelid) WITH ORDINALITY AS a(relid, depth)\n"
3326 " WHERE u.tgname = t.tgname AND u.tgrelid = a.relid\n"
3327 " AND u.tgparentid = 0\n"
3328 " ORDER BY a.depth LIMIT 1)\n"
3329 " END AS parent\n");
3330 else
3331 appendPQExpBufferStr(&buf, " NULL AS parent\n");
3332
3334 "FROM pg_catalog.pg_trigger t\n"
3335 "WHERE t.tgrelid = '%s' AND ",
3336 oid);
3337
3338 /*
3339 * tgisinternal is set true for inherited triggers of partitions in
3340 * servers between v11 and v14, though these must still be shown to
3341 * the user. So we use another property that is true for such
3342 * inherited triggers to avoid them being hidden, which is their
3343 * dependence on another trigger.
3344 */
3345 if (pset.sversion >= 110000 && pset.sversion < 150000)
3346 appendPQExpBufferStr(&buf, "(NOT t.tgisinternal OR (t.tgisinternal AND t.tgenabled = 'D') \n"
3347 " OR EXISTS (SELECT 1 FROM pg_catalog.pg_depend WHERE objid = t.oid \n"
3348 " AND refclassid = 'pg_catalog.pg_trigger'::pg_catalog.regclass))");
3349 else
3350 /* display/warn about disabled internal triggers */
3351 appendPQExpBufferStr(&buf, "(NOT t.tgisinternal OR (t.tgisinternal AND t.tgenabled = 'D'))");
3352 appendPQExpBufferStr(&buf, "\nORDER BY 1;");
3353
3354 result = PSQLexec(buf.data);
3355 if (!result)
3356 goto error_return;
3357 else
3358 tuples = PQntuples(result);
3359
3360 if (tuples > 0)
3361 {
3362 bool have_heading;
3363 int category;
3364
3365 /*
3366 * split the output into 4 different categories. Enabled triggers,
3367 * disabled triggers and the two special ALWAYS and REPLICA
3368 * configurations.
3369 */
3370 for (category = 0; category <= 4; category++)
3371 {
3372 have_heading = false;
3373 for (i = 0; i < tuples; i++)
3374 {
3375 bool list_trigger;
3376 const char *tgdef;
3377 const char *usingpos;
3378 const char *tgenabled;
3379 const char *tgisinternal;
3380
3381 /*
3382 * Check if this trigger falls into the current category
3383 */
3384 tgenabled = PQgetvalue(result, i, 2);
3385 tgisinternal = PQgetvalue(result, i, 3);
3386 list_trigger = false;
3387 switch (category)
3388 {
3389 case 0:
3390 if (*tgenabled == 'O' || *tgenabled == 't')
3391 list_trigger = true;
3392 break;
3393 case 1:
3394 if ((*tgenabled == 'D' || *tgenabled == 'f') &&
3395 *tgisinternal == 'f')
3396 list_trigger = true;
3397 break;
3398 case 2:
3399 if ((*tgenabled == 'D' || *tgenabled == 'f') &&
3400 *tgisinternal == 't')
3401 list_trigger = true;
3402 break;
3403 case 3:
3404 if (*tgenabled == 'A')
3405 list_trigger = true;
3406 break;
3407 case 4:
3408 if (*tgenabled == 'R')
3409 list_trigger = true;
3410 break;
3411 }
3412 if (list_trigger == false)
3413 continue;
3414
3415 /* Print the category heading once */
3416 if (have_heading == false)
3417 {
3418 switch (category)
3419 {
3420 case 0:
3421 printfPQExpBuffer(&buf, _("Triggers:"));
3422 break;
3423 case 1:
3424 printfPQExpBuffer(&buf, _("Disabled user triggers:"));
3425 break;
3426 case 2:
3427 printfPQExpBuffer(&buf, _("Disabled internal triggers:"));
3428 break;
3429 case 3:
3430 printfPQExpBuffer(&buf, _("Triggers firing always:"));
3431 break;
3432 case 4:
3433 printfPQExpBuffer(&buf, _("Triggers firing on replica only:"));
3434 break;
3435 }
3437 have_heading = true;
3438 }
3439
3440 /* Everything after "TRIGGER" is echoed verbatim */
3441 tgdef = PQgetvalue(result, i, 1);
3442 usingpos = strstr(tgdef, " TRIGGER ");
3443 if (usingpos)
3444 tgdef = usingpos + 9;
3445
3446 printfPQExpBuffer(&buf, " %s", tgdef);
3447
3448 /* Visually distinguish inherited triggers */
3449 if (!PQgetisnull(result, i, 4))
3450 appendPQExpBuffer(&buf, ", ON TABLE %s",
3451 PQgetvalue(result, i, 4));
3452
3454 }
3455 }
3456 }
3457 PQclear(result);
3458 }
3459
3460 /*
3461 * Finish printing the footer information about a table.
3462 */
3463 if (tableinfo.relkind == RELKIND_RELATION ||
3464 tableinfo.relkind == RELKIND_MATVIEW ||
3465 tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
3468 tableinfo.relkind == RELKIND_TOASTVALUE)
3469 {
3470 bool is_partitioned;
3472 int tuples;
3473
3474 /* simplify some repeated tests below */
3477
3478 /* print foreign server name */
3479 if (tableinfo.relkind == RELKIND_FOREIGN_TABLE)
3480 {
3481 char *ftoptions;
3482
3483 /* Footer information about foreign table */
3484 printfPQExpBuffer(&buf, "/* %s */\n",
3485 _("Get foreign server for this table"));
3487 "SELECT s.srvname,\n"
3488 " pg_catalog.array_to_string(ARRAY(\n"
3489 " SELECT pg_catalog.quote_ident(option_name)"
3490 " || ' ' || pg_catalog.quote_literal(option_value)\n"
3491 " FROM pg_catalog.pg_options_to_table(ftoptions)), ', ')\n"
3492 "FROM pg_catalog.pg_foreign_table f,\n"
3493 " pg_catalog.pg_foreign_server s\n"
3494 "WHERE f.ftrelid = '%s' AND s.oid = f.ftserver;",
3495 oid);
3496 result = PSQLexec(buf.data);
3497 if (!result)
3498 goto error_return;
3499 else if (PQntuples(result) != 1)
3500 {
3501 PQclear(result);
3502 goto error_return;
3503 }
3504
3505 /* Print server name */
3506 printfPQExpBuffer(&buf, _("Server: %s"),
3507 PQgetvalue(result, 0, 0));
3509
3510 /* Print per-table FDW options, if any */
3511 ftoptions = PQgetvalue(result, 0, 1);
3512 if (ftoptions && ftoptions[0] != '\0')
3513 {
3514 printfPQExpBuffer(&buf, _("FDW options: (%s)"), ftoptions);
3516 }
3517 PQclear(result);
3518 }
3519
3520 /* print tables inherited from (exclude partitioned parents) */
3521 printfPQExpBuffer(&buf, "/* %s */\n",
3522 _("Get inheritance parent tables"));
3524 "SELECT c.oid::pg_catalog.regclass\n"
3525 "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
3526 "WHERE c.oid = i.inhparent AND i.inhrelid = '%s'\n"
3527 " AND c.relkind != " CppAsString2(RELKIND_PARTITIONED_TABLE)
3528 " AND c.relkind != " CppAsString2(RELKIND_PARTITIONED_INDEX)
3529 "\nORDER BY inhseqno;",
3530 oid);
3531
3532 result = PSQLexec(buf.data);
3533 if (!result)
3534 goto error_return;
3535 else
3536 {
3537 const char *s = _("Inherits");
3538
3539 tuples = PQntuples(result);
3540
3541 if (tuples > 0)
3542 {
3543 printfPQExpBuffer(&buf, "%s:", s);
3545 }
3546
3547 for (i = 0; i < tuples; i++)
3548 {
3549 printfPQExpBuffer(&buf, " %s", PQgetvalue(result, i, 0));
3551 }
3552
3553 PQclear(result);
3554 }
3555
3556 /* print child tables (with additional info if partitions) */
3557 printfPQExpBuffer(&buf, "/* %s */\n", _("Get child tables"));
3558 if (pset.sversion >= 140000)
3560 "SELECT c.oid::pg_catalog.regclass, c.relkind,"
3561 " inhdetachpending,"
3562 " pg_catalog.pg_get_expr(c.relpartbound, c.oid)\n"
3563 "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
3564 "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n"
3565 "ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT',"
3566 " c.oid::pg_catalog.regclass::pg_catalog.text;",
3567 oid);
3568 else
3570 "SELECT c.oid::pg_catalog.regclass, c.relkind,"
3571 " false AS inhdetachpending,"
3572 " pg_catalog.pg_get_expr(c.relpartbound, c.oid)\n"
3573 "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
3574 "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n"
3575 "ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT',"
3576 " c.oid::pg_catalog.regclass::pg_catalog.text;",
3577 oid);
3578
3579 result = PSQLexec(buf.data);
3580 if (!result)
3581 goto error_return;
3582 tuples = PQntuples(result);
3583
3584 /*
3585 * For a partitioned table with no partitions, always print the number
3586 * of partitions as zero, even when verbose output is expected.
3587 * Otherwise, we will not print "Partitions" section for a partitioned
3588 * table without any partitions.
3589 */
3590 if (is_partitioned && tuples == 0)
3591 {
3592 printfPQExpBuffer(&buf, _("Number of partitions: %d"), tuples);
3594 }
3595 else if (!verbose)
3596 {
3597 /* print the number of child tables, if any */
3598 if (tuples > 0)
3599 {
3600 if (is_partitioned)
3601 printfPQExpBuffer(&buf, _("Number of partitions: %d (Use \\d+ to list them.)"), tuples);
3602 else
3603 printfPQExpBuffer(&buf, _("Number of child tables: %d (Use \\d+ to list them.)"), tuples);
3605 }
3606 }
3607 else
3608 {
3609 /* display the list of child tables */
3610 const char *ct = is_partitioned ? _("Partitions") : _("Child tables");
3611
3612 if (tuples > 0)
3613 {
3614 printfPQExpBuffer(&buf, "%s:", ct);
3616 }
3617
3618 for (i = 0; i < tuples; i++)
3619 {
3620 char child_relkind = *PQgetvalue(result, i, 1);
3621
3622 printfPQExpBuffer(&buf, " %s", PQgetvalue(result, i, 0));
3623 if (!PQgetisnull(result, i, 3))
3624 appendPQExpBuffer(&buf, " %s", PQgetvalue(result, i, 3));
3627 appendPQExpBufferStr(&buf, ", PARTITIONED");
3629 appendPQExpBufferStr(&buf, ", FOREIGN");
3630 if (strcmp(PQgetvalue(result, i, 2), "t") == 0)
3631 appendPQExpBufferStr(&buf, " (DETACH PENDING)");
3632
3634 }
3635 }
3636 PQclear(result);
3637
3638 /* Table type */
3639 if (tableinfo.reloftype)
3640 {
3641 printfPQExpBuffer(&buf, _("Typed table of type: %s"), tableinfo.reloftype);
3643 }
3644
3645 if (verbose &&
3646 (tableinfo.relkind == RELKIND_RELATION ||
3647 tableinfo.relkind == RELKIND_MATVIEW) &&
3648
3649 /*
3650 * No need to display default values; we already display a REPLICA
3651 * IDENTITY marker on indexes.
3652 */
3653 tableinfo.relreplident != REPLICA_IDENTITY_INDEX &&
3654 ((strcmp(schemaname, "pg_catalog") != 0 &&
3655 tableinfo.relreplident != REPLICA_IDENTITY_DEFAULT) ||
3656 (strcmp(schemaname, "pg_catalog") == 0 &&
3657 tableinfo.relreplident != REPLICA_IDENTITY_NOTHING)))
3658 {
3659 const char *s = _("Replica Identity");
3660
3661 printfPQExpBuffer(&buf, "%s: %s",
3662 s,
3663 tableinfo.relreplident == REPLICA_IDENTITY_FULL ? "FULL" :
3664 tableinfo.relreplident == REPLICA_IDENTITY_DEFAULT ? "NOTHING" :
3665 "???");
3666
3668 }
3669
3670 /* OIDs, if verbose and not a materialized view */
3671 if (verbose && tableinfo.relkind != RELKIND_MATVIEW && tableinfo.hasoids)
3672 printTableAddFooter(&cont, _("Has OIDs: yes"));
3673
3674 /* Tablespace info */
3675 add_tablespace_footer(&cont, tableinfo.relkind, tableinfo.tablespace,
3676 true);
3677
3678 /* Access method info */
3679 if (verbose && tableinfo.relam != NULL && !pset.hide_tableam)
3680 {
3681 printfPQExpBuffer(&buf, _("Access method: %s"), tableinfo.relam);
3683 }
3684 }
3685
3686 /* reloptions, if verbose */
3687 if (verbose &&
3688 tableinfo.reloptions && tableinfo.reloptions[0] != '\0')
3689 {
3690 const char *t = _("Options");
3691
3692 printfPQExpBuffer(&buf, "%s: %s", t, tableinfo.reloptions);
3694 }
3695
3697
3698 retval = true;
3699
3701
3702 /* clean up */
3706 termPQExpBuffer(&title);
3708
3710
3711 PQclear(res);
3712
3713 return retval;
3714}
#define Assert(condition)
Definition c.h:1002
int16_t int16
Definition c.h:678
static void add_tablespace_footer(printTableContent *const cont, char relkind, Oid tablespace, const bool newline)
Definition describe.c:3722
int PQfnumber(const PGresult *res, const char *field_name)
Definition fe-exec.c:3620
char * pg_strdup(const char *in)
Definition fe_memutils.c:91
void pg_free(void *ptr)
void printTableInit(printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows)
Definition print.c:3209
void printTableCleanup(printTableContent *const content)
Definition print.c:3390
void printTableAddCell(printTableContent *const content, char *cell, const bool translate, const bool mustfree)
Definition print.c:3297
void printTable(const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
Definition print.c:3654
void printTableAddHeader(printTableContent *const content, char *header, const bool translate, const char align)
Definition print.c:3257
#define storage
#define false
NameData relname
Definition pg_class.h:40
unsigned int Oid
#define atooid(x)
void resetPQExpBuffer(PQExpBuffer str)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
bool hide_tableam
Definition settings.h:171
bool hide_compression
Definition settings.h:170
printTableOpt topt
Definition print.h:185
char * title
Definition print.h:189
char ** footers
Definition print.h:190
bool translate_header
Definition print.h:191
bool default_footer
Definition print.h:129
static StringInfoData tmpbuf
Definition walsender.c:195

References _, add_tablespace_footer(), appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), Assert, atooid, buf, CppAsString2, StringInfoData::data, PQExpBufferData::data, printTableOpt::default_footer, fb(), printQueryOpt::footers, gettext_noop, _psqlSettings::hide_compression, _psqlSettings::hide_tableam, i, initPQExpBuffer(), lengthof, _psqlSettings::logfile, pg_free(), pg_log_error, pg_strdup(), _psqlSettings::popt, PQclear, PQfnumber(), PQgetisnull, PQgetvalue, PQntuples, printfPQExpBuffer(), printQuery(), printTable(), printTableAddCell(), printTableAddFooter(), printTableAddHeader(), printTableCleanup(), printTableInit(), pset, psprintf(), PSQLexec(), _psqlSettings::queryFout, _psqlSettings::quiet, relname, resetPQExpBuffer(), result, 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 5914 of file describe.c.

5916{
5918 title;
5919 PGresult *res;
5921
5923
5924 printfPQExpBuffer(&buf, "/* %s */\n", _("Get text search configuration details"));
5926 "SELECT\n"
5927 " ( SELECT t.alias FROM\n"
5928 " pg_catalog.ts_token_type(c.cfgparser) AS t\n"
5929 " WHERE t.tokid = m.maptokentype ) AS \"%s\",\n"
5930 " pg_catalog.btrim(\n"
5931 " ARRAY( SELECT mm.mapdict::pg_catalog.regdictionary\n"
5932 " FROM pg_catalog.pg_ts_config_map AS mm\n"
5933 " WHERE mm.mapcfg = m.mapcfg AND mm.maptokentype = m.maptokentype\n"
5934 " ORDER BY mapcfg, maptokentype, mapseqno\n"
5935 " ) :: pg_catalog.text,\n"
5936 " '{}') AS \"%s\"\n"
5937 "FROM pg_catalog.pg_ts_config AS c, pg_catalog.pg_ts_config_map AS m\n"
5938 "WHERE c.oid = '%s' AND m.mapcfg = c.oid\n"
5939 "GROUP BY m.mapcfg, m.maptokentype, c.cfgparser\n"
5940 "ORDER BY 1;",
5941 gettext_noop("Token"),
5942 gettext_noop("Dictionaries"),
5943 oid);
5944
5945 res = PSQLexec(buf.data);
5947 if (!res)
5948 return false;
5949
5950 initPQExpBuffer(&title);
5951
5952 if (nspname)
5953 appendPQExpBuffer(&title, _("Text search configuration \"%s.%s\""),
5954 nspname, cfgname);
5955 else
5956 appendPQExpBuffer(&title, _("Text search configuration \"%s\""),
5957 cfgname);
5958
5959 if (pnspname)
5960 appendPQExpBuffer(&title, _("\nParser: \"%s.%s\""),
5961 pnspname, prsname);
5962 else
5963 appendPQExpBuffer(&title, _("\nParser: \"%s\""),
5964 prsname);
5965
5966 myopt.title = title.data;
5967 myopt.footers = NULL;
5968 myopt.topt.default_footer = false;
5969 myopt.translate_header = true;
5970
5971 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5972
5973 termPQExpBuffer(&title);
5974
5975 PQclear(res);
5976 return true;
5977}

References _, appendPQExpBuffer(), buf, PQExpBufferData::data, fb(), gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear, printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, and termPQExpBuffer().

Referenced by listTSConfigsVerbose().

◆ describeOneTSParser()

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

Definition at line 5524 of file describe.c.

5525{
5527 PGresult *res;
5528 PQExpBufferData title;
5530 static const bool translate_columns[] = {true, false, false};
5531
5533
5534 printfPQExpBuffer(&buf, "/* %s */\n", _("Get text search parser details"));
5536 "SELECT '%s' AS \"%s\",\n"
5537 " p.prsstart::pg_catalog.regproc AS \"%s\",\n"
5538 " pg_catalog.obj_description(p.prsstart, 'pg_proc') as \"%s\"\n"
5539 " FROM pg_catalog.pg_ts_parser p\n"
5540 " WHERE p.oid = '%s'\n"
5541 "UNION ALL\n"
5542 "SELECT '%s',\n"
5543 " p.prstoken::pg_catalog.regproc,\n"
5544 " pg_catalog.obj_description(p.prstoken, 'pg_proc')\n"
5545 " FROM pg_catalog.pg_ts_parser p\n"
5546 " WHERE p.oid = '%s'\n"
5547 "UNION ALL\n"
5548 "SELECT '%s',\n"
5549 " p.prsend::pg_catalog.regproc,\n"
5550 " pg_catalog.obj_description(p.prsend, 'pg_proc')\n"
5551 " FROM pg_catalog.pg_ts_parser p\n"
5552 " WHERE p.oid = '%s'\n"
5553 "UNION ALL\n"
5554 "SELECT '%s',\n"
5555 " p.prsheadline::pg_catalog.regproc,\n"
5556 " pg_catalog.obj_description(p.prsheadline, 'pg_proc')\n"
5557 " FROM pg_catalog.pg_ts_parser p\n"
5558 " WHERE p.oid = '%s'\n"
5559 "UNION ALL\n"
5560 "SELECT '%s',\n"
5561 " p.prslextype::pg_catalog.regproc,\n"
5562 " pg_catalog.obj_description(p.prslextype, 'pg_proc')\n"
5563 " FROM pg_catalog.pg_ts_parser p\n"
5564 " WHERE p.oid = '%s';",
5565 gettext_noop("Start parse"),
5566 gettext_noop("Method"),
5567 gettext_noop("Function"),
5568 gettext_noop("Description"),
5569 oid,
5570 gettext_noop("Get next token"),
5571 oid,
5572 gettext_noop("End parse"),
5573 oid,
5574 gettext_noop("Get headline"),
5575 oid,
5576 gettext_noop("Get token types"),
5577 oid);
5578
5579 res = PSQLexec(buf.data);
5581 if (!res)
5582 return false;
5583
5584 initPQExpBuffer(&title);
5585 if (nspname)
5586 printfPQExpBuffer(&title, _("Text search parser \"%s.%s\""),
5587 nspname, prsname);
5588 else
5589 printfPQExpBuffer(&title, _("Text search parser \"%s\""), prsname);
5590 myopt.title = title.data;
5591 myopt.footers = NULL;
5592 myopt.topt.default_footer = false;
5593 myopt.translate_header = true;
5594 myopt.translate_columns = translate_columns;
5595 myopt.n_translate_columns = lengthof(translate_columns);
5596
5597 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5598
5599 PQclear(res);
5600
5602
5603 printfPQExpBuffer(&buf, "/* %s */\n",
5604 _("Get text search parser token types"));
5606 "SELECT t.alias as \"%s\",\n"
5607 " t.description as \"%s\"\n"
5608 "FROM pg_catalog.ts_token_type( '%s'::pg_catalog.oid ) as t\n"
5609 "ORDER BY 1;",
5610 gettext_noop("Token name"),
5611 gettext_noop("Description"),
5612 oid);
5613
5614 res = PSQLexec(buf.data);
5616 if (!res)
5617 {
5618 termPQExpBuffer(&title);
5619 return false;
5620 }
5621
5622 if (nspname)
5623 printfPQExpBuffer(&title, _("Token types for parser \"%s.%s\""),
5624 nspname, prsname);
5625 else
5626 printfPQExpBuffer(&title, _("Token types for parser \"%s\""), prsname);
5627 myopt.title = title.data;
5628 myopt.footers = NULL;
5629 myopt.topt.default_footer = true;
5630 myopt.translate_header = true;
5631 myopt.translate_columns = NULL;
5632 myopt.n_translate_columns = 0;
5633
5634 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5635
5636 termPQExpBuffer(&title);
5637 PQclear(res);
5638 return true;
5639}

References _, appendPQExpBuffer(), buf, PQExpBufferData::data, fb(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, _psqlSettings::popt, PQclear, printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, and termPQExpBuffer().

Referenced by listTSParsersVerbose().

◆ describeOperators()

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

Definition at line 778 of file describe.c.

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

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

Referenced by exec_command_dfo().

◆ describePublications()

bool describePublications ( const char pattern)

Definition at line 6621 of file describe.c.

6622{
6624 int i;
6625 PGresult *res;
6626 bool has_pubtruncate;
6627 bool has_pubgencols;
6628 bool has_pubviaroot;
6629 bool has_pubsequence;
6630 int ncols = 6;
6631 int nrows = 1;
6632
6633 PQExpBufferData title;
6635
6636 has_pubsequence = (pset.sversion >= 190000);
6637 has_pubtruncate = (pset.sversion >= 110000);
6638 has_pubgencols = (pset.sversion >= 180000);
6639 has_pubviaroot = (pset.sversion >= 130000);
6640
6642
6643 printfPQExpBuffer(&buf, "/* %s */\n", _("Get details about matching publications"));
6645 "SELECT oid, pubname,\n"
6646 " pg_catalog.pg_get_userbyid(pubowner) AS owner,\n"
6647 " puballtables");
6648
6649 if (has_pubsequence)
6651 ", puballsequences");
6652 else
6654 ", false AS puballsequences");
6655
6657 ", pubinsert, pubupdate, pubdelete");
6658
6659 if (has_pubtruncate)
6661 ", pubtruncate");
6662 else
6664 ", false AS pubtruncate");
6665
6666 if (has_pubgencols)
6668 ", (CASE pubgencols\n"
6669 " WHEN '%c' THEN 'none'\n"
6670 " WHEN '%c' THEN 'stored'\n"
6671 " END) AS \"%s\"\n",
6674 gettext_noop("Generated columns"));
6675 else
6677 ", 'none' AS pubgencols");
6678
6679 if (has_pubviaroot)
6681 ", pubviaroot");
6682 else
6684 ", false AS pubviaroot");
6685
6687 ", pg_catalog.obj_description(oid, 'pg_publication')");
6688
6690 "\nFROM pg_catalog.pg_publication\n");
6691
6692 if (!validateSQLNamePattern(&buf, pattern, false, false,
6693 NULL, "pubname", NULL,
6694 NULL,
6695 NULL, 1))
6696 {
6698 return false;
6699 }
6700
6701 appendPQExpBufferStr(&buf, "ORDER BY 2;");
6702
6703 res = PSQLexec(buf.data);
6704 if (!res)
6705 {
6707 return false;
6708 }
6709
6710 if (PQntuples(res) == 0)
6711 {
6712 if (!pset.quiet)
6713 {
6714 if (pattern)
6715 pg_log_error("Did not find any publication named \"%s\".",
6716 pattern);
6717 else
6718 pg_log_error("Did not find any publications.");
6719 }
6720
6722 PQclear(res);
6723 return false;
6724 }
6725
6726 if (has_pubsequence)
6727 ncols++;
6728 if (has_pubtruncate)
6729 ncols++;
6730 if (has_pubgencols)
6731 ncols++;
6732 if (has_pubviaroot)
6733 ncols++;
6734
6735 for (i = 0; i < PQntuples(res); i++)
6736 {
6737 const char align = 'l';
6738 char *pubid = PQgetvalue(res, i, 0);
6739 char *pubname = PQgetvalue(res, i, 1);
6740 bool puballtables = strcmp(PQgetvalue(res, i, 3), "t") == 0;
6742
6743 initPQExpBuffer(&title);
6744 printfPQExpBuffer(&title, _("Publication %s"), pubname);
6745 printTableInit(&cont, &myopt, title.data, ncols, nrows);
6746
6747 printTableAddHeader(&cont, gettext_noop("Owner"), true, align);
6748 printTableAddHeader(&cont, gettext_noop("All tables"), true, align);
6749 if (has_pubsequence)
6750 printTableAddHeader(&cont, gettext_noop("All sequences"), true, align);
6751 printTableAddHeader(&cont, gettext_noop("Inserts"), true, align);
6752 printTableAddHeader(&cont, gettext_noop("Updates"), true, align);
6753 printTableAddHeader(&cont, gettext_noop("Deletes"), true, align);
6754 if (has_pubtruncate)
6755 printTableAddHeader(&cont, gettext_noop("Truncates"), true, align);
6756 if (has_pubgencols)
6757 printTableAddHeader(&cont, gettext_noop("Generated columns"), true, align);
6758 if (has_pubviaroot)
6759 printTableAddHeader(&cont, gettext_noop("Via root"), true, align);
6760 printTableAddHeader(&cont, gettext_noop("Description"), true, align);
6761
6762 printTableAddCell(&cont, PQgetvalue(res, i, 2), false, false);
6763 printTableAddCell(&cont, PQgetvalue(res, i, 3), false, false);
6764 if (has_pubsequence)
6765 printTableAddCell(&cont, PQgetvalue(res, i, 4), false, false);
6766 printTableAddCell(&cont, PQgetvalue(res, i, 5), false, false);
6767 printTableAddCell(&cont, PQgetvalue(res, i, 6), false, false);
6768 printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false);
6769 if (has_pubtruncate)
6770 printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
6771 if (has_pubgencols)
6772 printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
6773 if (has_pubviaroot)
6774 printTableAddCell(&cont, PQgetvalue(res, i, 10), false, false);
6775 printTableAddCell(&cont, PQgetvalue(res, i, 11), false, false);
6776
6777 if (!puballtables)
6778 {
6779 /* Get the tables for the specified publication */
6780 printfPQExpBuffer(&buf, "/* %s */\n",
6781 _("Get tables published by this publication"));
6782 appendPQExpBufferStr(&buf, "SELECT n.nspname, c.relname");
6783 if (pset.sversion >= 150000)
6784 {
6786 ", pg_catalog.pg_get_expr(pr.prqual, c.oid)");
6788 ", (CASE WHEN pr.prattrs IS NOT NULL THEN\n"
6789 " pg_catalog.array_to_string("
6790 " ARRAY(SELECT attname\n"
6791 " FROM\n"
6792 " pg_catalog.generate_series(0, pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n"
6793 " pg_catalog.pg_attribute\n"
6794 " WHERE attrelid = c.oid AND attnum = prattrs[s]), ', ')\n"
6795 " ELSE NULL END)");
6796 }
6797 else
6799 ", NULL, NULL");
6801 "\nFROM pg_catalog.pg_class c,\n"
6802 " pg_catalog.pg_namespace n,\n"
6803 " pg_catalog.pg_publication_rel pr\n"
6804 "WHERE c.relnamespace = n.oid\n"
6805 " AND c.oid = pr.prrelid\n"
6806 " AND pr.prpubid = '%s'\n", pubid);
6807 if (pset.sversion >= 150000)
6808 {
6809 /*
6810 * Don't list tables that are also covered by a published
6811 * schema.
6812 */
6814 " AND NOT EXISTS (\n"
6815 " SELECT 1\n"
6816 " FROM pg_catalog.pg_publication_namespace pn\n"
6817 " WHERE pn.pnpubid = pr.prpubid\n"
6818 " AND pn.pnnspid = c.relnamespace)\n");
6819 }
6820
6821 if (pset.sversion >= 190000)
6822 appendPQExpBufferStr(&buf, " AND NOT pr.prexcept\n");
6823
6824 appendPQExpBufferStr(&buf, "ORDER BY 1,2");
6825 if (!addFooterToPublicationDesc(&buf, _("Tables:"), false, &cont))
6826 goto error_return;
6827
6828 if (pset.sversion >= 150000)
6829 {
6830 /* Get the schemas for the specified publication */
6831 printfPQExpBuffer(&buf, "/* %s */\n",
6832 _("Get schemas published by this publication"));
6834 "SELECT n.nspname\n"
6835 "FROM pg_catalog.pg_namespace n\n"
6836 " JOIN pg_catalog.pg_publication_namespace pn ON n.oid = pn.pnnspid\n"
6837 "WHERE pn.pnpubid = '%s'\n"
6838 "ORDER BY 1", pubid);
6839 if (!addFooterToPublicationDesc(&buf, _("Tables from schemas:"),
6840 true, &cont))
6841 goto error_return;
6842 }
6843 }
6844 else
6845 {
6846 if (pset.sversion >= 190000)
6847 {
6848 /* Get tables in the EXCEPT clause for this publication */
6849 printfPQExpBuffer(&buf, "/* %s */\n",
6850 _("Get tables excluded by this publication"));
6852 "SELECT n.nspname || '.' || c.relname\n"
6853 "FROM pg_catalog.pg_class c\n"
6854 " JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
6855 " JOIN pg_catalog.pg_publication_rel pr ON c.oid = pr.prrelid\n"
6856 "WHERE pr.prpubid = '%s' AND pr.prexcept\n"
6857 "ORDER BY 1", pubid);
6858 if (!addFooterToPublicationDesc(&buf, _("Except tables:"),
6859 true, &cont))
6860 goto error_return;
6861 }
6862 }
6863
6866
6867 termPQExpBuffer(&title);
6868 }
6869
6871 PQclear(res);
6872
6873 return true;
6874
6877 PQclear(res);
6879 termPQExpBuffer(&title);
6880 return false;
6881}
static bool addFooterToPublicationDesc(PQExpBuffer buf, const char *footermsg, bool as_schema, printTableContent *const cont)
Definition describe.c:6575

References _, addFooterToPublicationDesc(), appendPQExpBuffer(), appendPQExpBufferStr(), buf, PQExpBufferData::data, fb(), 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 4002 of file describe.c.

4003{
4005 PGresult *res;
4007
4009 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching role grants"));
4011 "SELECT m.rolname AS \"%s\", r.rolname AS \"%s\",\n"
4012 " pg_catalog.concat_ws(', ',\n",
4013 gettext_noop("Role name"),
4014 gettext_noop("Member of"));
4015
4016 if (pset.sversion >= 160000)
4018 " CASE WHEN pam.admin_option THEN 'ADMIN' END,\n"
4019 " CASE WHEN pam.inherit_option THEN 'INHERIT' END,\n"
4020 " CASE WHEN pam.set_option THEN 'SET' END\n");
4021 else
4023 " CASE WHEN pam.admin_option THEN 'ADMIN' END,\n"
4024 " CASE WHEN m.rolinherit THEN 'INHERIT' END,\n"
4025 " 'SET'\n");
4026
4028 " ) AS \"%s\",\n"
4029 " g.rolname AS \"%s\"\n",
4030 gettext_noop("Options"),
4031 gettext_noop("Grantor"));
4032
4034 "FROM pg_catalog.pg_roles m\n"
4035 " JOIN pg_catalog.pg_auth_members pam ON (pam.member = m.oid)\n"
4036 " LEFT JOIN pg_catalog.pg_roles r ON (pam.roleid = r.oid)\n"
4037 " LEFT JOIN pg_catalog.pg_roles g ON (pam.grantor = g.oid)\n");
4038
4039 if (!showSystem && !pattern)
4040 appendPQExpBufferStr(&buf, "WHERE m.rolname !~ '^pg_'\n");
4041
4042 if (!validateSQLNamePattern(&buf, pattern, false, false,
4043 NULL, "m.rolname", NULL, NULL,
4044 NULL, 1))
4045 {
4047 return false;
4048 }
4049
4050 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;\n");
4051
4052 res = PSQLexec(buf.data);
4054 if (!res)
4055 return false;
4056
4057 myopt.title = _("List of role grants");
4058 myopt.translate_header = true;
4059
4060 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4061
4062 PQclear(res);
4063 return true;
4064}

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

Referenced by exec_command_d().

◆ describeRoles()

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

Definition at line 3789 of file describe.c.

3790{
3792 PGresult *res;
3795 int ncols = 2;
3796 int nrows = 0;
3797 int i;
3798 int conns;
3799 const char align = 'l';
3800 char **attr;
3801
3802 myopt.default_footer = false;
3803
3805
3806 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching roles"));
3808 "SELECT r.rolname, r.rolsuper, r.rolinherit,\n"
3809 " r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,\n"
3810 " r.rolconnlimit, r.rolvaliduntil");
3811
3812 if (verbose)
3813 {
3814 appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
3815 ncols++;
3816 }
3817 appendPQExpBufferStr(&buf, "\n, r.rolreplication");
3818 appendPQExpBufferStr(&buf, "\n, r.rolbypassrls");
3819
3820 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_roles r\n");
3821
3822 if (!showSystem && !pattern)
3823 appendPQExpBufferStr(&buf, "WHERE r.rolname !~ '^pg_'\n");
3824
3825 if (!validateSQLNamePattern(&buf, pattern, false, false,
3826 NULL, "r.rolname", NULL, NULL,
3827 NULL, 1))
3828 {
3830 return false;
3831 }
3832
3833 appendPQExpBufferStr(&buf, "ORDER BY 1;");
3834
3835 res = PSQLexec(buf.data);
3836 if (!res)
3837 return false;
3838
3839 nrows = PQntuples(res);
3840 attr = pg_malloc0_array(char *, nrows + 1);
3841
3842 printTableInit(&cont, &myopt, _("List of roles"), ncols, nrows);
3843
3844 printTableAddHeader(&cont, gettext_noop("Role name"), true, align);
3845 printTableAddHeader(&cont, gettext_noop("Attributes"), true, align);
3846
3847 if (verbose)
3848 printTableAddHeader(&cont, gettext_noop("Description"), true, align);
3849
3850 for (i = 0; i < nrows; i++)
3851 {
3852 printTableAddCell(&cont, PQgetvalue(res, i, 0), false, false);
3853
3855 if (strcmp(PQgetvalue(res, i, 1), "t") == 0)
3856 add_role_attribute(&buf, _("Superuser"));
3857
3858 if (strcmp(PQgetvalue(res, i, 2), "t") != 0)
3859 add_role_attribute(&buf, _("No inheritance"));
3860
3861 if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
3862 add_role_attribute(&buf, _("Create role"));
3863
3864 if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
3865 add_role_attribute(&buf, _("Create DB"));
3866
3867 if (strcmp(PQgetvalue(res, i, 5), "t") != 0)
3868 add_role_attribute(&buf, _("Cannot login"));
3869
3870 if (strcmp(PQgetvalue(res, i, (verbose ? 9 : 8)), "t") == 0)
3871 add_role_attribute(&buf, _("Replication"));
3872
3873 if (strcmp(PQgetvalue(res, i, (verbose ? 10 : 9)), "t") == 0)
3874 add_role_attribute(&buf, _("Bypass RLS"));
3875
3876 conns = atoi(PQgetvalue(res, i, 6));
3877 if (conns >= 0)
3878 {
3879 if (buf.len > 0)
3880 appendPQExpBufferChar(&buf, '\n');
3881
3882 if (conns == 0)
3883 appendPQExpBufferStr(&buf, _("No connections"));
3884 else
3885 appendPQExpBuffer(&buf, ngettext("%d connection",
3886 "%d connections",
3887 conns),
3888 conns);
3889 }
3890
3891 if (strcmp(PQgetvalue(res, i, 7), "") != 0)
3892 {
3893 if (buf.len > 0)
3894 appendPQExpBufferChar(&buf, '\n');
3895 appendPQExpBufferStr(&buf, _("Password valid until "));
3897 }
3898
3899 attr[i] = pg_strdup(buf.data);
3900
3901 printTableAddCell(&cont, attr[i], false, false);
3902
3903 if (verbose)
3904 printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
3905 }
3907
3910
3911 for (i = 0; i < nrows; i++)
3912 pg_free(attr[i]);
3913 pg_free(attr);
3914
3915 PQclear(res);
3916 return true;
3917}
#define ngettext(s, p, n)
Definition c.h:1310
static void add_role_attribute(PQExpBuffer buf, const char *const str)
Definition describe.c:3920
#define pg_malloc0_array(type, count)
Definition fe_memutils.h:67
static IsoConnInfo * conns

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

Referenced by exec_command_d().

◆ describeSubscriptions()

bool describeSubscriptions ( const char pattern,
bool  verbose 
)

Definition at line 6890 of file describe.c.

6891{
6893 PGresult *res;
6895 static const bool translate_columns[] = {false, false, false, false,
6896 false, false, false, false, false, false, false, false, false, false,
6897 false, false, false, false, false, false, false};
6898
6900
6901 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching subscriptions"));
6903 "SELECT subname AS \"%s\"\n"
6904 ", pg_catalog.pg_get_userbyid(subowner) AS \"%s\"\n"
6905 ", subenabled AS \"%s\"\n"
6906 ", subpublications AS \"%s\"\n",
6907 gettext_noop("Name"),
6908 gettext_noop("Owner"),
6909 gettext_noop("Enabled"),
6910 gettext_noop("Publication"));
6911
6912 if (verbose)
6913 {
6914 /* Binary mode and streaming are only supported in v14 and higher */
6915 if (pset.sversion >= 140000)
6916 {
6918 ", subbinary AS \"%s\"\n",
6919 gettext_noop("Binary"));
6920
6921 if (pset.sversion >= 160000)
6923 ", (CASE substream\n"
6924 " WHEN " CppAsString2(LOGICALREP_STREAM_OFF) " THEN 'off'\n"
6925 " WHEN " CppAsString2(LOGICALREP_STREAM_ON) " THEN 'on'\n"
6926 " WHEN " CppAsString2(LOGICALREP_STREAM_PARALLEL) " THEN 'parallel'\n"
6927 " END) AS \"%s\"\n",
6928 gettext_noop("Streaming"));
6929 else
6931 ", substream AS \"%s\"\n",
6932 gettext_noop("Streaming"));
6933 }
6934
6935 /* Two_phase and disable_on_error are only supported in v15 and higher */
6936 if (pset.sversion >= 150000)
6938 ", subtwophasestate AS \"%s\"\n"
6939 ", subdisableonerr AS \"%s\"\n",
6940 gettext_noop("Two-phase commit"),
6941 gettext_noop("Disable on error"));
6942
6943 if (pset.sversion >= 160000)
6945 ", suborigin AS \"%s\"\n"
6946 ", subpasswordrequired AS \"%s\"\n"
6947 ", subrunasowner AS \"%s\"\n",
6948 gettext_noop("Origin"),
6949 gettext_noop("Password required"),
6950 gettext_noop("Run as owner?"));
6951
6952 if (pset.sversion >= 170000)
6954 ", subfailover AS \"%s\"\n",
6955 gettext_noop("Failover"));
6956 if (pset.sversion >= 190000)
6957 {
6959 ", (select srvname from pg_catalog.pg_foreign_server where oid=subserver) AS \"%s\"\n",
6960 gettext_noop("Server"));
6961
6963 ", subretaindeadtuples AS \"%s\"\n",
6964 gettext_noop("Retain dead tuples"));
6965
6967 ", submaxretention AS \"%s\"\n",
6968 gettext_noop("Max retention duration"));
6969
6971 ", subretentionactive AS \"%s\"\n",
6972 gettext_noop("Retention active"));
6973 }
6974
6976 ", subsynccommit AS \"%s\"\n"
6977 ", subconninfo AS \"%s\"\n",
6978 gettext_noop("Synchronous commit"),
6979 gettext_noop("Conninfo"));
6980
6981 if (pset.sversion >= 190000)
6983 ", subwalrcvtimeout AS \"%s\"\n",
6984 gettext_noop("Receiver timeout"));
6985
6986 /* Skip LSN is only supported in v15 and higher */
6987 if (pset.sversion >= 150000)
6989 ", subskiplsn AS \"%s\"\n",
6990 gettext_noop("Skip LSN"));
6991
6993 ", pg_catalog.obj_description(oid, 'pg_subscription') AS \"%s\"\n",
6994 gettext_noop("Description"));
6995 }
6996
6997 /* Only display subscriptions in current database. */
6999 "FROM pg_catalog.pg_subscription\n"
7000 "WHERE subdbid = (SELECT oid\n"
7001 " FROM pg_catalog.pg_database\n"
7002 " WHERE datname = pg_catalog.current_database())");
7003
7004 if (!validateSQLNamePattern(&buf, pattern, true, false,
7005 NULL, "subname", NULL,
7006 NULL,
7007 NULL, 1))
7008 {
7010 return false;
7011 }
7012
7013 appendPQExpBufferStr(&buf, "ORDER BY 1;");
7014
7015 res = PSQLexec(buf.data);
7017 if (!res)
7018 return false;
7019
7020 myopt.title = _("List of subscriptions");
7021 myopt.translate_header = true;
7022 myopt.translate_columns = translate_columns;
7023 myopt.n_translate_columns = lengthof(translate_columns);
7024
7025 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7026
7027 PQclear(res);
7028 return true;
7029}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, fb(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, _psqlSettings::popt, PQclear, printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ describeTableDetails()

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

Definition at line 1450 of file describe.c.

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

References _, appendPQExpBufferStr(), buf, cancel_pressed, describeOneTableDetails(), fb(), 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 215 of file describe.c.

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

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

Referenced by exec_command_d().

◆ describeTypes()

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

Definition at line 622 of file describe.c.

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

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

Referenced by exec_command_d().

◆ listAllDbs()

bool listAllDbs ( const char pattern,
bool  verbose 
)

Definition at line 931 of file describe.c.

932{
933 PGresult *res;
936
938
939 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching databases"));
941 "SELECT\n"
942 " d.datname as \"%s\",\n"
943 " pg_catalog.pg_get_userbyid(d.datdba) as \"%s\",\n"
944 " pg_catalog.pg_encoding_to_char(d.encoding) as \"%s\",\n",
945 gettext_noop("Name"),
946 gettext_noop("Owner"),
947 gettext_noop("Encoding"));
948 if (pset.sversion >= 150000)
950 " CASE d.datlocprovider "
951 "WHEN " CppAsString2(COLLPROVIDER_BUILTIN) " THEN 'builtin' "
952 "WHEN " CppAsString2(COLLPROVIDER_LIBC) " THEN 'libc' "
953 "WHEN " CppAsString2(COLLPROVIDER_ICU) " THEN 'icu' "
954 "END AS \"%s\",\n",
955 gettext_noop("Locale Provider"));
956 else
958 " 'libc' AS \"%s\",\n",
959 gettext_noop("Locale Provider"));
961 " d.datcollate as \"%s\",\n"
962 " d.datctype as \"%s\",\n",
963 gettext_noop("Collate"),
964 gettext_noop("Ctype"));
965 if (pset.sversion >= 170000)
967 " d.datlocale as \"%s\",\n",
968 gettext_noop("Locale"));
969 else if (pset.sversion >= 150000)
971 " d.daticulocale as \"%s\",\n",
972 gettext_noop("Locale"));
973 else
975 " NULL as \"%s\",\n",
976 gettext_noop("Locale"));
977 if (pset.sversion >= 160000)
979 " d.daticurules as \"%s\",\n",
980 gettext_noop("ICU Rules"));
981 else
983 " NULL as \"%s\",\n",
984 gettext_noop("ICU Rules"));
986 printACLColumn(&buf, "d.datacl");
987 if (verbose)
989 ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT') OR\n"
990 " pg_catalog.pg_has_role('pg_read_all_stats', 'USAGE')\n"
991 " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n"
992 " ELSE 'No Access'\n"
993 " END as \"%s\""
994 ",\n t.spcname as \"%s\""
995 ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"",
996 gettext_noop("Size"),
997 gettext_noop("Tablespace"),
998 gettext_noop("Description"));
1000 "\nFROM pg_catalog.pg_database d\n");
1001 if (verbose)
1003 " JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
1004
1005 if (pattern)
1006 {
1007 if (!validateSQLNamePattern(&buf, pattern, false, false,
1008 NULL, "d.datname", NULL, NULL,
1009 NULL, 1))
1010 {
1012 return false;
1013 }
1014 }
1015
1016 appendPQExpBufferStr(&buf, "ORDER BY 1;");
1017 res = PSQLexec(buf.data);
1019 if (!res)
1020 return false;
1021
1022 myopt.title = _("List of databases");
1023 myopt.translate_header = true;
1024
1025 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1026
1027 PQclear(res);
1028 return true;
1029}

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

Referenced by exec_command_list(), and main().

◆ listCasts()

bool listCasts ( const char pattern,
bool  verbose 
)

Definition at line 5026 of file describe.c.

5027{
5029 PGresult *res;
5031 static const bool translate_columns[] = {false, false, false, true, true, false};
5032
5034
5035 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching casts"));
5037 "SELECT pg_catalog.format_type(castsource, NULL) AS \"%s\",\n"
5038 " pg_catalog.format_type(casttarget, NULL) AS \"%s\",\n",
5039 gettext_noop("Source type"),
5040 gettext_noop("Target type"));
5041
5042 /*
5043 * We don't attempt to localize '(binary coercible)' or '(with inout)',
5044 * because there's too much risk of gettext translating a function name
5045 * that happens to match some string in the PO database.
5046 */
5048 " CASE WHEN c.castmethod = '%c' THEN '(binary coercible)'\n"
5049 " WHEN c.castmethod = '%c' THEN '(with inout)'\n"
5050 " ELSE p.proname\n"
5051 " END AS \"%s\",\n",
5054 gettext_noop("Function"));
5055
5057 " CASE WHEN c.castcontext = '%c' THEN '%s'\n"
5058 " WHEN c.castcontext = '%c' THEN '%s'\n"
5059 " ELSE '%s'\n"
5060 " END AS \"%s\"",
5062 gettext_noop("no"),
5064 gettext_noop("in assignment"),
5065 gettext_noop("yes"),
5066 gettext_noop("Implicit?"));
5067
5068 if (verbose)
5070 ",\n CASE WHEN p.proleakproof THEN '%s'\n"
5071 " ELSE '%s'\n"
5072 " END AS \"%s\",\n"
5073 " d.description AS \"%s\"",
5074 gettext_noop("yes"),
5075 gettext_noop("no"),
5076 gettext_noop("Leakproof?"),
5077 gettext_noop("Description"));
5078
5079 /*
5080 * We need a left join to pg_proc for binary casts; the others are just
5081 * paranoia.
5082 */
5084 "\nFROM pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p\n"
5085 " ON c.castfunc = p.oid\n"
5086 " LEFT JOIN pg_catalog.pg_type ts\n"
5087 " ON c.castsource = ts.oid\n"
5088 " LEFT JOIN pg_catalog.pg_namespace ns\n"
5089 " ON ns.oid = ts.typnamespace\n"
5090 " LEFT JOIN pg_catalog.pg_type tt\n"
5091 " ON c.casttarget = tt.oid\n"
5092 " LEFT JOIN pg_catalog.pg_namespace nt\n"
5093 " ON nt.oid = tt.typnamespace\n");
5094
5095 if (verbose)
5097 " LEFT JOIN pg_catalog.pg_description d\n"
5098 " ON d.classoid = c.tableoid AND d.objoid = "
5099 "c.oid AND d.objsubid = 0\n");
5100
5101 appendPQExpBufferStr(&buf, "WHERE ( (true");
5102
5103 /*
5104 * Match name pattern against either internal or external name of either
5105 * castsource or casttarget
5106 */
5107 if (!validateSQLNamePattern(&buf, pattern, true, false,
5108 "ns.nspname", "ts.typname",
5109 "pg_catalog.format_type(ts.oid, NULL)",
5110 "pg_catalog.pg_type_is_visible(ts.oid)",
5111 NULL, 3))
5112 goto error_return;
5113
5114 appendPQExpBufferStr(&buf, ") OR (true");
5115
5116 if (!validateSQLNamePattern(&buf, pattern, true, false,
5117 "nt.nspname", "tt.typname",
5118 "pg_catalog.format_type(tt.oid, NULL)",
5119 "pg_catalog.pg_type_is_visible(tt.oid)",
5120 NULL, 3))
5121 goto error_return;
5122
5123 appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;");
5124
5125 res = PSQLexec(buf.data);
5127 if (!res)
5128 return false;
5129
5130 myopt.title = _("List of casts");
5131 myopt.translate_header = true;
5132 myopt.translate_columns = translate_columns;
5133 myopt.n_translate_columns = lengthof(translate_columns);
5134
5135 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5136
5137 PQclear(res);
5138 return true;
5139
5142 return false;
5143}

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

Referenced by exec_command_d().

◆ listCollations()

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

Definition at line 5151 of file describe.c.

5152{
5154 PGresult *res;
5156 static const bool translate_columns[] = {false, false, false, false, false, false, false, true, false};
5157
5159
5160 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching collations"));
5162 "SELECT\n"
5163 " n.nspname AS \"%s\",\n"
5164 " c.collname AS \"%s\",\n",
5165 gettext_noop("Schema"),
5166 gettext_noop("Name"));
5167
5169 " CASE c.collprovider "
5170 "WHEN " CppAsString2(COLLPROVIDER_DEFAULT) " THEN 'default' "
5171 "WHEN " CppAsString2(COLLPROVIDER_BUILTIN) " THEN 'builtin' "
5172 "WHEN " CppAsString2(COLLPROVIDER_LIBC) " THEN 'libc' "
5173 "WHEN " CppAsString2(COLLPROVIDER_ICU) " THEN 'icu' "
5174 "END AS \"%s\",\n",
5175 gettext_noop("Provider"));
5176
5178 " c.collcollate AS \"%s\",\n"
5179 " c.collctype AS \"%s\",\n",
5180 gettext_noop("Collate"),
5181 gettext_noop("Ctype"));
5182
5183 if (pset.sversion >= 170000)
5185 " c.colllocale AS \"%s\",\n",
5186 gettext_noop("Locale"));
5187 else if (pset.sversion >= 150000)
5189 " c.colliculocale AS \"%s\",\n",
5190 gettext_noop("Locale"));
5191 else
5193 " c.collcollate AS \"%s\",\n",
5194 gettext_noop("Locale"));
5195
5196 if (pset.sversion >= 160000)
5198 " c.collicurules AS \"%s\",\n",
5199 gettext_noop("ICU Rules"));
5200 else
5202 " NULL AS \"%s\",\n",
5203 gettext_noop("ICU Rules"));
5204
5205 if (pset.sversion >= 120000)
5207 " CASE WHEN c.collisdeterministic THEN '%s' ELSE '%s' END AS \"%s\"",
5208 gettext_noop("yes"), gettext_noop("no"),
5209 gettext_noop("Deterministic?"));
5210 else
5212 " '%s' AS \"%s\"",
5213 gettext_noop("yes"),
5214 gettext_noop("Deterministic?"));
5215
5216 if (verbose)
5218 ",\n pg_catalog.obj_description(c.oid, 'pg_collation') AS \"%s\"",
5219 gettext_noop("Description"));
5220
5222 "\nFROM pg_catalog.pg_collation c, pg_catalog.pg_namespace n\n"
5223 "WHERE n.oid = c.collnamespace\n");
5224
5225 if (!showSystem && !pattern)
5226 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
5227 " AND n.nspname <> 'information_schema'\n");
5228
5229 /*
5230 * Hide collations that aren't usable in the current database's encoding.
5231 * If you think to change this, note that pg_collation_is_visible rejects
5232 * unusable collations, so you will need to hack name pattern processing
5233 * somehow to avoid inconsistent behavior.
5234 */
5235 appendPQExpBufferStr(&buf, " AND c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))\n");
5236
5237 if (!validateSQLNamePattern(&buf, pattern, true, false,
5238 "n.nspname", "c.collname", NULL,
5239 "pg_catalog.pg_collation_is_visible(c.oid)",
5240 NULL, 3))
5241 {
5243 return false;
5244 }
5245
5246 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5247
5248 res = PSQLexec(buf.data);
5250 if (!res)
5251 return false;
5252
5253 myopt.title = _("List of collations");
5254 myopt.translate_header = true;
5255 myopt.translate_columns = translate_columns;
5256 myopt.n_translate_columns = lengthof(translate_columns);
5257
5258 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5259
5260 PQclear(res);
5261 return true;
5262}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, fb(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, _psqlSettings::popt, PQclear, printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listConversions()

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

Definition at line 4710 of file describe.c.

4711{
4713 PGresult *res;
4715 static const bool translate_columns[] =
4716 {false, false, false, false, true, false};
4717
4719
4720 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching conversions"));
4722 "SELECT n.nspname AS \"%s\",\n"
4723 " c.conname AS \"%s\",\n"
4724 " pg_catalog.pg_encoding_to_char(c.conforencoding) AS \"%s\",\n"
4725 " pg_catalog.pg_encoding_to_char(c.contoencoding) AS \"%s\",\n"
4726 " CASE WHEN c.condefault THEN '%s'\n"
4727 " ELSE '%s' END AS \"%s\"",
4728 gettext_noop("Schema"),
4729 gettext_noop("Name"),
4730 gettext_noop("Source"),
4731 gettext_noop("Destination"),
4732 gettext_noop("yes"), gettext_noop("no"),
4733 gettext_noop("Default?"));
4734
4735 if (verbose)
4737 ",\n d.description AS \"%s\"",
4738 gettext_noop("Description"));
4739
4741 "\nFROM pg_catalog.pg_conversion c\n"
4742 " JOIN pg_catalog.pg_namespace n "
4743 "ON n.oid = c.connamespace\n");
4744
4745 if (verbose)
4747 "LEFT JOIN pg_catalog.pg_description d "
4748 "ON d.classoid = c.tableoid\n"
4749 " AND d.objoid = c.oid "
4750 "AND d.objsubid = 0\n");
4751
4752 appendPQExpBufferStr(&buf, "WHERE true\n");
4753
4754 if (!showSystem && !pattern)
4755 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4756 " AND n.nspname <> 'information_schema'\n");
4757
4758 if (!validateSQLNamePattern(&buf, pattern, true, false,
4759 "n.nspname", "c.conname", NULL,
4760 "pg_catalog.pg_conversion_is_visible(c.oid)",
4761 NULL, 3))
4762 {
4764 return false;
4765 }
4766
4767 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4768
4769 res = PSQLexec(buf.data);
4771 if (!res)
4772 return false;
4773
4774 myopt.title = _("List of conversions");
4775 myopt.translate_header = true;
4776 myopt.translate_columns = translate_columns;
4777 myopt.n_translate_columns = lengthof(translate_columns);
4778
4779 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4780
4781 PQclear(res);
4782 return true;
4783}

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

Referenced by exec_command_d().

◆ listDbRoleSettings()

bool listDbRoleSettings ( const char pattern,
const char pattern2 
)

Definition at line 3932 of file describe.c.

3933{
3935 PGresult *res;
3937 bool havewhere;
3938
3940
3941 printfPQExpBuffer(&buf, "/* %s */\n", _("Get per-database and per-role settings"));
3942 appendPQExpBuffer(&buf, "SELECT rolname AS \"%s\", datname AS \"%s\",\n"
3943 "pg_catalog.array_to_string(setconfig, E'\\n') AS \"%s\"\n"
3944 "FROM pg_catalog.pg_db_role_setting s\n"
3945 "LEFT JOIN pg_catalog.pg_database d ON d.oid = setdatabase\n"
3946 "LEFT JOIN pg_catalog.pg_roles r ON r.oid = setrole\n",
3947 gettext_noop("Role"),
3948 gettext_noop("Database"),
3949 gettext_noop("Settings"));
3950 if (!validateSQLNamePattern(&buf, pattern, false, false,
3951 NULL, "r.rolname", NULL, NULL, &havewhere, 1))
3952 goto error_return;
3954 NULL, "d.datname", NULL, NULL,
3955 NULL, 1))
3956 goto error_return;
3957 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
3958
3959 res = PSQLexec(buf.data);
3961 if (!res)
3962 return false;
3963
3964 /*
3965 * Most functions in this file are content to print an empty table when
3966 * there are no matching objects. We intentionally deviate from that
3967 * here, but only in !quiet mode, because of the possibility that the user
3968 * is confused about what the two pattern arguments mean.
3969 */
3970 if (PQntuples(res) == 0 && !pset.quiet)
3971 {
3972 if (pattern && pattern2)
3973 pg_log_error("Did not find any settings for role \"%s\" and database \"%s\".",
3974 pattern, pattern2);
3975 else if (pattern)
3976 pg_log_error("Did not find any settings for role \"%s\".",
3977 pattern);
3978 else
3979 pg_log_error("Did not find any settings.");
3980 }
3981 else
3982 {
3983 myopt.title = _("List of settings");
3984 myopt.translate_header = true;
3985
3986 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
3987 }
3988
3989 PQclear(res);
3990 return true;
3991
3994 return false;
3995}

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

Referenced by exec_command_d().

◆ listDefaultACLs()

bool listDefaultACLs ( const char pattern)

Definition at line 1174 of file describe.c.

1175{
1177 PGresult *res;
1179 static const bool translate_columns[] = {false, false, true, false};
1180
1182
1183 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching default ACLs"));
1185 "SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS \"%s\",\n"
1186 " n.nspname AS \"%s\",\n"
1187 " CASE d.defaclobjtype "
1188 " WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s'"
1189 " WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' END AS \"%s\",\n"
1190 " ",
1191 gettext_noop("Owner"),
1192 gettext_noop("Schema"),
1194 gettext_noop("table"),
1196 gettext_noop("sequence"),
1198 gettext_noop("function"),
1200 gettext_noop("type"),
1202 gettext_noop("schema"),
1204 gettext_noop("large object"),
1205 gettext_noop("Type"));
1206
1207 printACLColumn(&buf, "d.defaclacl");
1208
1209 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_default_acl d\n"
1210 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.defaclnamespace\n");
1211
1212 if (!validateSQLNamePattern(&buf, pattern, false, false,
1213 NULL,
1214 "n.nspname",
1215 "pg_catalog.pg_get_userbyid(d.defaclrole)",
1216 NULL,
1217 NULL, 3))
1218 goto error_return;
1219
1220 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
1221
1222 res = PSQLexec(buf.data);
1223 if (!res)
1224 goto error_return;
1225
1226 printfPQExpBuffer(&buf, _("Default access privileges"));
1227 myopt.title = buf.data;
1228 myopt.translate_header = true;
1229 myopt.translate_columns = translate_columns;
1230 myopt.n_translate_columns = lengthof(translate_columns);
1231
1232 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1233
1235 PQclear(res);
1236 return true;
1237
1240 return false;
1241}

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

Referenced by exec_command_d().

◆ listDomains()

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

Definition at line 4626 of file describe.c.

4627{
4629 PGresult *res;
4631
4633
4634 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching domains"));
4636 "SELECT n.nspname as \"%s\",\n"
4637 " t.typname as \"%s\",\n"
4638 " pg_catalog.format_type(t.typbasetype, t.typtypmod) as \"%s\",\n"
4639 " (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type bt\n"
4640 " WHERE c.oid = t.typcollation AND bt.oid = t.typbasetype AND t.typcollation <> bt.typcollation) as \"%s\",\n"
4641 " CASE WHEN t.typnotnull THEN 'not null' END as \"%s\",\n"
4642 " t.typdefault as \"%s\",\n"
4643 " pg_catalog.array_to_string(ARRAY(\n"
4644 " 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"
4645 " ), ' ') as \"%s\"",
4646 gettext_noop("Schema"),
4647 gettext_noop("Name"),
4648 gettext_noop("Type"),
4649 gettext_noop("Collation"),
4650 gettext_noop("Nullable"),
4651 gettext_noop("Default"),
4652 gettext_noop("Check"));
4653
4654 if (verbose)
4655 {
4656 appendPQExpBufferStr(&buf, ",\n ");
4657 printACLColumn(&buf, "t.typacl");
4659 ",\n d.description as \"%s\"",
4660 gettext_noop("Description"));
4661 }
4662
4664 "\nFROM pg_catalog.pg_type t\n"
4665 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
4666
4667 if (verbose)
4669 " LEFT JOIN pg_catalog.pg_description d "
4670 "ON d.classoid = t.tableoid AND d.objoid = t.oid "
4671 "AND d.objsubid = 0\n");
4672
4673 appendPQExpBufferStr(&buf, "WHERE t.typtype = 'd'\n");
4674
4675 if (!showSystem && !pattern)
4676 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4677 " AND n.nspname <> 'information_schema'\n");
4678
4679 if (!validateSQLNamePattern(&buf, pattern, true, false,
4680 "n.nspname", "t.typname", NULL,
4681 "pg_catalog.pg_type_is_visible(t.oid)",
4682 NULL, 3))
4683 {
4685 return false;
4686 }
4687
4688 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4689
4690 res = PSQLexec(buf.data);
4692 if (!res)
4693 return false;
4694
4695 myopt.title = _("List of domains");
4696 myopt.translate_header = true;
4697
4698 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4699
4700 PQclear(res);
4701 return true;
4702}

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

Referenced by exec_command_d().

◆ listEventTriggers()

bool listEventTriggers ( const char pattern,
bool  verbose 
)

Definition at line 4862 of file describe.c.

4863{
4865 PGresult *res;
4867 static const bool translate_columns[] =
4868 {false, false, false, true, false, false, false};
4869
4871
4872 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching event triggers"));
4874 "SELECT evtname as \"%s\", "
4875 "evtevent as \"%s\", "
4876 "pg_catalog.pg_get_userbyid(e.evtowner) as \"%s\",\n"
4877 " case evtenabled when 'O' then '%s'"
4878 " when 'R' then '%s'"
4879 " when 'A' then '%s'"
4880 " when 'D' then '%s' end as \"%s\",\n"
4881 " e.evtfoid::pg_catalog.regproc as \"%s\", "
4882 "pg_catalog.array_to_string(array(select x"
4883 " from pg_catalog.unnest(evttags) as t(x)), ', ') as \"%s\"",
4884 gettext_noop("Name"),
4885 gettext_noop("Event"),
4886 gettext_noop("Owner"),
4887 gettext_noop("enabled"),
4888 gettext_noop("replica"),
4889 gettext_noop("always"),
4890 gettext_noop("disabled"),
4891 gettext_noop("Enabled"),
4892 gettext_noop("Function"),
4893 gettext_noop("Tags"));
4894 if (verbose)
4896 ",\npg_catalog.obj_description(e.oid, 'pg_event_trigger') as \"%s\"",
4897 gettext_noop("Description"));
4899 "\nFROM pg_catalog.pg_event_trigger e ");
4900
4901 if (!validateSQLNamePattern(&buf, pattern, false, false,
4902 NULL, "evtname", NULL, NULL,
4903 NULL, 1))
4904 {
4906 return false;
4907 }
4908
4909 appendPQExpBufferStr(&buf, "ORDER BY 1");
4910
4911 res = PSQLexec(buf.data);
4913 if (!res)
4914 return false;
4915
4916 myopt.title = _("List of event triggers");
4917 myopt.translate_header = true;
4918 myopt.translate_columns = translate_columns;
4919 myopt.n_translate_columns = lengthof(translate_columns);
4920
4921 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4922
4923 PQclear(res);
4924 return true;
4925}

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

Referenced by exec_command_d().

◆ listExtendedStats()

bool listExtendedStats ( const char pattern,
bool  verbose 
)

Definition at line 4933 of file describe.c.

4934{
4936 PGresult *res;
4938
4940
4941 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching extended statistics"));
4943 "SELECT \n"
4944 "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text AS \"%s\", \n"
4945 "es.stxname AS \"%s\", \n",
4946 gettext_noop("Schema"),
4947 gettext_noop("Name"));
4948
4949 if (pset.sversion >= 140000)
4951 "pg_catalog.format('%%s FROM %%s', \n"
4952 " pg_catalog.pg_get_statisticsobjdef_columns(es.oid), \n"
4953 " es.stxrelid::pg_catalog.regclass) AS \"%s\"",
4954 gettext_noop("Definition"));
4955 else
4957 "pg_catalog.format('%%s FROM %%s', \n"
4958 " (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(a.attname),', ') \n"
4959 " FROM pg_catalog.unnest(es.stxkeys) s(attnum) \n"
4960 " JOIN pg_catalog.pg_attribute a \n"
4961 " ON (es.stxrelid = a.attrelid \n"
4962 " AND a.attnum = s.attnum \n"
4963 " AND NOT a.attisdropped)), \n"
4964 "es.stxrelid::pg_catalog.regclass) AS \"%s\"",
4965 gettext_noop("Definition"));
4966
4968 ",\nCASE WHEN " CppAsString2(STATS_EXT_NDISTINCT) " = any(es.stxkind) THEN 'defined' \n"
4969 "END AS \"%s\", \n"
4970 "CASE WHEN " CppAsString2(STATS_EXT_DEPENDENCIES) " = any(es.stxkind) THEN 'defined' \n"
4971 "END AS \"%s\"",
4972 gettext_noop("Ndistinct"),
4973 gettext_noop("Dependencies"));
4974
4975 /*
4976 * Include the MCV statistics kind.
4977 */
4978 if (pset.sversion >= 120000)
4979 {
4981 ",\nCASE WHEN " CppAsString2(STATS_EXT_MCV) " = any(es.stxkind) THEN 'defined' \n"
4982 "END AS \"%s\" ",
4983 gettext_noop("MCV"));
4984 }
4985
4986 if (verbose)
4988 ", \npg_catalog.obj_description(oid, 'pg_statistic_ext') AS \"%s\"\n",
4989 gettext_noop("Description"));
4990
4992 " \nFROM pg_catalog.pg_statistic_ext es \n");
4993
4994 if (!validateSQLNamePattern(&buf, pattern,
4995 false, false,
4996 "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text", "es.stxname",
4997 NULL, "pg_catalog.pg_statistics_obj_is_visible(es.oid)",
4998 NULL, 3))
4999 {
5001 return false;
5002 }
5003
5004 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5005
5006 res = PSQLexec(buf.data);
5008 if (!res)
5009 return false;
5010
5011 myopt.title = _("List of extended statistics");
5012 myopt.translate_header = true;
5013
5014 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5015
5016 PQclear(res);
5017 return true;
5018}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, fb(), gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear, printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listExtensionContents()

bool listExtensionContents ( const char pattern)

Definition at line 6324 of file describe.c.

6325{
6327 PGresult *res;
6328 int i;
6329
6331
6332 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching installed extensions"));
6334 "SELECT e.extname, e.oid\n"
6335 "FROM pg_catalog.pg_extension e\n");
6336
6337 if (!validateSQLNamePattern(&buf, pattern,
6338 false, false,
6339 NULL, "e.extname", NULL,
6340 NULL,
6341 NULL, 1))
6342 {
6344 return false;
6345 }
6346
6347 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6348
6349 res = PSQLexec(buf.data);
6351 if (!res)
6352 return false;
6353
6354 if (PQntuples(res) == 0)
6355 {
6356 if (!pset.quiet)
6357 {
6358 if (pattern)
6359 pg_log_error("Did not find any extension named \"%s\".",
6360 pattern);
6361 else
6362 pg_log_error("Did not find any extensions.");
6363 }
6364 PQclear(res);
6365 return false;
6366 }
6367
6368 for (i = 0; i < PQntuples(res); i++)
6369 {
6370 const char *extname;
6371 const char *oid;
6372
6373 extname = PQgetvalue(res, i, 0);
6374 oid = PQgetvalue(res, i, 1);
6375
6376 if (!listOneExtensionContents(extname, oid))
6377 {
6378 PQclear(res);
6379 return false;
6380 }
6381 if (cancel_pressed)
6382 {
6383 PQclear(res);
6384 return false;
6385 }
6386 }
6387
6388 PQclear(res);
6389 return true;
6390}
static bool listOneExtensionContents(const char *extname, const char *oid)
Definition describe.c:6393

References _, appendPQExpBufferStr(), buf, cancel_pressed, fb(), 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 6268 of file describe.c.

6269{
6271 PGresult *res;
6273
6275
6276 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching installed extensions"));
6278 "SELECT e.extname AS \"%s\", "
6279 "e.extversion AS \"%s\", ae.default_version AS \"%s\","
6280 "n.nspname AS \"%s\", d.description AS \"%s\"\n"
6281 "FROM pg_catalog.pg_extension e "
6282 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace "
6283 "LEFT JOIN pg_catalog.pg_description d ON d.objoid = e.oid "
6284 "AND d.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass "
6285 "LEFT JOIN pg_catalog.pg_available_extensions() ae(name, default_version, comment) ON ae.name = e.extname\n",
6286 gettext_noop("Name"),
6287 gettext_noop("Version"),
6288 gettext_noop("Default version"),
6289 gettext_noop("Schema"),
6290 gettext_noop("Description"));
6291
6292 if (!validateSQLNamePattern(&buf, pattern,
6293 false, false,
6294 NULL, "e.extname", NULL,
6295 NULL,
6296 NULL, 1))
6297 {
6299 return false;
6300 }
6301
6302 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6303
6304 res = PSQLexec(buf.data);
6306 if (!res)
6307 return false;
6308
6309 myopt.title = _("List of installed extensions");
6310 myopt.translate_header = true;
6311
6312 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6313
6314 PQclear(res);
6315 return true;
6316}

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

Referenced by exec_command_d().

◆ listForeignDataWrappers()

bool listForeignDataWrappers ( const char pattern,
bool  verbose 
)

Definition at line 5986 of file describe.c.

5987{
5989 PGresult *res;
5991
5993
5994 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching foreign-data wrappers"));
5996 "SELECT fdw.fdwname AS \"%s\",\n"
5997 " pg_catalog.pg_get_userbyid(fdw.fdwowner) AS \"%s\",\n"
5998 " fdw.fdwhandler::pg_catalog.regproc AS \"%s\",\n"
5999 " fdw.fdwvalidator::pg_catalog.regproc AS \"%s\"",
6000 gettext_noop("Name"),
6001 gettext_noop("Owner"),
6002 gettext_noop("Handler"),
6003 gettext_noop("Validator"));
6004
6005 if (verbose)
6006 {
6007 appendPQExpBufferStr(&buf, ",\n ");
6008 printACLColumn(&buf, "fdwacl");
6010 ",\n CASE WHEN fdwoptions IS NULL THEN '' ELSE "
6011 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6012 " pg_catalog.quote_ident(option_name) || ' ' || "
6013 " pg_catalog.quote_literal(option_value) FROM "
6014 " pg_catalog.pg_options_to_table(fdwoptions)), ', ') || ')' "
6015 " END AS \"%s\""
6016 ",\n d.description AS \"%s\" ",
6017 gettext_noop("FDW options"),
6018 gettext_noop("Description"));
6019 }
6020
6021 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
6022
6023 if (verbose)
6025 "LEFT JOIN pg_catalog.pg_description d\n"
6026 " ON d.classoid = fdw.tableoid "
6027 "AND d.objoid = fdw.oid AND d.objsubid = 0\n");
6028
6029 if (!validateSQLNamePattern(&buf, pattern, false, false,
6030 NULL, "fdwname", NULL, NULL,
6031 NULL, 1))
6032 {
6034 return false;
6035 }
6036
6037 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6038
6039 res = PSQLexec(buf.data);
6041 if (!res)
6042 return false;
6043
6044 myopt.title = _("List of foreign-data wrappers");
6045 myopt.translate_header = true;
6046
6047 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6048
6049 PQclear(res);
6050 return true;
6051}

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

Referenced by exec_command_d().

◆ listForeignServers()

bool listForeignServers ( const char pattern,
bool  verbose 
)

Definition at line 6059 of file describe.c.

6060{
6062 PGresult *res;
6064
6066
6067 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching foreign servers"));
6069 "SELECT s.srvname AS \"%s\",\n"
6070 " pg_catalog.pg_get_userbyid(s.srvowner) AS \"%s\",\n"
6071 " f.fdwname AS \"%s\"",
6072 gettext_noop("Name"),
6073 gettext_noop("Owner"),
6074 gettext_noop("Foreign-data wrapper"));
6075
6076 if (verbose)
6077 {
6078 appendPQExpBufferStr(&buf, ",\n ");
6079 printACLColumn(&buf, "s.srvacl");
6081 ",\n"
6082 " s.srvtype AS \"%s\",\n"
6083 " s.srvversion AS \"%s\",\n"
6084 " CASE WHEN srvoptions IS NULL THEN '' ELSE "
6085 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6086 " pg_catalog.quote_ident(option_name) || ' ' || "
6087 " pg_catalog.quote_literal(option_value) FROM "
6088 " pg_catalog.pg_options_to_table(srvoptions)), ', ') || ')' "
6089 " END AS \"%s\",\n"
6090 " d.description AS \"%s\"",
6091 gettext_noop("Type"),
6092 gettext_noop("Version"),
6093 gettext_noop("FDW options"),
6094 gettext_noop("Description"));
6095 }
6096
6098 "\nFROM pg_catalog.pg_foreign_server s\n"
6099 " JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid=s.srvfdw\n");
6100
6101 if (verbose)
6103 "LEFT JOIN pg_catalog.pg_description d\n "
6104 "ON d.classoid = s.tableoid AND d.objoid = s.oid "
6105 "AND d.objsubid = 0\n");
6106
6107 if (!validateSQLNamePattern(&buf, pattern, false, false,
6108 NULL, "s.srvname", NULL, NULL,
6109 NULL, 1))
6110 {
6112 return false;
6113 }
6114
6115 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6116
6117 res = PSQLexec(buf.data);
6119 if (!res)
6120 return false;
6121
6122 myopt.title = _("List of foreign servers");
6123 myopt.translate_header = true;
6124
6125 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6126
6127 PQclear(res);
6128 return true;
6129}

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

Referenced by exec_command_d().

◆ listForeignTables()

bool listForeignTables ( const char pattern,
bool  verbose 
)

Definition at line 6194 of file describe.c.

6195{
6197 PGresult *res;
6199
6201
6202 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching foreign tables"));
6204 "SELECT n.nspname AS \"%s\",\n"
6205 " c.relname AS \"%s\",\n"
6206 " s.srvname AS \"%s\"",
6207 gettext_noop("Schema"),
6208 gettext_noop("Table"),
6209 gettext_noop("Server"));
6210
6211 if (verbose)
6213 ",\n CASE WHEN ftoptions IS NULL THEN '' ELSE "
6214 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6215 " pg_catalog.quote_ident(option_name) || ' ' || "
6216 " pg_catalog.quote_literal(option_value) FROM "
6217 " pg_catalog.pg_options_to_table(ftoptions)), ', ') || ')' "
6218 " END AS \"%s\",\n"
6219 " d.description AS \"%s\"",
6220 gettext_noop("FDW options"),
6221 gettext_noop("Description"));
6222
6224 "\nFROM pg_catalog.pg_foreign_table ft\n"
6225 " INNER JOIN pg_catalog.pg_class c"
6226 " ON c.oid = ft.ftrelid\n"
6227 " INNER JOIN pg_catalog.pg_namespace n"
6228 " ON n.oid = c.relnamespace\n"
6229 " INNER JOIN pg_catalog.pg_foreign_server s"
6230 " ON s.oid = ft.ftserver\n");
6231 if (verbose)
6233 " LEFT JOIN pg_catalog.pg_description d\n"
6234 " ON d.classoid = c.tableoid AND "
6235 "d.objoid = c.oid AND d.objsubid = 0\n");
6236
6237 if (!validateSQLNamePattern(&buf, pattern, false, false,
6238 "n.nspname", "c.relname", NULL,
6239 "pg_catalog.pg_table_is_visible(c.oid)",
6240 NULL, 3))
6241 {
6243 return false;
6244 }
6245
6246 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
6247
6248 res = PSQLexec(buf.data);
6250 if (!res)
6251 return false;
6252
6253 myopt.title = _("List of foreign tables");
6254 myopt.translate_header = true;
6255
6256 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6257
6258 PQclear(res);
6259 return true;
6260}

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

Referenced by exec_command_d().

◆ listLanguages()

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

Definition at line 4549 of file describe.c.

4550{
4552 PGresult *res;
4554
4556
4557 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching procedural languages"));
4559 "SELECT l.lanname AS \"%s\",\n"
4560 " pg_catalog.pg_get_userbyid(l.lanowner) as \"%s\",\n"
4561 " l.lanpltrusted AS \"%s\"",
4562 gettext_noop("Name"),
4563 gettext_noop("Owner"),
4564 gettext_noop("Trusted"));
4565
4566 if (verbose)
4567 {
4569 ",\n NOT l.lanispl AS \"%s\",\n"
4570 " l.lanplcallfoid::pg_catalog.regprocedure AS \"%s\",\n"
4571 " l.lanvalidator::pg_catalog.regprocedure AS \"%s\",\n "
4572 "l.laninline::pg_catalog.regprocedure AS \"%s\",\n ",
4573 gettext_noop("Internal language"),
4574 gettext_noop("Call handler"),
4575 gettext_noop("Validator"),
4576 gettext_noop("Inline handler"));
4577 printACLColumn(&buf, "l.lanacl");
4578 }
4579
4581 ",\n d.description AS \"%s\""
4582 "\nFROM pg_catalog.pg_language l\n"
4583 "LEFT JOIN pg_catalog.pg_description d\n"
4584 " ON d.classoid = l.tableoid AND d.objoid = l.oid\n"
4585 " AND d.objsubid = 0\n",
4586 gettext_noop("Description"));
4587
4588 if (pattern)
4589 {
4590 if (!validateSQLNamePattern(&buf, pattern, false, false,
4591 NULL, "l.lanname", NULL, NULL,
4592 NULL, 2))
4593 {
4595 return false;
4596 }
4597 }
4598
4599 if (!showSystem && !pattern)
4600 appendPQExpBufferStr(&buf, "WHERE l.lanplcallfoid != 0\n");
4601
4602
4603 appendPQExpBufferStr(&buf, "ORDER BY 1;");
4604
4605 res = PSQLexec(buf.data);
4607 if (!res)
4608 return false;
4609
4610 myopt.title = _("List of languages");
4611 myopt.translate_header = true;
4612
4613 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4614
4615 PQclear(res);
4616 return true;
4617}

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

Referenced by exec_command_d().

◆ listLargeObjects()

bool listLargeObjects ( bool  verbose)

Definition at line 7451 of file describe.c.

7452{
7454 PGresult *res;
7456
7458
7459 printfPQExpBuffer(&buf, "/* %s */\n", _("Get large objects"));
7461 "SELECT oid as \"%s\",\n"
7462 " pg_catalog.pg_get_userbyid(lomowner) as \"%s\",\n ",
7463 gettext_noop("ID"),
7464 gettext_noop("Owner"));
7465
7466 if (verbose)
7467 {
7468 printACLColumn(&buf, "lomacl");
7469 appendPQExpBufferStr(&buf, ",\n ");
7470 }
7471
7473 "pg_catalog.obj_description(oid, 'pg_largeobject') as \"%s\"\n"
7474 "FROM pg_catalog.pg_largeobject_metadata\n"
7475 "ORDER BY oid",
7476 gettext_noop("Description"));
7477
7478 res = PSQLexec(buf.data);
7480 if (!res)
7481 return false;
7482
7483 myopt.title = _("Large objects");
7484 myopt.translate_header = true;
7485
7486 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7487
7488 PQclear(res);
7489 return true;
7490}

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

6394{
6396 PGresult *res;
6397 PQExpBufferData title;
6399
6401
6402 printfPQExpBuffer(&buf, "/* %s */\n", _("Get installed extension's contents"));
6404 "SELECT pg_catalog.pg_describe_object(classid, objid, 0) AS \"%s\"\n"
6405 "FROM pg_catalog.pg_depend\n"
6406 "WHERE refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass AND refobjid = '%s' AND deptype = 'e'\n"
6407 "ORDER BY 1;",
6408 gettext_noop("Object description"),
6409 oid);
6410
6411 res = PSQLexec(buf.data);
6413 if (!res)
6414 return false;
6415
6416 initPQExpBuffer(&title);
6417 printfPQExpBuffer(&title, _("Objects in extension \"%s\""), extname);
6418 myopt.title = title.data;
6419 myopt.translate_header = true;
6420
6421 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6422
6423 termPQExpBuffer(&title);
6424 PQclear(res);
6425 return true;
6426}

References _, appendPQExpBuffer(), buf, PQExpBufferData::data, fb(), gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, _psqlSettings::popt, PQclear, printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, and termPQExpBuffer().

Referenced by listExtensionContents().

◆ listOperatorClasses()

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

Definition at line 7060 of file describe.c.

7062{
7064 PGresult *res;
7066 bool have_where = false;
7067 static const bool translate_columns[] = {false, false, false, false, false, false, false};
7068
7070
7071 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching operator classes"));
7073 "SELECT\n"
7074 " am.amname AS \"%s\",\n"
7075 " pg_catalog.format_type(c.opcintype, NULL) AS \"%s\",\n"
7076 " CASE\n"
7077 " WHEN c.opckeytype <> 0 AND c.opckeytype <> c.opcintype\n"
7078 " THEN pg_catalog.format_type(c.opckeytype, NULL)\n"
7079 " ELSE NULL\n"
7080 " END AS \"%s\",\n"
7081 " CASE\n"
7082 " WHEN pg_catalog.pg_opclass_is_visible(c.oid)\n"
7083 " THEN pg_catalog.format('%%I', c.opcname)\n"
7084 " ELSE pg_catalog.format('%%I.%%I', n.nspname, c.opcname)\n"
7085 " END AS \"%s\",\n"
7086 " (CASE WHEN c.opcdefault\n"
7087 " THEN '%s'\n"
7088 " ELSE '%s'\n"
7089 " END) AS \"%s\"",
7090 gettext_noop("AM"),
7091 gettext_noop("Input type"),
7092 gettext_noop("Storage type"),
7093 gettext_noop("Operator class"),
7094 gettext_noop("yes"),
7095 gettext_noop("no"),
7096 gettext_noop("Default?"));
7097 if (verbose)
7099 ",\n CASE\n"
7100 " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
7101 " THEN pg_catalog.format('%%I', of.opfname)\n"
7102 " ELSE pg_catalog.format('%%I.%%I', ofn.nspname, of.opfname)\n"
7103 " END AS \"%s\",\n"
7104 " pg_catalog.pg_get_userbyid(c.opcowner) AS \"%s\"\n",
7105 gettext_noop("Operator family"),
7106 gettext_noop("Owner"));
7108 "\nFROM pg_catalog.pg_opclass c\n"
7109 " LEFT JOIN pg_catalog.pg_am am on am.oid = c.opcmethod\n"
7110 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.opcnamespace\n"
7111 " LEFT JOIN pg_catalog.pg_type t ON t.oid = c.opcintype\n"
7112 " LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n");
7113 if (verbose)
7115 " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = c.opcfamily\n"
7116 " LEFT JOIN pg_catalog.pg_namespace ofn ON ofn.oid = of.opfnamespace\n");
7117
7120 false, false, NULL, "am.amname", NULL, NULL,
7121 &have_where, 1))
7122 goto error_return;
7123 if (type_pattern)
7124 {
7125 /* Match type name pattern against either internal or external name */
7127 "tn.nspname", "t.typname",
7128 "pg_catalog.format_type(t.oid, NULL)",
7129 "pg_catalog.pg_type_is_visible(t.oid)",
7130 NULL, 3))
7131 goto error_return;
7132 }
7133
7134 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
7135 res = PSQLexec(buf.data);
7137 if (!res)
7138 return false;
7139
7140 myopt.title = _("List of operator classes");
7141 myopt.translate_header = true;
7142 myopt.translate_columns = translate_columns;
7143 myopt.n_translate_columns = lengthof(translate_columns);
7144
7145 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7146
7147 PQclear(res);
7148 return true;
7149
7152 return false;
7153}

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

7164{
7166 PGresult *res;
7168 bool have_where = false;
7169 static const bool translate_columns[] = {false, false, false, false};
7170
7172
7173 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching operator families"));
7175 "SELECT\n"
7176 " am.amname AS \"%s\",\n"
7177 " CASE\n"
7178 " WHEN pg_catalog.pg_opfamily_is_visible(f.oid)\n"
7179 " THEN pg_catalog.format('%%I', f.opfname)\n"
7180 " ELSE pg_catalog.format('%%I.%%I', n.nspname, f.opfname)\n"
7181 " END AS \"%s\",\n"
7182 " (SELECT\n"
7183 " pg_catalog.string_agg(pg_catalog.format_type(oc.opcintype, NULL), ', ')\n"
7184 " FROM pg_catalog.pg_opclass oc\n"
7185 " WHERE oc.opcfamily = f.oid) \"%s\"",
7186 gettext_noop("AM"),
7187 gettext_noop("Operator family"),
7188 gettext_noop("Applicable types"));
7189 if (verbose)
7191 ",\n pg_catalog.pg_get_userbyid(f.opfowner) AS \"%s\"\n",
7192 gettext_noop("Owner"));
7194 "\nFROM pg_catalog.pg_opfamily f\n"
7195 " LEFT JOIN pg_catalog.pg_am am on am.oid = f.opfmethod\n"
7196 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = f.opfnamespace\n");
7197
7200 false, false, NULL, "am.amname", NULL, NULL,
7201 &have_where, 1))
7202 goto error_return;
7203 if (type_pattern)
7204 {
7206 " %s EXISTS (\n"
7207 " SELECT 1\n"
7208 " FROM pg_catalog.pg_type t\n"
7209 " JOIN pg_catalog.pg_opclass oc ON oc.opcintype = t.oid\n"
7210 " LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n"
7211 " WHERE oc.opcfamily = f.oid\n",
7212 have_where ? "AND" : "WHERE");
7213 /* Match type name pattern against either internal or external name */
7214 if (!validateSQLNamePattern(&buf, type_pattern, true, false,
7215 "tn.nspname", "t.typname",
7216 "pg_catalog.format_type(t.oid, NULL)",
7217 "pg_catalog.pg_type_is_visible(t.oid)",
7218 NULL, 3))
7219 goto error_return;
7220 appendPQExpBufferStr(&buf, " )\n");
7221 }
7222
7223 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
7224 res = PSQLexec(buf.data);
7226 if (!res)
7227 return false;
7228
7229 myopt.title = _("List of operator families");
7230 myopt.translate_header = true;
7231 myopt.translate_columns = translate_columns;
7232 myopt.n_translate_columns = lengthof(translate_columns);
7233
7234 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7235
7236 PQclear(res);
7237 return true;
7238
7241 return false;
7242}

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

7362{
7364 PGresult *res;
7366 bool have_where = false;
7367 static const bool translate_columns[] = {false, false, false, false, false, false};
7368
7370
7371 printfPQExpBuffer(&buf, "/* %s */\n",
7372 _("Get support functions of matching operator families"));
7374 "SELECT\n"
7375 " am.amname AS \"%s\",\n"
7376 " CASE\n"
7377 " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
7378 " THEN pg_catalog.format('%%I', of.opfname)\n"
7379 " ELSE pg_catalog.format('%%I.%%I', ns.nspname, of.opfname)\n"
7380 " END AS \"%s\",\n"
7381 " pg_catalog.format_type(ap.amproclefttype, NULL) AS \"%s\",\n"
7382 " pg_catalog.format_type(ap.amprocrighttype, NULL) AS \"%s\",\n"
7383 " ap.amprocnum AS \"%s\"\n",
7384 gettext_noop("AM"),
7385 gettext_noop("Operator family"),
7386 gettext_noop("Registered left type"),
7387 gettext_noop("Registered right type"),
7388 gettext_noop("Number"));
7389
7390 if (!verbose)
7392 ", p.proname AS \"%s\"\n",
7393 gettext_noop("Function"));
7394 else
7396 ", ap.amproc::pg_catalog.regprocedure AS \"%s\"\n",
7397 gettext_noop("Function"));
7398
7400 "FROM pg_catalog.pg_amproc ap\n"
7401 " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = ap.amprocfamily\n"
7402 " LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod\n"
7403 " LEFT JOIN pg_catalog.pg_namespace ns ON of.opfnamespace = ns.oid\n"
7404 " LEFT JOIN pg_catalog.pg_proc p ON ap.amproc = p.oid\n");
7405
7407 {
7409 false, false, NULL, "am.amname",
7410 NULL, NULL,
7411 &have_where, 1))
7412 goto error_return;
7413 }
7414 if (family_pattern)
7415 {
7417 "ns.nspname", "of.opfname", NULL, NULL,
7418 NULL, 3))
7419 goto error_return;
7420 }
7421
7422 appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
7423 " ap.amproclefttype = ap.amprocrighttype DESC,\n"
7424 " 3, 4, 5;");
7425
7426 res = PSQLexec(buf.data);
7428 if (!res)
7429 return false;
7430
7431 myopt.title = _("List of support functions of operator families");
7432 myopt.translate_header = true;
7433 myopt.translate_columns = translate_columns;
7434 myopt.n_translate_columns = lengthof(translate_columns);
7435
7436 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7437
7438 PQclear(res);
7439 return true;
7440
7443 return false;
7444}

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

7254{
7256 PGresult *res;
7258 bool have_where = false;
7259
7260 static const bool translate_columns[] = {false, false, false, false, false, false, true};
7261
7263
7264 printfPQExpBuffer(&buf, "/* %s */\n", _("Get operators of matching operator families"));
7266 "SELECT\n"
7267 " am.amname AS \"%s\",\n"
7268 " CASE\n"
7269 " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
7270 " THEN pg_catalog.format('%%I', of.opfname)\n"
7271 " ELSE pg_catalog.format('%%I.%%I', nsf.nspname, of.opfname)\n"
7272 " END AS \"%s\",\n"
7273 " o.amopopr::pg_catalog.regoperator AS \"%s\"\n,"
7274 " o.amopstrategy AS \"%s\",\n"
7275 " CASE o.amoppurpose\n"
7276 " WHEN " CppAsString2(AMOP_ORDER) " THEN '%s'\n"
7277 " WHEN " CppAsString2(AMOP_SEARCH) " THEN '%s'\n"
7278 " END AS \"%s\"\n",
7279 gettext_noop("AM"),
7280 gettext_noop("Operator family"),
7281 gettext_noop("Operator"),
7282 gettext_noop("Strategy"),
7283 gettext_noop("ordering"),
7284 gettext_noop("search"),
7285 gettext_noop("Purpose"));
7286
7287 if (verbose)
7289 ", ofs.opfname AS \"%s\",\n"
7290 " CASE\n"
7291 " WHEN p.proleakproof THEN '%s'\n"
7292 " ELSE '%s'\n"
7293 " END AS \"%s\"\n",
7294 gettext_noop("Sort opfamily"),
7295 gettext_noop("yes"),
7296 gettext_noop("no"),
7297 gettext_noop("Leakproof?"));
7299 "FROM pg_catalog.pg_amop o\n"
7300 " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = o.amopfamily\n"
7301 " LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod AND am.oid = o.amopmethod\n"
7302 " LEFT JOIN pg_catalog.pg_namespace nsf ON of.opfnamespace = nsf.oid\n");
7303 if (verbose)
7305 " LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n"
7306 " LEFT JOIN pg_catalog.pg_operator op ON op.oid = o.amopopr\n"
7307 " LEFT JOIN pg_catalog.pg_proc p ON p.oid = op.oprcode\n");
7308
7310 {
7312 false, false, NULL, "am.amname",
7313 NULL, NULL,
7314 &have_where, 1))
7315 goto error_return;
7316 }
7317
7318 if (family_pattern)
7319 {
7321 "nsf.nspname", "of.opfname", NULL, NULL,
7322 NULL, 3))
7323 goto error_return;
7324 }
7325
7326 appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
7327 " o.amoplefttype = o.amoprighttype DESC,\n"
7328 " pg_catalog.format_type(o.amoplefttype, NULL),\n"
7329 " pg_catalog.format_type(o.amoprighttype, NULL),\n"
7330 " o.amopstrategy;");
7331
7332 res = PSQLexec(buf.data);
7334 if (!res)
7335 return false;
7336
7337 myopt.title = _("List of operators of operator families");
7338 myopt.translate_header = true;
7339 myopt.translate_columns = translate_columns;
7340 myopt.n_translate_columns = lengthof(translate_columns);
7341
7342 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7343
7344 PQclear(res);
7345 return true;
7346
7349 return false;
7350}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, fb(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, _psqlSettings::popt, PQclear, printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, termPQExpBuffer(), validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listPartitionedTables()

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

Definition at line 4350 of file describe.c.

4351{
4352 bool showTables = strchr(reltypes, 't') != NULL;
4353 bool showIndexes = strchr(reltypes, 'i') != NULL;
4354 bool showNested = strchr(reltypes, 'n') != NULL;
4356 PQExpBufferData title;
4357 PGresult *res;
4359 bool translate_columns[] = {false, false, false, false, false, false, false, false, false, false};
4360 const char *tabletitle;
4361 bool mixed_output = false;
4362
4363 /* If no relation kind was selected, show them all */
4364 if (!showTables && !showIndexes)
4365 showTables = showIndexes = true;
4366
4367 if (showIndexes && !showTables)
4368 tabletitle = _("List of partitioned indexes"); /* \dPi */
4369 else if (showTables && !showIndexes)
4370 tabletitle = _("List of partitioned tables"); /* \dPt */
4371 else
4372 {
4373 /* show all kinds */
4374 tabletitle = _("List of partitioned relations");
4375 mixed_output = true;
4376 }
4377
4379
4380 printfPQExpBuffer(&buf, "/* %s */\n",
4381 _("Get matching partitioned relations"));
4383 "SELECT n.nspname as \"%s\",\n"
4384 " c.relname as \"%s\",\n"
4385 " pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"",
4386 gettext_noop("Schema"),
4387 gettext_noop("Name"),
4388 gettext_noop("Owner"));
4389
4390 if (mixed_output)
4391 {
4393 ",\n CASE c.relkind"
4394 " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
4395 " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
4396 " END as \"%s\"",
4397 gettext_noop("partitioned table"),
4398 gettext_noop("partitioned index"),
4399 gettext_noop("Type"));
4400
4401 translate_columns[3] = true;
4402 }
4403
4404 if (showNested || pattern)
4406 ",\n inh.inhparent::pg_catalog.regclass as \"%s\"",
4407 gettext_noop("Parent name"));
4408
4409 if (showIndexes)
4411 ",\n c2.oid::pg_catalog.regclass as \"%s\"",
4412 gettext_noop("Table"));
4413
4414 if (verbose)
4415 {
4416 /*
4417 * Table access methods were introduced in v12, and can be set on
4418 * partitioned tables since v17.
4419 */
4420 appendPQExpBuffer(&buf, ",\n am.amname as \"%s\"",
4421 gettext_noop("Access method"));
4422
4423 if (showNested)
4424 {
4426 ",\n s.dps as \"%s\"",
4427 gettext_noop("Leaf partition size"));
4429 ",\n s.tps as \"%s\"",
4430 gettext_noop("Total size"));
4431 }
4432 else
4433 /* Sizes of all partitions are considered in this case. */
4435 ",\n s.tps as \"%s\"",
4436 gettext_noop("Total size"));
4437
4439 ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"",
4440 gettext_noop("Description"));
4441 }
4442
4444 "\nFROM pg_catalog.pg_class c"
4445 "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace");
4446
4447 if (showIndexes)
4449 "\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid"
4450 "\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid");
4451
4452 if (showNested || pattern)
4454 "\n LEFT JOIN pg_catalog.pg_inherits inh ON c.oid = inh.inhrelid");
4455
4456 if (verbose)
4457 {
4459 "\n LEFT JOIN pg_catalog.pg_am am ON c.relam = am.oid");
4460
4461 if (pset.sversion < 120000)
4462 {
4464 ",\n LATERAL (WITH RECURSIVE d\n"
4465 " AS (SELECT inhrelid AS oid, 1 AS level\n"
4466 " FROM pg_catalog.pg_inherits\n"
4467 " WHERE inhparent = c.oid\n"
4468 " UNION ALL\n"
4469 " SELECT inhrelid, level + 1\n"
4470 " FROM pg_catalog.pg_inherits i\n"
4471 " JOIN d ON i.inhparent = d.oid)\n"
4472 " SELECT pg_catalog.pg_size_pretty(sum(pg_catalog.pg_table_size("
4473 "d.oid))) AS tps,\n"
4474 " pg_catalog.pg_size_pretty(sum("
4475 "\n CASE WHEN d.level = 1"
4476 " THEN pg_catalog.pg_table_size(d.oid) ELSE 0 END)) AS dps\n"
4477 " FROM d) s");
4478 }
4479 else
4480 {
4481 /* PostgreSQL 12 has pg_partition_tree function */
4483 ",\n LATERAL (SELECT pg_catalog.pg_size_pretty(sum("
4484 "\n CASE WHEN ppt.isleaf AND ppt.level = 1"
4485 "\n THEN pg_catalog.pg_table_size(ppt.relid)"
4486 " ELSE 0 END)) AS dps"
4487 ",\n pg_catalog.pg_size_pretty(sum("
4488 "pg_catalog.pg_table_size(ppt.relid))) AS tps"
4489 "\n FROM pg_catalog.pg_partition_tree(c.oid) ppt) s");
4490 }
4491 }
4492
4493 appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
4494 if (showTables)
4496 if (showIndexes)
4498 appendPQExpBufferStr(&buf, "''"); /* dummy */
4499 appendPQExpBufferStr(&buf, ")\n");
4500
4501 appendPQExpBufferStr(&buf, !showNested && !pattern ?
4502 " AND NOT c.relispartition\n" : "");
4503
4504 if (!pattern)
4505 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4506 " AND n.nspname !~ '^pg_toast'\n"
4507 " AND n.nspname <> 'information_schema'\n");
4508
4509 if (!validateSQLNamePattern(&buf, pattern, true, false,
4510 "n.nspname", "c.relname", NULL,
4511 "pg_catalog.pg_table_is_visible(c.oid)",
4512 NULL, 3))
4513 {
4515 return false;
4516 }
4517
4518 appendPQExpBuffer(&buf, "ORDER BY \"Schema\", %s%s\"Name\";",
4519 mixed_output ? "\"Type\" DESC, " : "",
4520 showNested || pattern ? "\"Parent name\" NULLS FIRST, " : "");
4521
4522 res = PSQLexec(buf.data);
4524 if (!res)
4525 return false;
4526
4527 initPQExpBuffer(&title);
4529
4530 myopt.title = title.data;
4531 myopt.translate_header = true;
4532 myopt.translate_columns = translate_columns;
4533 myopt.n_translate_columns = lengthof(translate_columns);
4534
4535 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4536
4537 termPQExpBuffer(&title);
4538
4539 PQclear(res);
4540 return true;
4541}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, PQExpBufferData::data, fb(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, _psqlSettings::popt, PQclear, printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, _psqlSettings::sversion, termPQExpBuffer(), validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listPublications()

bool listPublications ( const char pattern)

Definition at line 6492 of file describe.c.

6493{
6495 PGresult *res;
6497 static const bool translate_columns[] = {false, false, false, false, false, false, false, false, false, false};
6498
6500
6501 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching publications"));
6503 "SELECT pubname AS \"%s\",\n"
6504 " pg_catalog.pg_get_userbyid(pubowner) AS \"%s\",\n"
6505 " puballtables AS \"%s\"",
6506 gettext_noop("Name"),
6507 gettext_noop("Owner"),
6508 gettext_noop("All tables"));
6509
6510 if (pset.sversion >= 190000)
6512 ",\n puballsequences AS \"%s\"",
6513 gettext_noop("All sequences"));
6514
6516 ",\n pubinsert AS \"%s\",\n"
6517 " pubupdate AS \"%s\",\n"
6518 " pubdelete AS \"%s\"",
6519 gettext_noop("Inserts"),
6520 gettext_noop("Updates"),
6521 gettext_noop("Deletes"));
6522 if (pset.sversion >= 110000)
6524 ",\n pubtruncate AS \"%s\"",
6525 gettext_noop("Truncates"));
6526 if (pset.sversion >= 180000)
6528 ",\n (CASE pubgencols\n"
6529 " WHEN '%c' THEN 'none'\n"
6530 " WHEN '%c' THEN 'stored'\n"
6531 " END) AS \"%s\"",
6534 gettext_noop("Generated columns"));
6535 if (pset.sversion >= 130000)
6537 ",\n pubviaroot AS \"%s\"",
6538 gettext_noop("Via root"));
6539
6541 "\nFROM pg_catalog.pg_publication\n");
6542
6543 if (!validateSQLNamePattern(&buf, pattern, false, false,
6544 NULL, "pubname", NULL,
6545 NULL,
6546 NULL, 1))
6547 {
6549 return false;
6550 }
6551
6552 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6553
6554 res = PSQLexec(buf.data);
6556 if (!res)
6557 return false;
6558
6559 myopt.title = _("List of publications");
6560 myopt.translate_header = true;
6561 myopt.translate_columns = translate_columns;
6562 myopt.n_translate_columns = lengthof(translate_columns);
6563
6564 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6565
6566 PQclear(res);
6567
6568 return true;
6569}

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

Referenced by exec_command_d().

◆ listSchemas()

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

Definition at line 5270 of file describe.c.

5271{
5273 PGresult *res;
5275 int pub_schema_tuples = 0;
5276 char **footers = NULL;
5277
5279
5280 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching schemas"));
5282 "SELECT n.nspname AS \"%s\",\n"
5283 " pg_catalog.pg_get_userbyid(n.nspowner) AS \"%s\"",
5284 gettext_noop("Name"),
5285 gettext_noop("Owner"));
5286
5287 if (verbose)
5288 {
5289 appendPQExpBufferStr(&buf, ",\n ");
5290 printACLColumn(&buf, "n.nspacl");
5292 ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"",
5293 gettext_noop("Description"));
5294 }
5295
5297 "\nFROM pg_catalog.pg_namespace n\n");
5298
5299 if (!showSystem && !pattern)
5301 "WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'\n");
5302
5303 if (!validateSQLNamePattern(&buf, pattern,
5304 !showSystem && !pattern, false,
5305 NULL, "n.nspname", NULL,
5306 NULL,
5307 NULL, 2))
5308 goto error_return;
5309
5310 appendPQExpBufferStr(&buf, "ORDER BY 1;");
5311
5312 res = PSQLexec(buf.data);
5313 if (!res)
5314 goto error_return;
5315
5316 myopt.title = _("List of schemas");
5317 myopt.translate_header = true;
5318
5319 if (pattern && pset.sversion >= 150000)
5320 {
5322 int i;
5323
5324 printfPQExpBuffer(&buf, "/* %s */\n",
5325 _("Get publications that publish this schema"));
5327 "SELECT pubname \n"
5328 "FROM pg_catalog.pg_publication p\n"
5329 " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
5330 " JOIN pg_catalog.pg_namespace n ON n.oid = pn.pnnspid \n"
5331 "WHERE n.nspname = '%s'\n"
5332 "ORDER BY 1",
5333 pattern);
5334 result = PSQLexec(buf.data);
5335 if (!result)
5336 goto error_return;
5337 else
5339
5340 if (pub_schema_tuples > 0)
5341 {
5342 /*
5343 * Allocate memory for footers. Size of footers will be 1 (for
5344 * storing "Included in publications:" string) + publication
5345 * schema mapping count + 1 (for storing NULL).
5346 */
5347 footers = pg_malloc_array(char *, 1 + pub_schema_tuples + 1);
5348 footers[0] = pg_strdup(_("Included in publications:"));
5349
5350 /* Might be an empty set - that's ok */
5351 for (i = 0; i < pub_schema_tuples; i++)
5352 {
5353 printfPQExpBuffer(&buf, " \"%s\"",
5354 PQgetvalue(result, i, 0));
5355
5356 footers[i + 1] = pg_strdup(buf.data);
5357 }
5358
5359 footers[i + 1] = NULL;
5360 myopt.footers = footers;
5361 }
5362
5363 PQclear(result);
5364 }
5365
5366 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5367
5369 PQclear(res);
5370
5371 /* Free the memory allocated for the footer */
5372 if (footers)
5373 {
5374 char **footer = NULL;
5375
5376 for (footer = footers; *footer; footer++)
5377 pg_free(*footer);
5378
5379 pg_free(footers);
5380 }
5381
5382 return true;
5383
5386 return false;
5387}
#define pg_malloc_array(type, count)
Definition fe_memutils.h:66

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, fb(), gettext_noop, i, initPQExpBuffer(), _psqlSettings::logfile, pg_free(), pg_malloc_array, pg_strdup(), _psqlSettings::popt, PQclear, PQgetvalue, PQntuples, printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, result, _psqlSettings::sversion, termPQExpBuffer(), validateSQLNamePattern(), and verbose.

Referenced by exec_command_d().

◆ listTables()

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

Definition at line 4083 of file describe.c.

4084{
4085 bool showTables = strchr(tabtypes, 't') != NULL;
4086 bool showIndexes = strchr(tabtypes, 'i') != NULL;
4087 bool showViews = strchr(tabtypes, 'v') != NULL;
4088 bool showMatViews = strchr(tabtypes, 'm') != NULL;
4089 bool showSeq = strchr(tabtypes, 's') != NULL;
4090 bool showForeign = strchr(tabtypes, 'E') != NULL;
4091 bool showPropGraphs = strchr(tabtypes, 'G') != NULL;
4092
4093 int ntypes;
4095 PGresult *res;
4097 int cols_so_far;
4098 bool translate_columns[] = {false, false, true, false, false, false, false, false, false};
4099
4100 /* Count the number of explicitly-requested relation types */
4103 /* If none, we default to \dtvmsEG (but see also command.c) */
4104 if (ntypes == 0)
4106
4108
4109 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching relations"));
4111 "SELECT n.nspname as \"%s\",\n"
4112 " c.relname as \"%s\",\n"
4113 " CASE c.relkind"
4114 " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'"
4115 " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'"
4116 " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'"
4117 " WHEN " CppAsString2(RELKIND_INDEX) " THEN '%s'"
4118 " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'"
4119 " WHEN " CppAsString2(RELKIND_TOASTVALUE) " THEN '%s'"
4120 " WHEN " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN '%s'"
4121 " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
4122 " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
4123 " WHEN " CppAsString2(RELKIND_PROPGRAPH) " THEN '%s'"
4124 " END as \"%s\",\n"
4125 " pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"",
4126 gettext_noop("Schema"),
4127 gettext_noop("Name"),
4128 gettext_noop("table"),
4129 gettext_noop("view"),
4130 gettext_noop("materialized view"),
4131 gettext_noop("index"),
4132 gettext_noop("sequence"),
4133 gettext_noop("TOAST table"),
4134 gettext_noop("foreign table"),
4135 gettext_noop("partitioned table"),
4136 gettext_noop("partitioned index"),
4137 gettext_noop("property graph"),
4138 gettext_noop("Type"),
4139 gettext_noop("Owner"));
4140 cols_so_far = 4;
4141
4142 if (showIndexes)
4143 {
4145 ",\n c2.relname as \"%s\"",
4146 gettext_noop("Table"));
4147 cols_so_far++;
4148 }
4149
4150 if (verbose)
4151 {
4152 /*
4153 * Show whether a relation is permanent, temporary, or unlogged.
4154 */
4156 ",\n CASE c.relpersistence "
4157 "WHEN " CppAsString2(RELPERSISTENCE_PERMANENT) " THEN '%s' "
4158 "WHEN " CppAsString2(RELPERSISTENCE_TEMP) " THEN '%s' "
4159 "WHEN " CppAsString2(RELPERSISTENCE_UNLOGGED) " THEN '%s' "
4160 "END as \"%s\"",
4161 gettext_noop("permanent"),
4162 gettext_noop("temporary"),
4163 gettext_noop("unlogged"),
4164 gettext_noop("Persistence"));
4165 translate_columns[cols_so_far] = true;
4166
4167 /*
4168 * We don't bother to count cols_so_far below here, as there's no need
4169 * to; this might change with future additions to the output columns.
4170 */
4171
4172 /*
4173 * Access methods exist for tables, materialized views and indexes.
4174 * This has been introduced in PostgreSQL 12 for tables.
4175 */
4176 if (pset.sversion >= 120000 && !pset.hide_tableam &&
4179 ",\n am.amname as \"%s\"",
4180 gettext_noop("Access method"));
4181
4183 ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\""
4184 ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"",
4185 gettext_noop("Size"),
4186 gettext_noop("Description"));
4187 }
4188
4190 "\nFROM pg_catalog.pg_class c"
4191 "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace");
4192
4193 if (pset.sversion >= 120000 && !pset.hide_tableam &&
4196 "\n LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam");
4197
4198 if (showIndexes)
4200 "\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid"
4201 "\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid");
4202
4203 appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
4204 if (showTables)
4205 {
4208 /* with 'S' or a pattern, allow 't' to match TOAST tables too */
4209 if (showSystem || pattern)
4211 }
4212 if (showViews)
4214 if (showMatViews)
4216 if (showIndexes)
4219 if (showSeq)
4221 if (showSystem || pattern)
4222 appendPQExpBufferStr(&buf, "'s',"); /* was RELKIND_SPECIAL */
4223 if (showForeign)
4225 if (showPropGraphs)
4227
4228 appendPQExpBufferStr(&buf, "''"); /* dummy */
4229 appendPQExpBufferStr(&buf, ")\n");
4230
4231 if (!showSystem && !pattern)
4232 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4233 " AND n.nspname !~ '^pg_toast'\n"
4234 " AND n.nspname <> 'information_schema'\n");
4235
4236 if (!validateSQLNamePattern(&buf, pattern, true, false,
4237 "n.nspname", "c.relname", NULL,
4238 "pg_catalog.pg_table_is_visible(c.oid)",
4239 NULL, 3))
4240 {
4242 return false;
4243 }
4244
4245 appendPQExpBufferStr(&buf, "ORDER BY 1,2;");
4246
4247 res = PSQLexec(buf.data);
4249 if (!res)
4250 return false;
4251
4252 /*
4253 * Most functions in this file are content to print an empty table when
4254 * there are no matching objects. We intentionally deviate from that
4255 * here, but only in !quiet mode, for historical reasons.
4256 */
4257 if (PQntuples(res) == 0 && !pset.quiet)
4258 {
4259 if (pattern)
4260 {
4261 if (ntypes != 1)
4262 pg_log_error("Did not find any relations named \"%s\".",
4263 pattern);
4264 else if (showTables)
4265 pg_log_error("Did not find any tables named \"%s\".",
4266 pattern);
4267 else if (showIndexes)
4268 pg_log_error("Did not find any indexes named \"%s\".",
4269 pattern);
4270 else if (showViews)
4271 pg_log_error("Did not find any views named \"%s\".",
4272 pattern);
4273 else if (showMatViews)
4274 pg_log_error("Did not find any materialized views named \"%s\".",
4275 pattern);
4276 else if (showSeq)
4277 pg_log_error("Did not find any sequences named \"%s\".",
4278 pattern);
4279 else if (showForeign)
4280 pg_log_error("Did not find any foreign tables named \"%s\".",
4281 pattern);
4282 else if (showPropGraphs)
4283 pg_log_error("Did not find any property graphs named \"%s\".",
4284 pattern);
4285 else /* should not get here */
4286 pg_log_error_internal("Did not find any ??? named \"%s\".",
4287 pattern);
4288 }
4289 else
4290 {
4291 if (ntypes != 1)
4292 pg_log_error("Did not find any relations.");
4293 else if (showTables)
4294 pg_log_error("Did not find any tables.");
4295 else if (showIndexes)
4296 pg_log_error("Did not find any indexes.");
4297 else if (showViews)
4298 pg_log_error("Did not find any views.");
4299 else if (showMatViews)
4300 pg_log_error("Did not find any materialized views.");
4301 else if (showSeq)
4302 pg_log_error("Did not find any sequences.");
4303 else if (showForeign)
4304 pg_log_error("Did not find any foreign tables.");
4305 else if (showPropGraphs)
4306 pg_log_error("Did not find any property graphs.");
4307 else /* should not get here */
4308 pg_log_error_internal("Did not find any ??? relations.");
4309 }
4310 }
4311 else
4312 {
4313 myopt.title =
4314 (ntypes != 1) ? _("List of relations") :
4315 (showTables) ? _("List of tables") :
4316 (showIndexes) ? _("List of indexes") :
4317 (showViews) ? _("List of views") :
4318 (showMatViews) ? _("List of materialized views") :
4319 (showSeq) ? _("List of sequences") :
4320 (showForeign) ? _("List of foreign tables") :
4321 (showPropGraphs) ? _("List of property graphs") :
4322 "List of ???"; /* should not get here */
4323 myopt.translate_header = true;
4324 myopt.translate_columns = translate_columns;
4325 myopt.n_translate_columns = lengthof(translate_columns);
4326
4327 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4328 }
4329
4330 PQclear(res);
4331 return true;
4332}
#define pg_log_error_internal(...)
Definition logging.h:162

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

Referenced by exec_command_d().

◆ listTSConfigs()

bool listTSConfigs ( const char pattern,
bool  verbose 
)

Definition at line 5779 of file describe.c.

5780{
5782 PGresult *res;
5784
5785 if (verbose)
5786 return listTSConfigsVerbose(pattern);
5787
5789
5790 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching text search configurations"));
5792 "SELECT\n"
5793 " n.nspname as \"%s\",\n"
5794 " c.cfgname as \"%s\",\n"
5795 " pg_catalog.obj_description(c.oid, 'pg_ts_config') as \"%s\"\n"
5796 "FROM pg_catalog.pg_ts_config c\n"
5797 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace\n",
5798 gettext_noop("Schema"),
5799 gettext_noop("Name"),
5800 gettext_noop("Description")
5801 );
5802
5803 if (!validateSQLNamePattern(&buf, pattern, false, false,
5804 "n.nspname", "c.cfgname", NULL,
5805 "pg_catalog.pg_ts_config_is_visible(c.oid)",
5806 NULL, 3))
5807 {
5809 return false;
5810 }
5811
5812 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5813
5814 res = PSQLexec(buf.data);
5816 if (!res)
5817 return false;
5818
5819 myopt.title = _("List of text search configurations");
5820 myopt.translate_header = true;
5821
5822 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5823
5824 PQclear(res);
5825 return true;
5826}
static bool listTSConfigsVerbose(const char *pattern)
Definition describe.c:5829

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

Referenced by exec_command_d().

◆ listTSConfigsVerbose()

static bool listTSConfigsVerbose ( const char pattern)
static

Definition at line 5829 of file describe.c.

5830{
5832 PGresult *res;
5833 int i;
5834
5836
5837 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching text search configurations"));
5839 "SELECT c.oid, c.cfgname,\n"
5840 " n.nspname,\n"
5841 " p.prsname,\n"
5842 " np.nspname as pnspname\n"
5843 "FROM pg_catalog.pg_ts_config c\n"
5844 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace,\n"
5845 " pg_catalog.pg_ts_parser p\n"
5846 " LEFT JOIN pg_catalog.pg_namespace np ON np.oid = p.prsnamespace\n"
5847 "WHERE p.oid = c.cfgparser\n"
5848 );
5849
5850 if (!validateSQLNamePattern(&buf, pattern, true, false,
5851 "n.nspname", "c.cfgname", NULL,
5852 "pg_catalog.pg_ts_config_is_visible(c.oid)",
5853 NULL, 3))
5854 {
5856 return false;
5857 }
5858
5859 appendPQExpBufferStr(&buf, "ORDER BY 3, 2;");
5860
5861 res = PSQLexec(buf.data);
5863 if (!res)
5864 return false;
5865
5866 if (PQntuples(res) == 0)
5867 {
5868 if (!pset.quiet)
5869 {
5870 if (pattern)
5871 pg_log_error("Did not find any text search configuration named \"%s\".",
5872 pattern);
5873 else
5874 pg_log_error("Did not find any text search configurations.");
5875 }
5876 PQclear(res);
5877 return false;
5878 }
5879
5880 for (i = 0; i < PQntuples(res); i++)
5881 {
5882 const char *oid;
5883 const char *cfgname;
5884 const char *nspname = NULL;
5885 const char *prsname;
5886 const char *pnspname = NULL;
5887
5888 oid = PQgetvalue(res, i, 0);
5889 cfgname = PQgetvalue(res, i, 1);
5890 if (!PQgetisnull(res, i, 2))
5891 nspname = PQgetvalue(res, i, 2);
5892 prsname = PQgetvalue(res, i, 3);
5893 if (!PQgetisnull(res, i, 4))
5894 pnspname = PQgetvalue(res, i, 4);
5895
5896 if (!describeOneTSConfig(oid, nspname, cfgname, pnspname, prsname))
5897 {
5898 PQclear(res);
5899 return false;
5900 }
5901
5902 if (cancel_pressed)
5903 {
5904 PQclear(res);
5905 return false;
5906 }
5907 }
5908
5909 PQclear(res);
5910 return true;
5911}
static bool describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname, const char *pnspname, const char *prsname)
Definition describe.c:5914

References _, appendPQExpBufferStr(), buf, cancel_pressed, describeOneTSConfig(), fb(), 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 5647 of file describe.c.

5648{
5650 PGresult *res;
5652
5654
5655 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching text search dictionaries"));
5657 "SELECT\n"
5658 " n.nspname as \"%s\",\n"
5659 " d.dictname as \"%s\",\n",
5660 gettext_noop("Schema"),
5661 gettext_noop("Name"));
5662
5663 if (verbose)
5664 {
5666 " ( SELECT COALESCE(nt.nspname, '(null)')::pg_catalog.text || '.' || t.tmplname FROM\n"
5667 " pg_catalog.pg_ts_template t\n"
5668 " LEFT JOIN pg_catalog.pg_namespace nt ON nt.oid = t.tmplnamespace\n"
5669 " WHERE d.dicttemplate = t.oid ) AS \"%s\",\n"
5670 " d.dictinitoption as \"%s\",\n",
5671 gettext_noop("Template"),
5672 gettext_noop("Init options"));
5673 }
5674
5676 " pg_catalog.obj_description(d.oid, 'pg_ts_dict') as \"%s\"\n",
5677 gettext_noop("Description"));
5678
5679 appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_dict d\n"
5680 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace\n");
5681
5682 if (!validateSQLNamePattern(&buf, pattern, false, false,
5683 "n.nspname", "d.dictname", NULL,
5684 "pg_catalog.pg_ts_dict_is_visible(d.oid)",
5685 NULL, 3))
5686 {
5688 return false;
5689 }
5690
5691 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5692
5693 res = PSQLexec(buf.data);
5695 if (!res)
5696 return false;
5697
5698 myopt.title = _("List of text search dictionaries");
5699 myopt.translate_header = true;
5700
5701 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5702
5703 PQclear(res);
5704 return true;
5705}

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

Referenced by exec_command_d().

◆ listTSParsers()

bool listTSParsers ( const char pattern,
bool  verbose 
)

Definition at line 5395 of file describe.c.

5396{
5398 PGresult *res;
5400
5401 if (verbose)
5402 return listTSParsersVerbose(pattern);
5403
5405
5406 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching text search parsers"));
5408 "SELECT\n"
5409 " n.nspname as \"%s\",\n"
5410 " p.prsname as \"%s\",\n"
5411 " pg_catalog.obj_description(p.oid, 'pg_ts_parser') as \"%s\"\n"
5412 "FROM pg_catalog.pg_ts_parser p\n"
5413 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n",
5414 gettext_noop("Schema"),
5415 gettext_noop("Name"),
5416 gettext_noop("Description")
5417 );
5418
5419 if (!validateSQLNamePattern(&buf, pattern, false, false,
5420 "n.nspname", "p.prsname", NULL,
5421 "pg_catalog.pg_ts_parser_is_visible(p.oid)",
5422 NULL, 3))
5423 {
5425 return false;
5426 }
5427
5428 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5429
5430 res = PSQLexec(buf.data);
5432 if (!res)
5433 return false;
5434
5435 myopt.title = _("List of text search parsers");
5436 myopt.translate_header = true;
5437
5438 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5439
5440 PQclear(res);
5441 return true;
5442}
static bool listTSParsersVerbose(const char *pattern)
Definition describe.c:5448

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

Referenced by exec_command_d().

◆ listTSParsersVerbose()

static bool listTSParsersVerbose ( const char pattern)
static

Definition at line 5448 of file describe.c.

5449{
5451 PGresult *res;
5452 int i;
5453
5455
5456 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching text search parsers"));
5458 "SELECT p.oid,\n"
5459 " n.nspname,\n"
5460 " p.prsname\n"
5461 "FROM pg_catalog.pg_ts_parser p\n"
5462 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n"
5463 );
5464
5465 if (!validateSQLNamePattern(&buf, pattern, false, false,
5466 "n.nspname", "p.prsname", NULL,
5467 "pg_catalog.pg_ts_parser_is_visible(p.oid)",
5468 NULL, 3))
5469 {
5471 return false;
5472 }
5473
5474 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5475
5476 res = PSQLexec(buf.data);
5478 if (!res)
5479 return false;
5480
5481 if (PQntuples(res) == 0)
5482 {
5483 if (!pset.quiet)
5484 {
5485 if (pattern)
5486 pg_log_error("Did not find any text search parser named \"%s\".",
5487 pattern);
5488 else
5489 pg_log_error("Did not find any text search parsers.");
5490 }
5491 PQclear(res);
5492 return false;
5493 }
5494
5495 for (i = 0; i < PQntuples(res); i++)
5496 {
5497 const char *oid;
5498 const char *nspname = NULL;
5499 const char *prsname;
5500
5501 oid = PQgetvalue(res, i, 0);
5502 if (!PQgetisnull(res, i, 1))
5503 nspname = PQgetvalue(res, i, 1);
5504 prsname = PQgetvalue(res, i, 2);
5505
5506 if (!describeOneTSParser(oid, nspname, prsname))
5507 {
5508 PQclear(res);
5509 return false;
5510 }
5511
5512 if (cancel_pressed)
5513 {
5514 PQclear(res);
5515 return false;
5516 }
5517 }
5518
5519 PQclear(res);
5520 return true;
5521}
static bool describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
Definition describe.c:5524

References _, appendPQExpBufferStr(), buf, cancel_pressed, describeOneTSParser(), fb(), 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 5713 of file describe.c.

5714{
5716 PGresult *res;
5718
5720
5721 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching text search templates"));
5722 if (verbose)
5724 "SELECT\n"
5725 " n.nspname AS \"%s\",\n"
5726 " t.tmplname AS \"%s\",\n"
5727 " t.tmplinit::pg_catalog.regproc AS \"%s\",\n"
5728 " t.tmpllexize::pg_catalog.regproc AS \"%s\",\n"
5729 " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
5730 gettext_noop("Schema"),
5731 gettext_noop("Name"),
5732 gettext_noop("Init"),
5733 gettext_noop("Lexize"),
5734 gettext_noop("Description"));
5735 else
5737 "SELECT\n"
5738 " n.nspname AS \"%s\",\n"
5739 " t.tmplname AS \"%s\",\n"
5740 " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
5741 gettext_noop("Schema"),
5742 gettext_noop("Name"),
5743 gettext_noop("Description"));
5744
5745 appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_template t\n"
5746 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.tmplnamespace\n");
5747
5748 if (!validateSQLNamePattern(&buf, pattern, false, false,
5749 "n.nspname", "t.tmplname", NULL,
5750 "pg_catalog.pg_ts_template_is_visible(t.oid)",
5751 NULL, 3))
5752 {
5754 return false;
5755 }
5756
5757 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5758
5759 res = PSQLexec(buf.data);
5761 if (!res)
5762 return false;
5763
5764 myopt.title = _("List of text search templates");
5765 myopt.translate_header = true;
5766
5767 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5768
5769 PQclear(res);
5770 return true;
5771}

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

Referenced by exec_command_d().

◆ listUserMappings()

bool listUserMappings ( const char pattern,
bool  verbose 
)

Definition at line 6137 of file describe.c.

6138{
6140 PGresult *res;
6142
6144
6145 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching user mappings"));
6147 "SELECT um.srvname AS \"%s\",\n"
6148 " um.usename AS \"%s\"",
6149 gettext_noop("Server"),
6150 gettext_noop("User name"));
6151
6152 if (verbose)
6154 ",\n CASE WHEN umoptions IS NULL THEN '' ELSE "
6155 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6156 " pg_catalog.quote_ident(option_name) || ' ' || "
6157 " pg_catalog.quote_literal(option_value) FROM "
6158 " pg_catalog.pg_options_to_table(umoptions)), ', ') || ')' "
6159 " END AS \"%s\"",
6160 gettext_noop("FDW options"));
6161
6162 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_user_mappings um\n");
6163
6164 if (!validateSQLNamePattern(&buf, pattern, false, false,
6165 NULL, "um.srvname", "um.usename", NULL,
6166 NULL, 1))
6167 {
6169 return false;
6170 }
6171
6172 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
6173
6174 res = PSQLexec(buf.data);
6176 if (!res)
6177 return false;
6178
6179 myopt.title = _("List of user mappings");
6180 myopt.translate_header = true;
6181
6182 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6183
6184 PQclear(res);
6185 return true;
6186}

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

Referenced by exec_command_d().

◆ map_typename_pattern()

static const char * map_typename_pattern ( const char pattern)
static

Definition at line 728 of file describe.c.

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

References fb(), i, and pg_strcasecmp().

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

◆ objectDescription()

bool objectDescription ( const char pattern,
bool  showSystem 
)

Definition at line 1256 of file describe.c.

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

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, fb(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, _psqlSettings::popt, PQclear, printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, termPQExpBuffer(), and validateSQLNamePattern().

Referenced by exec_command_d().

◆ permissionsList()

bool permissionsList ( const char pattern,
bool  showSystem 
)

Definition at line 1037 of file describe.c.

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

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, fb(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, _psqlSettings::popt, PQclear, printACLColumn(), printfPQExpBuffer(), printQuery(), pset, PSQLexec(), _psqlSettings::queryFout, termPQExpBuffer(), and validateSQLNamePattern().

Referenced by exec_command_d(), and exec_command_z().

◆ printACLColumn()

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

Definition at line 7042 of file describe.c.

7043{
7045 "CASE"
7046 " WHEN pg_catalog.array_length(%s, 1) = 0 THEN '%s'"
7047 " ELSE pg_catalog.array_to_string(%s, E'\\n')"
7048 " END AS \"%s\"",
7049 colname, gettext_noop("(none)"),
7050 colname, gettext_noop("Access privileges"));
7051}

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

6444{
6446 int dotcnt;
6447 bool added;
6448
6453 if (added_clause != NULL)
6455
6456 if (dotcnt >= maxparts)
6457 {
6458 pg_log_error("improper qualified name (too many dotted names): %s",
6459 pattern);
6460 goto error_return;
6461 }
6462
6463 if (maxparts > 1 && dotcnt == maxparts - 1)
6464 {
6465 if (PQdb(pset.db) == NULL)
6466 {
6467 pg_log_error("You are currently not connected to a database.");
6468 goto error_return;
6469 }
6470 if (strcmp(PQdb(pset.db), dbbuf.data) != 0)
6471 {
6472 pg_log_error("cross-database references are not implemented: %s",
6473 pattern);
6474 goto error_return;
6475 }
6476 }
6478 return true;
6479
6482 return false;
6483}
char * PQdb(const PGconn *conn)

References buf, _psqlSettings::db, fb(), 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().