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

3920{
3921 if (buf->len > 0)
3923
3925}
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 3721 of file describe.c.

3723{
3724 /* relkinds for which we support tablespaces */
3725 if (relkind == RELKIND_RELATION ||
3726 relkind == RELKIND_MATVIEW ||
3727 relkind == RELKIND_INDEX ||
3728 relkind == RELKIND_PARTITIONED_TABLE ||
3729 relkind == RELKIND_PARTITIONED_INDEX ||
3730 relkind == RELKIND_TOASTVALUE)
3731 {
3732 /*
3733 * We ignore the database default tablespace so that users not using
3734 * tablespaces don't need to know about them.
3735 */
3736 if (tablespace != 0)
3737 {
3738 PGresult *result = NULL;
3740
3742 printfPQExpBuffer(&buf, "/* %s */\n",
3743 _("Get tablespace information for this relation"));
3745 "SELECT spcname FROM pg_catalog.pg_tablespace\n"
3746 "WHERE oid = '%u';", tablespace);
3747 result = PSQLexec(buf.data);
3748 if (!result)
3749 {
3751 return;
3752 }
3753 /* Should always be the case, but.... */
3754 if (PQntuples(result) > 0)
3755 {
3756 if (newline)
3757 {
3758 /* Add the tablespace as a new footer */
3759 printfPQExpBuffer(&buf, _("Tablespace: \"%s\""),
3760 PQgetvalue(result, 0, 0));
3762 }
3763 else
3764 {
3765 /* Append the tablespace to the latest footer */
3766 printfPQExpBuffer(&buf, "%s", cont->footer->data);
3767
3768 /*-------
3769 translator: before this string there's an index description like
3770 '"foo_pkey" PRIMARY KEY, btree (a)' */
3771 appendPQExpBuffer(&buf, _(", tablespace \"%s\""),
3772 PQgetvalue(result, 0, 0));
3774 }
3775 }
3776 PQclear(result);
3778 }
3779 }
3780}
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 6574 of file describe.c.

6576{
6577 PGresult *res;
6578 int count = 0;
6579 int i = 0;
6580
6581 res = PSQLexec(buf->data);
6582 if (!res)
6583 return false;
6584 else
6585 count = PQntuples(res);
6586
6587 if (count > 0)
6589
6590 for (i = 0; i < count; i++)
6591 {
6592 if (as_schema)
6593 printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, 0));
6594 else
6595 {
6596 printfPQExpBuffer(buf, " \"%s.%s\"", PQgetvalue(res, i, 0),
6597 PQgetvalue(res, i, 1));
6598
6599 if (!PQgetisnull(res, i, 3))
6600 appendPQExpBuffer(buf, " (%s)", PQgetvalue(res, i, 3));
6601
6602 if (!PQgetisnull(res, i, 2))
6603 appendPQExpBuffer(buf, " WHERE %s", PQgetvalue(res, i, 2));
6604 }
6605
6607 }
6608
6609 PQclear(res);
6610 return true;
6611}
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:6438
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 4790 of file describe.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

1450{
1452 PGresult *res;
1453 int i;
1454
1456
1457 printfPQExpBuffer(&buf, "/* %s */\n",
1458 _("Get matching relations to describe"));
1460 "SELECT c.oid,\n"
1461 " n.nspname,\n"
1462 " c.relname\n"
1463 "FROM pg_catalog.pg_class c\n"
1464 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n");
1465
1466 if (!showSystem && !pattern)
1467 appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
1468 " AND n.nspname <> 'information_schema'\n");
1469
1470 if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern, false,
1471 "n.nspname", "c.relname", NULL,
1472 "pg_catalog.pg_table_is_visible(c.oid)",
1473 NULL, 3))
1474 {
1476 return false;
1477 }
1478
1479 appendPQExpBufferStr(&buf, "ORDER BY 2, 3;");
1480
1481 res = PSQLexec(buf.data);
1483 if (!res)
1484 return false;
1485
1486 if (PQntuples(res) == 0)
1487 {
1488 if (!pset.quiet)
1489 {
1490 if (pattern)
1491 pg_log_error("Did not find any relation named \"%s\".",
1492 pattern);
1493 else
1494 pg_log_error("Did not find any relations.");
1495 }
1496 PQclear(res);
1497 return false;
1498 }
1499
1500 for (i = 0; i < PQntuples(res); i++)
1501 {
1502 const char *oid;
1503 const char *nspname;
1504 const char *relname;
1505
1506 oid = PQgetvalue(res, i, 0);
1507 nspname = PQgetvalue(res, i, 1);
1508 relname = PQgetvalue(res, i, 2);
1509
1510 if (!describeOneTableDetails(nspname, relname, oid, verbose))
1511 {
1512 PQclear(res);
1513 return false;
1514 }
1515 if (cancel_pressed)
1516 {
1517 PQclear(res);
1518 return false;
1519 }
1520 }
1521
1522 PQclear(res);
1523 return true;
1524}
static bool describeOneTableDetails(const char *schemaname, const char *relationname, const char *oid, bool verbose)
Definition describe.c:1534
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')\n"
990 " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n"
991 " ELSE 'No Access'\n"
992 " END as \"%s\""
993 ",\n t.spcname as \"%s\""
994 ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"",
995 gettext_noop("Size"),
996 gettext_noop("Tablespace"),
997 gettext_noop("Description"));
999 "\nFROM pg_catalog.pg_database d\n");
1000 if (verbose)
1002 " JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
1003
1004 if (pattern)
1005 {
1006 if (!validateSQLNamePattern(&buf, pattern, false, false,
1007 NULL, "d.datname", NULL, NULL,
1008 NULL, 1))
1009 {
1011 return false;
1012 }
1013 }
1014
1015 appendPQExpBufferStr(&buf, "ORDER BY 1;");
1016 res = PSQLexec(buf.data);
1018 if (!res)
1019 return false;
1020
1021 myopt.title = _("List of databases");
1022 myopt.translate_header = true;
1023
1024 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1025
1026 PQclear(res);
1027 return true;
1028}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

6443{
6445 int dotcnt;
6446 bool added;
6447
6452 if (added_clause != NULL)
6454
6455 if (dotcnt >= maxparts)
6456 {
6457 pg_log_error("improper qualified name (too many dotted names): %s",
6458 pattern);
6459 goto error_return;
6460 }
6461
6462 if (maxparts > 1 && dotcnt == maxparts - 1)
6463 {
6464 if (PQdb(pset.db) == NULL)
6465 {
6466 pg_log_error("You are currently not connected to a database.");
6467 goto error_return;
6468 }
6469 if (strcmp(PQdb(pset.db), dbbuf.data) != 0)
6470 {
6471 pg_log_error("cross-database references are not implemented: %s",
6472 pattern);
6473 goto error_return;
6474 }
6475 }
6477 return true;
6478
6481 return false;
6482}
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().