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

4075{
4076 if (buf->len > 0)
4078
4080}
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 3871 of file describe.c.

3873{
3874 /* relkinds for which we support tablespaces */
3875 if (relkind == RELKIND_RELATION ||
3876 relkind == RELKIND_MATVIEW ||
3877 relkind == RELKIND_INDEX ||
3878 relkind == RELKIND_PARTITIONED_TABLE ||
3879 relkind == RELKIND_PARTITIONED_INDEX ||
3880 relkind == RELKIND_TOASTVALUE)
3881 {
3882 /*
3883 * We ignore the database default tablespace so that users not using
3884 * tablespaces don't need to know about them.
3885 */
3886 if (tablespace != 0)
3887 {
3888 PGresult *result = NULL;
3890
3892 printfPQExpBuffer(&buf, "/* %s */\n",
3893 _("Get tablespace information for this relation"));
3895 "SELECT spcname FROM pg_catalog.pg_tablespace\n"
3896 "WHERE oid = '%u';", tablespace);
3897 result = PSQLexec(buf.data);
3898 if (!result)
3899 {
3901 return;
3902 }
3903 /* Should always be the case, but.... */
3904 if (PQntuples(result) > 0)
3905 {
3906 if (newline)
3907 {
3908 /* Add the tablespace as a new footer */
3909 printfPQExpBuffer(&buf, _("Tablespace: \"%s\""),
3910 PQgetvalue(result, 0, 0));
3912 }
3913 else
3914 {
3915 /* Append the tablespace to the latest footer */
3916 printfPQExpBuffer(&buf, "%s", cont->footer->data);
3917
3918 /*-------
3919 translator: before this string there's an index description like
3920 '"foo_pkey" PRIMARY KEY, btree (a)' */
3921 appendPQExpBuffer(&buf, _(", tablespace \"%s\""),
3922 PQgetvalue(result, 0, 0));
3924 }
3925 }
3926 PQclear(result);
3928 }
3929 }
3930}
PGresult * PSQLexec(const char *query)
Definition common.c:655
uint32 result
#define _(x)
Definition elog.c:95
void printTableSetFooter(printTableContent *const content, const char *footer)
Definition print.c:3354
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition print.c:3329
#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 6777 of file describe.c.

6779{
6780 PGresult *res;
6781 int count = 0;
6782 int i = 0;
6783
6784 res = PSQLexec(buf->data);
6785 if (!res)
6786 return false;
6787 else
6788 count = PQntuples(res);
6789
6790 if (count > 0)
6792
6793 for (i = 0; i < count; i++)
6794 {
6795 if (as_schema)
6796 printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, 0));
6797 else
6798 {
6799 printfPQExpBuffer(buf, " \"%s.%s\"", PQgetvalue(res, i, 0),
6800 PQgetvalue(res, i, 1));
6801
6802 if (!PQgetisnull(res, i, 3))
6803 appendPQExpBuffer(buf, " (%s)", PQgetvalue(res, i, 3));
6804
6805 if (!PQgetisnull(res, i, 2))
6806 appendPQExpBuffer(buf, " WHERE %s", PQgetvalue(res, i, 2));
6807 }
6808
6810 }
6811
6812 PQclear(res);
6813 return true;
6814}
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
157 if (pset.sversion < 90600)
158 {
159 char sverbuf[32];
160
161 pg_log_error("The server (version %s) does not support access methods.",
163 sverbuf, sizeof(sverbuf)));
164 return true;
165 }
166
168
169 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching access methods"));
171 "SELECT amname AS \"%s\",\n"
172 " CASE amtype"
173 " WHEN " CppAsString2(AMTYPE_INDEX) " THEN '%s'"
174 " WHEN " CppAsString2(AMTYPE_TABLE) " THEN '%s'"
175 " END AS \"%s\"",
176 gettext_noop("Name"),
177 gettext_noop("Index"),
178 gettext_noop("Table"),
179 gettext_noop("Type"));
180
181 if (verbose)
182 {
184 ",\n amhandler AS \"%s\",\n"
185 " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"",
186 gettext_noop("Handler"),
187 gettext_noop("Description"));
188 }
189
191 "\nFROM pg_catalog.pg_am\n");
192
193 if (!validateSQLNamePattern(&buf, pattern, false, false,
194 NULL, "amname", NULL,
195 NULL,
196 NULL, 1))
197 {
199 return false;
200 }
201
202 appendPQExpBufferStr(&buf, "ORDER BY 1;");
203
204 res = PSQLexec(buf.data);
206 if (!res)
207 return false;
208
209 myopt.title = _("List of access methods");
210 myopt.translate_header = true;
211 myopt.translate_columns = translate_columns;
212 myopt.n_translate_columns = lengthof(translate_columns);
213
214 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
215
216 PQclear(res);
217 return true;
218}
#define gettext_noop(x)
Definition c.h:1285
#define CppAsString2(x)
Definition c.h:506
#define lengthof(array)
Definition c.h:873
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:6631
void printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
Definition print.c:3742
#define pg_log_error(...)
Definition logging.h:106
static int verbose
PsqlSettings pset
Definition startup.c:33
char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)
printQueryOpt popt
Definition settings.h:112
FILE * logfile
Definition settings.h:149
FILE * queryFout
Definition settings.h:105

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

4960{
4962 PGresult *res;
4964
4966
4967 printfPQExpBuffer(&buf, "/* %s */\n",
4968 _("Get matching configuration parameters"));
4970 "SELECT s.name AS \"%s\", "
4971 "pg_catalog.current_setting(s.name) AS \"%s\"",
4972 gettext_noop("Parameter"),
4973 gettext_noop("Value"));
4974
4975 if (verbose)
4976 {
4978 ", s.vartype AS \"%s\", s.context AS \"%s\", ",
4979 gettext_noop("Type"),
4980 gettext_noop("Context"));
4981 if (pset.sversion >= 150000)
4982 printACLColumn(&buf, "p.paracl");
4983 else
4984 appendPQExpBuffer(&buf, "NULL AS \"%s\"",
4985 gettext_noop("Access privileges"));
4986 }
4987
4988 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_settings s\n");
4989
4990 if (verbose && pset.sversion >= 150000)
4992 " LEFT JOIN pg_catalog.pg_parameter_acl p\n"
4993 " ON pg_catalog.lower(s.name) = p.parname\n");
4994
4995 if (pattern)
4996 processSQLNamePattern(pset.db, &buf, pattern,
4997 false, false,
4998 NULL, "pg_catalog.lower(s.name)", NULL,
4999 NULL, NULL, NULL);
5000 else
5001 appendPQExpBufferStr(&buf, "WHERE s.source <> 'default' AND\n"
5002 " s.setting IS DISTINCT FROM s.boot_val\n");
5003
5004 appendPQExpBufferStr(&buf, "ORDER BY 1;");
5005
5006 res = PSQLexec(buf.data);
5008 if (!res)
5009 return false;
5010
5011 if (pattern)
5012 myopt.title = _("List of configuration parameters");
5013 else
5014 myopt.title = _("List of non-default configuration parameters");
5015 myopt.translate_header = true;
5016
5017 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5018
5019 PQclear(res);
5020 return true;
5021}
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition describe.c:7251
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 299 of file describe.c.

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

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

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

References _, add_tablespace_footer(), appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), Assert, atooid, buf, CppAsString2, StringInfoData::data, PQExpBufferData::data, fb(), fmtId(), free, gettext_noop, _psqlSettings::hide_compression, _psqlSettings::hide_tableam, i, initPQExpBuffer(), lengthof, _psqlSettings::logfile, 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(), tmpbuf, printQueryOpt::topt, 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 6106 of file describe.c.

6108{
6110 title;
6111 PGresult *res;
6113
6115
6116 printfPQExpBuffer(&buf, "/* %s */\n", _("Get text search configuration details"));
6118 "SELECT\n"
6119 " ( SELECT t.alias FROM\n"
6120 " pg_catalog.ts_token_type(c.cfgparser) AS t\n"
6121 " WHERE t.tokid = m.maptokentype ) AS \"%s\",\n"
6122 " pg_catalog.btrim(\n"
6123 " ARRAY( SELECT mm.mapdict::pg_catalog.regdictionary\n"
6124 " FROM pg_catalog.pg_ts_config_map AS mm\n"
6125 " WHERE mm.mapcfg = m.mapcfg AND mm.maptokentype = m.maptokentype\n"
6126 " ORDER BY mapcfg, maptokentype, mapseqno\n"
6127 " ) :: pg_catalog.text,\n"
6128 " '{}') AS \"%s\"\n"
6129 "FROM pg_catalog.pg_ts_config AS c, pg_catalog.pg_ts_config_map AS m\n"
6130 "WHERE c.oid = '%s' AND m.mapcfg = c.oid\n"
6131 "GROUP BY m.mapcfg, m.maptokentype, c.cfgparser\n"
6132 "ORDER BY 1;",
6133 gettext_noop("Token"),
6134 gettext_noop("Dictionaries"),
6135 oid);
6136
6137 res = PSQLexec(buf.data);
6139 if (!res)
6140 return false;
6141
6142 initPQExpBuffer(&title);
6143
6144 if (nspname)
6145 appendPQExpBuffer(&title, _("Text search configuration \"%s.%s\""),
6146 nspname, cfgname);
6147 else
6148 appendPQExpBuffer(&title, _("Text search configuration \"%s\""),
6149 cfgname);
6150
6151 if (pnspname)
6152 appendPQExpBuffer(&title, _("\nParser: \"%s.%s\""),
6153 pnspname, prsname);
6154 else
6155 appendPQExpBuffer(&title, _("\nParser: \"%s\""),
6156 prsname);
6157
6158 myopt.title = title.data;
6159 myopt.footers = NULL;
6160 myopt.topt.default_footer = false;
6161 myopt.translate_header = true;
6162
6163 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6164
6165 termPQExpBuffer(&title);
6166
6167 PQclear(res);
6168 return true;
6169}

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

5717{
5719 PGresult *res;
5720 PQExpBufferData title;
5722 static const bool translate_columns[] = {true, false, false};
5723
5725
5726 printfPQExpBuffer(&buf, "/* %s */\n", _("Get text search parser details"));
5728 "SELECT '%s' AS \"%s\",\n"
5729 " p.prsstart::pg_catalog.regproc AS \"%s\",\n"
5730 " pg_catalog.obj_description(p.prsstart, 'pg_proc') as \"%s\"\n"
5731 " FROM pg_catalog.pg_ts_parser p\n"
5732 " WHERE p.oid = '%s'\n"
5733 "UNION ALL\n"
5734 "SELECT '%s',\n"
5735 " p.prstoken::pg_catalog.regproc,\n"
5736 " pg_catalog.obj_description(p.prstoken, 'pg_proc')\n"
5737 " FROM pg_catalog.pg_ts_parser p\n"
5738 " WHERE p.oid = '%s'\n"
5739 "UNION ALL\n"
5740 "SELECT '%s',\n"
5741 " p.prsend::pg_catalog.regproc,\n"
5742 " pg_catalog.obj_description(p.prsend, 'pg_proc')\n"
5743 " FROM pg_catalog.pg_ts_parser p\n"
5744 " WHERE p.oid = '%s'\n"
5745 "UNION ALL\n"
5746 "SELECT '%s',\n"
5747 " p.prsheadline::pg_catalog.regproc,\n"
5748 " pg_catalog.obj_description(p.prsheadline, 'pg_proc')\n"
5749 " FROM pg_catalog.pg_ts_parser p\n"
5750 " WHERE p.oid = '%s'\n"
5751 "UNION ALL\n"
5752 "SELECT '%s',\n"
5753 " p.prslextype::pg_catalog.regproc,\n"
5754 " pg_catalog.obj_description(p.prslextype, 'pg_proc')\n"
5755 " FROM pg_catalog.pg_ts_parser p\n"
5756 " WHERE p.oid = '%s';",
5757 gettext_noop("Start parse"),
5758 gettext_noop("Method"),
5759 gettext_noop("Function"),
5760 gettext_noop("Description"),
5761 oid,
5762 gettext_noop("Get next token"),
5763 oid,
5764 gettext_noop("End parse"),
5765 oid,
5766 gettext_noop("Get headline"),
5767 oid,
5768 gettext_noop("Get token types"),
5769 oid);
5770
5771 res = PSQLexec(buf.data);
5773 if (!res)
5774 return false;
5775
5776 initPQExpBuffer(&title);
5777 if (nspname)
5778 printfPQExpBuffer(&title, _("Text search parser \"%s.%s\""),
5779 nspname, prsname);
5780 else
5781 printfPQExpBuffer(&title, _("Text search parser \"%s\""), prsname);
5782 myopt.title = title.data;
5783 myopt.footers = NULL;
5784 myopt.topt.default_footer = false;
5785 myopt.translate_header = true;
5786 myopt.translate_columns = translate_columns;
5787 myopt.n_translate_columns = lengthof(translate_columns);
5788
5789 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5790
5791 PQclear(res);
5792
5794
5795 printfPQExpBuffer(&buf, "/* %s */\n",
5796 _("Get text search parser token types"));
5798 "SELECT t.alias as \"%s\",\n"
5799 " t.description as \"%s\"\n"
5800 "FROM pg_catalog.ts_token_type( '%s'::pg_catalog.oid ) as t\n"
5801 "ORDER BY 1;",
5802 gettext_noop("Token name"),
5803 gettext_noop("Description"),
5804 oid);
5805
5806 res = PSQLexec(buf.data);
5808 if (!res)
5809 {
5810 termPQExpBuffer(&title);
5811 return false;
5812 }
5813
5814 if (nspname)
5815 printfPQExpBuffer(&title, _("Token types for parser \"%s.%s\""),
5816 nspname, prsname);
5817 else
5818 printfPQExpBuffer(&title, _("Token types for parser \"%s\""), prsname);
5819 myopt.title = title.data;
5820 myopt.footers = NULL;
5821 myopt.topt.default_footer = true;
5822 myopt.translate_header = true;
5823 myopt.translate_columns = NULL;
5824 myopt.n_translate_columns = 0;
5825
5826 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5827
5828 termPQExpBuffer(&title);
5829 PQclear(res);
5830 return true;
5831}

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

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

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

6824{
6826 int i;
6827 PGresult *res;
6828 bool has_pubtruncate;
6829 bool has_pubgencols;
6830 bool has_pubviaroot;
6831 bool has_pubsequence;
6832 int ncols = 6;
6833 int nrows = 1;
6834
6835 PQExpBufferData title;
6837
6838 if (pset.sversion < 100000)
6839 {
6840 char sverbuf[32];
6841
6842 pg_log_error("The server (version %s) does not support publications.",
6844 sverbuf, sizeof(sverbuf)));
6845 return true;
6846 }
6847
6848 has_pubsequence = (pset.sversion >= 190000);
6849 has_pubtruncate = (pset.sversion >= 110000);
6850 has_pubgencols = (pset.sversion >= 180000);
6851 has_pubviaroot = (pset.sversion >= 130000);
6852
6854
6855 printfPQExpBuffer(&buf, "/* %s */\n", _("Get details about matching publications"));
6857 "SELECT oid, pubname,\n"
6858 " pg_catalog.pg_get_userbyid(pubowner) AS owner,\n"
6859 " puballtables");
6860
6861 if (has_pubsequence)
6863 ", puballsequences");
6864 else
6866 ", false AS puballsequences");
6867
6869 ", pubinsert, pubupdate, pubdelete");
6870
6871 if (has_pubtruncate)
6873 ", pubtruncate");
6874 else
6876 ", false AS pubtruncate");
6877
6878 if (has_pubgencols)
6880 ", (CASE pubgencols\n"
6881 " WHEN '%c' THEN 'none'\n"
6882 " WHEN '%c' THEN 'stored'\n"
6883 " END) AS \"%s\"\n",
6886 gettext_noop("Generated columns"));
6887 else
6889 ", 'none' AS pubgencols");
6890
6891 if (has_pubviaroot)
6893 ", pubviaroot");
6894 else
6896 ", false AS pubviaroot");
6897
6899 ", pg_catalog.obj_description(oid, 'pg_publication')");
6900
6902 "\nFROM pg_catalog.pg_publication\n");
6903
6904 if (!validateSQLNamePattern(&buf, pattern, false, false,
6905 NULL, "pubname", NULL,
6906 NULL,
6907 NULL, 1))
6908 {
6910 return false;
6911 }
6912
6913 appendPQExpBufferStr(&buf, "ORDER BY 2;");
6914
6915 res = PSQLexec(buf.data);
6916 if (!res)
6917 {
6919 return false;
6920 }
6921
6922 if (PQntuples(res) == 0)
6923 {
6924 if (!pset.quiet)
6925 {
6926 if (pattern)
6927 pg_log_error("Did not find any publication named \"%s\".",
6928 pattern);
6929 else
6930 pg_log_error("Did not find any publications.");
6931 }
6932
6934 PQclear(res);
6935 return false;
6936 }
6937
6938 if (has_pubsequence)
6939 ncols++;
6940 if (has_pubtruncate)
6941 ncols++;
6942 if (has_pubgencols)
6943 ncols++;
6944 if (has_pubviaroot)
6945 ncols++;
6946
6947 for (i = 0; i < PQntuples(res); i++)
6948 {
6949 const char align = 'l';
6950 char *pubid = PQgetvalue(res, i, 0);
6951 char *pubname = PQgetvalue(res, i, 1);
6952 bool puballtables = strcmp(PQgetvalue(res, i, 3), "t") == 0;
6954
6955 initPQExpBuffer(&title);
6956 printfPQExpBuffer(&title, _("Publication %s"), pubname);
6957 printTableInit(&cont, &myopt, title.data, ncols, nrows);
6958
6959 printTableAddHeader(&cont, gettext_noop("Owner"), true, align);
6960 printTableAddHeader(&cont, gettext_noop("All tables"), true, align);
6961 if (has_pubsequence)
6962 printTableAddHeader(&cont, gettext_noop("All sequences"), true, align);
6963 printTableAddHeader(&cont, gettext_noop("Inserts"), true, align);
6964 printTableAddHeader(&cont, gettext_noop("Updates"), true, align);
6965 printTableAddHeader(&cont, gettext_noop("Deletes"), true, align);
6966 if (has_pubtruncate)
6967 printTableAddHeader(&cont, gettext_noop("Truncates"), true, align);
6968 if (has_pubgencols)
6969 printTableAddHeader(&cont, gettext_noop("Generated columns"), true, align);
6970 if (has_pubviaroot)
6971 printTableAddHeader(&cont, gettext_noop("Via root"), true, align);
6972 printTableAddHeader(&cont, gettext_noop("Description"), true, align);
6973
6974 printTableAddCell(&cont, PQgetvalue(res, i, 2), false, false);
6975 printTableAddCell(&cont, PQgetvalue(res, i, 3), false, false);
6976 if (has_pubsequence)
6977 printTableAddCell(&cont, PQgetvalue(res, i, 4), false, false);
6978 printTableAddCell(&cont, PQgetvalue(res, i, 5), false, false);
6979 printTableAddCell(&cont, PQgetvalue(res, i, 6), false, false);
6980 printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false);
6981 if (has_pubtruncate)
6982 printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
6983 if (has_pubgencols)
6984 printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
6985 if (has_pubviaroot)
6986 printTableAddCell(&cont, PQgetvalue(res, i, 10), false, false);
6987 printTableAddCell(&cont, PQgetvalue(res, i, 11), false, false);
6988
6989 if (!puballtables)
6990 {
6991 /* Get the tables for the specified publication */
6992 printfPQExpBuffer(&buf, "/* %s */\n",
6993 _("Get tables published by this publication"));
6994 appendPQExpBuffer(&buf, "SELECT n.nspname, c.relname");
6995 if (pset.sversion >= 150000)
6996 {
6998 ", pg_get_expr(pr.prqual, c.oid)");
7000 ", (CASE WHEN pr.prattrs IS NOT NULL THEN\n"
7001 " pg_catalog.array_to_string("
7002 " ARRAY(SELECT attname\n"
7003 " FROM\n"
7004 " pg_catalog.generate_series(0, pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n"
7005 " pg_catalog.pg_attribute\n"
7006 " WHERE attrelid = c.oid AND attnum = prattrs[s]), ', ')\n"
7007 " ELSE NULL END)");
7008 }
7009 else
7011 ", NULL, NULL");
7013 "\nFROM pg_catalog.pg_class c,\n"
7014 " pg_catalog.pg_namespace n,\n"
7015 " pg_catalog.pg_publication_rel pr\n"
7016 "WHERE c.relnamespace = n.oid\n"
7017 " AND c.oid = pr.prrelid\n"
7018 " AND pr.prpubid = '%s'\n", pubid);
7019
7020 if (pset.sversion >= 190000)
7021 appendPQExpBuffer(&buf, " AND NOT pr.prexcept\n");
7022
7023 appendPQExpBuffer(&buf, "ORDER BY 1,2");
7024 if (!addFooterToPublicationDesc(&buf, _("Tables:"), false, &cont))
7025 goto error_return;
7026
7027 if (pset.sversion >= 150000)
7028 {
7029 /* Get the schemas for the specified publication */
7030 printfPQExpBuffer(&buf, "/* %s */\n",
7031 _("Get schemas published by this publication"));
7033 "SELECT n.nspname\n"
7034 "FROM pg_catalog.pg_namespace n\n"
7035 " JOIN pg_catalog.pg_publication_namespace pn ON n.oid = pn.pnnspid\n"
7036 "WHERE pn.pnpubid = '%s'\n"
7037 "ORDER BY 1", pubid);
7038 if (!addFooterToPublicationDesc(&buf, _("Tables from schemas:"),
7039 true, &cont))
7040 goto error_return;
7041 }
7042 }
7043 else
7044 {
7045 if (pset.sversion >= 190000)
7046 {
7047 /* Get tables in the EXCEPT clause for this publication */
7048 printfPQExpBuffer(&buf, "/* %s */\n",
7049 _("Get tables excluded by this publication"));
7051 "SELECT n.nspname || '.' || c.relname\n"
7052 "FROM pg_catalog.pg_class c\n"
7053 " JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
7054 " JOIN pg_catalog.pg_publication_rel pr ON c.oid = pr.prrelid\n"
7055 "WHERE pr.prpubid = '%s' AND pr.prexcept\n"
7056 "ORDER BY 1", pubid);
7057 if (!addFooterToPublicationDesc(&buf, _("Except tables:"),
7058 true, &cont))
7059 goto error_return;
7060 }
7061 }
7062
7065
7066 termPQExpBuffer(&title);
7067 }
7068
7070 PQclear(res);
7071
7072 return true;
7073
7076 PQclear(res);
7078 termPQExpBuffer(&title);
7079 return false;
7080}
static bool addFooterToPublicationDesc(PQExpBuffer buf, const char *footermsg, bool as_schema, printTableContent *const cont)
Definition describe.c:6777

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

Referenced by exec_command_d().

◆ describeRoleGrants()

bool describeRoleGrants ( const char pattern,
bool  showSystem 
)

Definition at line 4156 of file describe.c.

4157{
4159 PGresult *res;
4161
4163 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching role grants"));
4165 "SELECT m.rolname AS \"%s\", r.rolname AS \"%s\",\n"
4166 " pg_catalog.concat_ws(', ',\n",
4167 gettext_noop("Role name"),
4168 gettext_noop("Member of"));
4169
4170 if (pset.sversion >= 160000)
4172 " CASE WHEN pam.admin_option THEN 'ADMIN' END,\n"
4173 " CASE WHEN pam.inherit_option THEN 'INHERIT' END,\n"
4174 " CASE WHEN pam.set_option THEN 'SET' END\n");
4175 else
4177 " CASE WHEN pam.admin_option THEN 'ADMIN' END,\n"
4178 " CASE WHEN m.rolinherit THEN 'INHERIT' END,\n"
4179 " 'SET'\n");
4180
4182 " ) AS \"%s\",\n"
4183 " g.rolname AS \"%s\"\n",
4184 gettext_noop("Options"),
4185 gettext_noop("Grantor"));
4186
4188 "FROM pg_catalog.pg_roles m\n"
4189 " JOIN pg_catalog.pg_auth_members pam ON (pam.member = m.oid)\n"
4190 " LEFT JOIN pg_catalog.pg_roles r ON (pam.roleid = r.oid)\n"
4191 " LEFT JOIN pg_catalog.pg_roles g ON (pam.grantor = g.oid)\n");
4192
4193 if (!showSystem && !pattern)
4194 appendPQExpBufferStr(&buf, "WHERE m.rolname !~ '^pg_'\n");
4195
4196 if (!validateSQLNamePattern(&buf, pattern, false, false,
4197 NULL, "m.rolname", NULL, NULL,
4198 NULL, 1))
4199 {
4201 return false;
4202 }
4203
4204 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;\n");
4205
4206 res = PSQLexec(buf.data);
4208 if (!res)
4209 return false;
4210
4211 myopt.title = _("List of role grants");
4212 myopt.translate_header = true;
4213
4214 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4215
4216 PQclear(res);
4217 return true;
4218}

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

3939{
3941 PGresult *res;
3944 int ncols = 2;
3945 int nrows = 0;
3946 int i;
3947 int conns;
3948 const char align = 'l';
3949 char **attr;
3950
3951 myopt.default_footer = false;
3952
3954
3955 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching roles"));
3957 "SELECT r.rolname, r.rolsuper, r.rolinherit,\n"
3958 " r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,\n"
3959 " r.rolconnlimit, r.rolvaliduntil");
3960
3961 if (verbose)
3962 {
3963 appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
3964 ncols++;
3965 }
3966 appendPQExpBufferStr(&buf, "\n, r.rolreplication");
3967
3968 if (pset.sversion >= 90500)
3969 {
3970 appendPQExpBufferStr(&buf, "\n, r.rolbypassrls");
3971 }
3972
3973 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_roles r\n");
3974
3975 if (!showSystem && !pattern)
3976 appendPQExpBufferStr(&buf, "WHERE r.rolname !~ '^pg_'\n");
3977
3978 if (!validateSQLNamePattern(&buf, pattern, false, false,
3979 NULL, "r.rolname", NULL, NULL,
3980 NULL, 1))
3981 {
3983 return false;
3984 }
3985
3986 appendPQExpBufferStr(&buf, "ORDER BY 1;");
3987
3988 res = PSQLexec(buf.data);
3989 if (!res)
3990 return false;
3991
3992 nrows = PQntuples(res);
3993 attr = pg_malloc0_array(char *, nrows + 1);
3994
3995 printTableInit(&cont, &myopt, _("List of roles"), ncols, nrows);
3996
3997 printTableAddHeader(&cont, gettext_noop("Role name"), true, align);
3998 printTableAddHeader(&cont, gettext_noop("Attributes"), true, align);
3999
4000 if (verbose)
4001 printTableAddHeader(&cont, gettext_noop("Description"), true, align);
4002
4003 for (i = 0; i < nrows; i++)
4004 {
4005 printTableAddCell(&cont, PQgetvalue(res, i, 0), false, false);
4006
4008 if (strcmp(PQgetvalue(res, i, 1), "t") == 0)
4009 add_role_attribute(&buf, _("Superuser"));
4010
4011 if (strcmp(PQgetvalue(res, i, 2), "t") != 0)
4012 add_role_attribute(&buf, _("No inheritance"));
4013
4014 if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
4015 add_role_attribute(&buf, _("Create role"));
4016
4017 if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
4018 add_role_attribute(&buf, _("Create DB"));
4019
4020 if (strcmp(PQgetvalue(res, i, 5), "t") != 0)
4021 add_role_attribute(&buf, _("Cannot login"));
4022
4023 if (strcmp(PQgetvalue(res, i, (verbose ? 9 : 8)), "t") == 0)
4024 add_role_attribute(&buf, _("Replication"));
4025
4026 if (pset.sversion >= 90500)
4027 if (strcmp(PQgetvalue(res, i, (verbose ? 10 : 9)), "t") == 0)
4028 add_role_attribute(&buf, _("Bypass RLS"));
4029
4030 conns = atoi(PQgetvalue(res, i, 6));
4031 if (conns >= 0)
4032 {
4033 if (buf.len > 0)
4034 appendPQExpBufferChar(&buf, '\n');
4035
4036 if (conns == 0)
4037 appendPQExpBufferStr(&buf, _("No connections"));
4038 else
4039 appendPQExpBuffer(&buf, ngettext("%d connection",
4040 "%d connections",
4041 conns),
4042 conns);
4043 }
4044
4045 if (strcmp(PQgetvalue(res, i, 7), "") != 0)
4046 {
4047 if (buf.len > 0)
4048 appendPQExpBufferChar(&buf, '\n');
4049 appendPQExpBufferStr(&buf, _("Password valid until "));
4051 }
4052
4053 attr[i] = pg_strdup(buf.data);
4054
4055 printTableAddCell(&cont, attr[i], false, false);
4056
4057 if (verbose)
4058 printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
4059 }
4061
4064
4065 for (i = 0; i < nrows; i++)
4066 free(attr[i]);
4067 free(attr);
4068
4069 PQclear(res);
4070 return true;
4071}
#define ngettext(s, p, n)
Definition c.h:1270
static void add_role_attribute(PQExpBuffer buf, const char *const str)
Definition describe.c:4074
#define pg_malloc0_array(type, count)
Definition fe_memutils.h:57
static IsoConnInfo * conns

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

Referenced by exec_command_d().

◆ describeSubscriptions()

bool describeSubscriptions ( const char pattern,
bool  verbose 
)

Definition at line 7089 of file describe.c.

7090{
7092 PGresult *res;
7094 static const bool translate_columns[] = {false, false, false, false,
7095 false, false, false, false, false, false, false, false, false, false,
7096 false, false, false, false, false, false, false};
7097
7098 if (pset.sversion < 100000)
7099 {
7100 char sverbuf[32];
7101
7102 pg_log_error("The server (version %s) does not support subscriptions.",
7104 sverbuf, sizeof(sverbuf)));
7105 return true;
7106 }
7107
7109
7110 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching subscriptions"));
7112 "SELECT subname AS \"%s\"\n"
7113 ", pg_catalog.pg_get_userbyid(subowner) AS \"%s\"\n"
7114 ", subenabled AS \"%s\"\n"
7115 ", subpublications AS \"%s\"\n",
7116 gettext_noop("Name"),
7117 gettext_noop("Owner"),
7118 gettext_noop("Enabled"),
7119 gettext_noop("Publication"));
7120
7121 if (verbose)
7122 {
7123 /* Binary mode and streaming are only supported in v14 and higher */
7124 if (pset.sversion >= 140000)
7125 {
7127 ", subbinary AS \"%s\"\n",
7128 gettext_noop("Binary"));
7129
7130 if (pset.sversion >= 160000)
7132 ", (CASE substream\n"
7133 " WHEN " CppAsString2(LOGICALREP_STREAM_OFF) " THEN 'off'\n"
7134 " WHEN " CppAsString2(LOGICALREP_STREAM_ON) " THEN 'on'\n"
7135 " WHEN " CppAsString2(LOGICALREP_STREAM_PARALLEL) " THEN 'parallel'\n"
7136 " END) AS \"%s\"\n",
7137 gettext_noop("Streaming"));
7138 else
7140 ", substream AS \"%s\"\n",
7141 gettext_noop("Streaming"));
7142 }
7143
7144 /* Two_phase and disable_on_error are only supported in v15 and higher */
7145 if (pset.sversion >= 150000)
7147 ", subtwophasestate AS \"%s\"\n"
7148 ", subdisableonerr AS \"%s\"\n",
7149 gettext_noop("Two-phase commit"),
7150 gettext_noop("Disable on error"));
7151
7152 if (pset.sversion >= 160000)
7154 ", suborigin AS \"%s\"\n"
7155 ", subpasswordrequired AS \"%s\"\n"
7156 ", subrunasowner AS \"%s\"\n",
7157 gettext_noop("Origin"),
7158 gettext_noop("Password required"),
7159 gettext_noop("Run as owner?"));
7160
7161 if (pset.sversion >= 170000)
7163 ", subfailover AS \"%s\"\n",
7164 gettext_noop("Failover"));
7165 if (pset.sversion >= 190000)
7166 {
7168 ", (select srvname from pg_foreign_server where oid=subserver) AS \"%s\"\n",
7169 gettext_noop("Server"));
7170
7172 ", subretaindeadtuples AS \"%s\"\n",
7173 gettext_noop("Retain dead tuples"));
7174
7176 ", submaxretention AS \"%s\"\n",
7177 gettext_noop("Max retention duration"));
7178
7180 ", subretentionactive AS \"%s\"\n",
7181 gettext_noop("Retention active"));
7182 }
7183
7185 ", subsynccommit AS \"%s\"\n"
7186 ", subconninfo AS \"%s\"\n",
7187 gettext_noop("Synchronous commit"),
7188 gettext_noop("Conninfo"));
7189
7190 if (pset.sversion >= 190000)
7192 ", subwalrcvtimeout AS \"%s\"\n",
7193 gettext_noop("Receiver timeout"));
7194
7195 /* Skip LSN is only supported in v15 and higher */
7196 if (pset.sversion >= 150000)
7198 ", subskiplsn AS \"%s\"\n",
7199 gettext_noop("Skip LSN"));
7200
7202 ", pg_catalog.obj_description(oid, 'pg_subscription') AS \"%s\"\n",
7203 gettext_noop("Description"));
7204 }
7205
7206 /* Only display subscriptions in current database. */
7208 "FROM pg_catalog.pg_subscription\n"
7209 "WHERE subdbid = (SELECT oid\n"
7210 " FROM pg_catalog.pg_database\n"
7211 " WHERE datname = pg_catalog.current_database())");
7212
7213 if (!validateSQLNamePattern(&buf, pattern, true, false,
7214 NULL, "subname", NULL,
7215 NULL,
7216 NULL, 1))
7217 {
7219 return false;
7220 }
7221
7222 appendPQExpBufferStr(&buf, "ORDER BY 1;");
7223
7224 res = PSQLexec(buf.data);
7226 if (!res)
7227 return false;
7228
7229 myopt.title = _("List of subscriptions");
7230 myopt.translate_header = true;
7231 myopt.translate_columns = translate_columns;
7232 myopt.n_translate_columns = lengthof(translate_columns);
7233
7234 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7235
7236 PQclear(res);
7237 return true;
7238}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, fb(), formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, pg_log_error, _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 1503 of file describe.c.

1504{
1506 PGresult *res;
1507 int i;
1508
1510
1511 printfPQExpBuffer(&buf, "/* %s */\n",
1512 _("Get matching relations to describe"));
1514 "SELECT c.oid,\n"
1515 " n.nspname,\n"
1516 " c.relname\n"
1517 "FROM pg_catalog.pg_class c\n"
1518 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n");
1519
1520 if (!showSystem && !pattern)
1521 appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
1522 " AND n.nspname <> 'information_schema'\n");
1523
1524 if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern, false,
1525 "n.nspname", "c.relname", NULL,
1526 "pg_catalog.pg_table_is_visible(c.oid)",
1527 NULL, 3))
1528 {
1530 return false;
1531 }
1532
1533 appendPQExpBufferStr(&buf, "ORDER BY 2, 3;");
1534
1535 res = PSQLexec(buf.data);
1537 if (!res)
1538 return false;
1539
1540 if (PQntuples(res) == 0)
1541 {
1542 if (!pset.quiet)
1543 {
1544 if (pattern)
1545 pg_log_error("Did not find any relation named \"%s\".",
1546 pattern);
1547 else
1548 pg_log_error("Did not find any relations.");
1549 }
1550 PQclear(res);
1551 return false;
1552 }
1553
1554 for (i = 0; i < PQntuples(res); i++)
1555 {
1556 const char *oid;
1557 const char *nspname;
1558 const char *relname;
1559
1560 oid = PQgetvalue(res, i, 0);
1561 nspname = PQgetvalue(res, i, 1);
1562 relname = PQgetvalue(res, i, 2);
1563
1564 if (!describeOneTableDetails(nspname, relname, oid, verbose))
1565 {
1566 PQclear(res);
1567 return false;
1568 }
1569 if (cancel_pressed)
1570 {
1571 PQclear(res);
1572 return false;
1573 }
1574 }
1575
1576 PQclear(res);
1577 return true;
1578}
static bool describeOneTableDetails(const char *schemaname, const char *relationname, const char *oid, bool verbose)
Definition describe.c:1588
volatile sig_atomic_t cancel_pressed
Definition print.c:48

References _, appendPQExpBuffer(), 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 225 of file describe.c.

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

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

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

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

954{
955 PGresult *res;
958
960
961 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching databases"));
963 "SELECT\n"
964 " d.datname as \"%s\",\n"
965 " pg_catalog.pg_get_userbyid(d.datdba) as \"%s\",\n"
966 " pg_catalog.pg_encoding_to_char(d.encoding) as \"%s\",\n",
967 gettext_noop("Name"),
968 gettext_noop("Owner"),
969 gettext_noop("Encoding"));
970 if (pset.sversion >= 150000)
972 " CASE d.datlocprovider "
973 "WHEN " CppAsString2(COLLPROVIDER_BUILTIN) " THEN 'builtin' "
974 "WHEN " CppAsString2(COLLPROVIDER_LIBC) " THEN 'libc' "
975 "WHEN " CppAsString2(COLLPROVIDER_ICU) " THEN 'icu' "
976 "END AS \"%s\",\n",
977 gettext_noop("Locale Provider"));
978 else
980 " 'libc' AS \"%s\",\n",
981 gettext_noop("Locale Provider"));
983 " d.datcollate as \"%s\",\n"
984 " d.datctype as \"%s\",\n",
985 gettext_noop("Collate"),
986 gettext_noop("Ctype"));
987 if (pset.sversion >= 170000)
989 " d.datlocale as \"%s\",\n",
990 gettext_noop("Locale"));
991 else if (pset.sversion >= 150000)
993 " d.daticulocale as \"%s\",\n",
994 gettext_noop("Locale"));
995 else
997 " NULL as \"%s\",\n",
998 gettext_noop("Locale"));
999 if (pset.sversion >= 160000)
1001 " d.daticurules as \"%s\",\n",
1002 gettext_noop("ICU Rules"));
1003 else
1005 " NULL as \"%s\",\n",
1006 gettext_noop("ICU Rules"));
1008 printACLColumn(&buf, "d.datacl");
1009 if (verbose)
1011 ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n"
1012 " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n"
1013 " ELSE 'No Access'\n"
1014 " END as \"%s\""
1015 ",\n t.spcname as \"%s\""
1016 ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"",
1017 gettext_noop("Size"),
1018 gettext_noop("Tablespace"),
1019 gettext_noop("Description"));
1021 "\nFROM pg_catalog.pg_database d\n");
1022 if (verbose)
1024 " JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
1025
1026 if (pattern)
1027 {
1028 if (!validateSQLNamePattern(&buf, pattern, false, false,
1029 NULL, "d.datname", NULL, NULL,
1030 NULL, 1))
1031 {
1033 return false;
1034 }
1035 }
1036
1037 appendPQExpBufferStr(&buf, "ORDER BY 1;");
1038 res = PSQLexec(buf.data);
1040 if (!res)
1041 return false;
1042
1043 myopt.title = _("List of databases");
1044 myopt.translate_header = true;
1045
1046 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1047
1048 PQclear(res);
1049 return true;
1050}

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

5214{
5216 PGresult *res;
5218 static const bool translate_columns[] = {false, false, false, true, true, false};
5219
5221
5222 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching casts"));
5224 "SELECT pg_catalog.format_type(castsource, NULL) AS \"%s\",\n"
5225 " pg_catalog.format_type(casttarget, NULL) AS \"%s\",\n",
5226 gettext_noop("Source type"),
5227 gettext_noop("Target type"));
5228
5229 /*
5230 * We don't attempt to localize '(binary coercible)' or '(with inout)',
5231 * because there's too much risk of gettext translating a function name
5232 * that happens to match some string in the PO database.
5233 */
5235 " CASE WHEN c.castmethod = '%c' THEN '(binary coercible)'\n"
5236 " WHEN c.castmethod = '%c' THEN '(with inout)'\n"
5237 " ELSE p.proname\n"
5238 " END AS \"%s\",\n",
5241 gettext_noop("Function"));
5242
5244 " CASE WHEN c.castcontext = '%c' THEN '%s'\n"
5245 " WHEN c.castcontext = '%c' THEN '%s'\n"
5246 " ELSE '%s'\n"
5247 " END AS \"%s\"",
5249 gettext_noop("no"),
5251 gettext_noop("in assignment"),
5252 gettext_noop("yes"),
5253 gettext_noop("Implicit?"));
5254
5255 if (verbose)
5257 ",\n CASE WHEN p.proleakproof THEN '%s'\n"
5258 " ELSE '%s'\n"
5259 " END AS \"%s\",\n"
5260 " d.description AS \"%s\"",
5261 gettext_noop("yes"),
5262 gettext_noop("no"),
5263 gettext_noop("Leakproof?"),
5264 gettext_noop("Description"));
5265
5266 /*
5267 * We need a left join to pg_proc for binary casts; the others are just
5268 * paranoia.
5269 */
5271 "\nFROM pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p\n"
5272 " ON c.castfunc = p.oid\n"
5273 " LEFT JOIN pg_catalog.pg_type ts\n"
5274 " ON c.castsource = ts.oid\n"
5275 " LEFT JOIN pg_catalog.pg_namespace ns\n"
5276 " ON ns.oid = ts.typnamespace\n"
5277 " LEFT JOIN pg_catalog.pg_type tt\n"
5278 " ON c.casttarget = tt.oid\n"
5279 " LEFT JOIN pg_catalog.pg_namespace nt\n"
5280 " ON nt.oid = tt.typnamespace\n");
5281
5282 if (verbose)
5284 " LEFT JOIN pg_catalog.pg_description d\n"
5285 " ON d.classoid = c.tableoid AND d.objoid = "
5286 "c.oid AND d.objsubid = 0\n");
5287
5288 appendPQExpBufferStr(&buf, "WHERE ( (true");
5289
5290 /*
5291 * Match name pattern against either internal or external name of either
5292 * castsource or casttarget
5293 */
5294 if (!validateSQLNamePattern(&buf, pattern, true, false,
5295 "ns.nspname", "ts.typname",
5296 "pg_catalog.format_type(ts.oid, NULL)",
5297 "pg_catalog.pg_type_is_visible(ts.oid)",
5298 NULL, 3))
5299 goto error_return;
5300
5301 appendPQExpBufferStr(&buf, ") OR (true");
5302
5303 if (!validateSQLNamePattern(&buf, pattern, true, false,
5304 "nt.nspname", "tt.typname",
5305 "pg_catalog.format_type(tt.oid, NULL)",
5306 "pg_catalog.pg_type_is_visible(tt.oid)",
5307 NULL, 3))
5308 goto error_return;
5309
5310 appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;");
5311
5312 res = PSQLexec(buf.data);
5314 if (!res)
5315 return false;
5316
5317 myopt.title = _("List of casts");
5318 myopt.translate_header = true;
5319 myopt.translate_columns = translate_columns;
5320 myopt.n_translate_columns = lengthof(translate_columns);
5321
5322 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5323
5324 PQclear(res);
5325 return true;
5326
5329 return false;
5330}

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

5339{
5341 PGresult *res;
5343 static const bool translate_columns[] = {false, false, false, false, false, false, false, true, false};
5344
5346
5347 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching collations"));
5349 "SELECT\n"
5350 " n.nspname AS \"%s\",\n"
5351 " c.collname AS \"%s\",\n",
5352 gettext_noop("Schema"),
5353 gettext_noop("Name"));
5354
5355 if (pset.sversion >= 100000)
5357 " CASE c.collprovider "
5358 "WHEN " CppAsString2(COLLPROVIDER_DEFAULT) " THEN 'default' "
5359 "WHEN " CppAsString2(COLLPROVIDER_BUILTIN) " THEN 'builtin' "
5360 "WHEN " CppAsString2(COLLPROVIDER_LIBC) " THEN 'libc' "
5361 "WHEN " CppAsString2(COLLPROVIDER_ICU) " THEN 'icu' "
5362 "END AS \"%s\",\n",
5363 gettext_noop("Provider"));
5364 else
5366 " 'libc' AS \"%s\",\n",
5367 gettext_noop("Provider"));
5368
5370 " c.collcollate AS \"%s\",\n"
5371 " c.collctype AS \"%s\",\n",
5372 gettext_noop("Collate"),
5373 gettext_noop("Ctype"));
5374
5375 if (pset.sversion >= 170000)
5377 " c.colllocale AS \"%s\",\n",
5378 gettext_noop("Locale"));
5379 else if (pset.sversion >= 150000)
5381 " c.colliculocale AS \"%s\",\n",
5382 gettext_noop("Locale"));
5383 else
5385 " c.collcollate AS \"%s\",\n",
5386 gettext_noop("Locale"));
5387
5388 if (pset.sversion >= 160000)
5390 " c.collicurules AS \"%s\",\n",
5391 gettext_noop("ICU Rules"));
5392 else
5394 " NULL AS \"%s\",\n",
5395 gettext_noop("ICU Rules"));
5396
5397 if (pset.sversion >= 120000)
5399 " CASE WHEN c.collisdeterministic THEN '%s' ELSE '%s' END AS \"%s\"",
5400 gettext_noop("yes"), gettext_noop("no"),
5401 gettext_noop("Deterministic?"));
5402 else
5404 " '%s' AS \"%s\"",
5405 gettext_noop("yes"),
5406 gettext_noop("Deterministic?"));
5407
5408 if (verbose)
5410 ",\n pg_catalog.obj_description(c.oid, 'pg_collation') AS \"%s\"",
5411 gettext_noop("Description"));
5412
5414 "\nFROM pg_catalog.pg_collation c, pg_catalog.pg_namespace n\n"
5415 "WHERE n.oid = c.collnamespace\n");
5416
5417 if (!showSystem && !pattern)
5418 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
5419 " AND n.nspname <> 'information_schema'\n");
5420
5421 /*
5422 * Hide collations that aren't usable in the current database's encoding.
5423 * If you think to change this, note that pg_collation_is_visible rejects
5424 * unusable collations, so you will need to hack name pattern processing
5425 * somehow to avoid inconsistent behavior.
5426 */
5427 appendPQExpBufferStr(&buf, " AND c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))\n");
5428
5429 if (!validateSQLNamePattern(&buf, pattern, true, false,
5430 "n.nspname", "c.collname", NULL,
5431 "pg_catalog.pg_collation_is_visible(c.oid)",
5432 NULL, 3))
5433 {
5435 return false;
5436 }
5437
5438 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5439
5440 res = PSQLexec(buf.data);
5442 if (!res)
5443 return false;
5444
5445 myopt.title = _("List of collations");
5446 myopt.translate_header = true;
5447 myopt.translate_columns = translate_columns;
5448 myopt.n_translate_columns = lengthof(translate_columns);
5449
5450 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5451
5452 PQclear(res);
5453 return true;
5454}

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

4878{
4880 PGresult *res;
4882 static const bool translate_columns[] =
4883 {false, false, false, false, true, false};
4884
4886
4887 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching conversions"));
4889 "SELECT n.nspname AS \"%s\",\n"
4890 " c.conname AS \"%s\",\n"
4891 " pg_catalog.pg_encoding_to_char(c.conforencoding) AS \"%s\",\n"
4892 " pg_catalog.pg_encoding_to_char(c.contoencoding) AS \"%s\",\n"
4893 " CASE WHEN c.condefault THEN '%s'\n"
4894 " ELSE '%s' END AS \"%s\"",
4895 gettext_noop("Schema"),
4896 gettext_noop("Name"),
4897 gettext_noop("Source"),
4898 gettext_noop("Destination"),
4899 gettext_noop("yes"), gettext_noop("no"),
4900 gettext_noop("Default?"));
4901
4902 if (verbose)
4904 ",\n d.description AS \"%s\"",
4905 gettext_noop("Description"));
4906
4908 "\nFROM pg_catalog.pg_conversion c\n"
4909 " JOIN pg_catalog.pg_namespace n "
4910 "ON n.oid = c.connamespace\n");
4911
4912 if (verbose)
4914 "LEFT JOIN pg_catalog.pg_description d "
4915 "ON d.classoid = c.tableoid\n"
4916 " AND d.objoid = c.oid "
4917 "AND d.objsubid = 0\n");
4918
4919 appendPQExpBufferStr(&buf, "WHERE true\n");
4920
4921 if (!showSystem && !pattern)
4922 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4923 " AND n.nspname <> 'information_schema'\n");
4924
4925 if (!validateSQLNamePattern(&buf, pattern, true, false,
4926 "n.nspname", "c.conname", NULL,
4927 "pg_catalog.pg_conversion_is_visible(c.oid)",
4928 NULL, 3))
4929 {
4931 return false;
4932 }
4933
4934 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4935
4936 res = PSQLexec(buf.data);
4938 if (!res)
4939 return false;
4940
4941 myopt.title = _("List of conversions");
4942 myopt.translate_header = true;
4943 myopt.translate_columns = translate_columns;
4944 myopt.n_translate_columns = lengthof(translate_columns);
4945
4946 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4947
4948 PQclear(res);
4949 return true;
4950}

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

4087{
4089 PGresult *res;
4091 bool havewhere;
4092
4094
4095 printfPQExpBuffer(&buf, "/* %s */\n", _("Get per-database and per-role settings"));
4096 appendPQExpBuffer(&buf, "SELECT rolname AS \"%s\", datname AS \"%s\",\n"
4097 "pg_catalog.array_to_string(setconfig, E'\\n') AS \"%s\"\n"
4098 "FROM pg_catalog.pg_db_role_setting s\n"
4099 "LEFT JOIN pg_catalog.pg_database d ON d.oid = setdatabase\n"
4100 "LEFT JOIN pg_catalog.pg_roles r ON r.oid = setrole\n",
4101 gettext_noop("Role"),
4102 gettext_noop("Database"),
4103 gettext_noop("Settings"));
4104 if (!validateSQLNamePattern(&buf, pattern, false, false,
4105 NULL, "r.rolname", NULL, NULL, &havewhere, 1))
4106 goto error_return;
4108 NULL, "d.datname", NULL, NULL,
4109 NULL, 1))
4110 goto error_return;
4111 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4112
4113 res = PSQLexec(buf.data);
4115 if (!res)
4116 return false;
4117
4118 /*
4119 * Most functions in this file are content to print an empty table when
4120 * there are no matching objects. We intentionally deviate from that
4121 * here, but only in !quiet mode, because of the possibility that the user
4122 * is confused about what the two pattern arguments mean.
4123 */
4124 if (PQntuples(res) == 0 && !pset.quiet)
4125 {
4126 if (pattern && pattern2)
4127 pg_log_error("Did not find any settings for role \"%s\" and database \"%s\".",
4128 pattern, pattern2);
4129 else if (pattern)
4130 pg_log_error("Did not find any settings for role \"%s\".",
4131 pattern);
4132 else
4133 pg_log_error("Did not find any settings.");
4134 }
4135 else
4136 {
4137 myopt.title = _("List of settings");
4138 myopt.translate_header = true;
4139
4140 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4141 }
4142
4143 PQclear(res);
4144 return true;
4145
4148 return false;
4149}

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

1228{
1230 PGresult *res;
1232 static const bool translate_columns[] = {false, false, true, false};
1233
1235
1236 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching default ACLs"));
1238 "SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS \"%s\",\n"
1239 " n.nspname AS \"%s\",\n"
1240 " CASE d.defaclobjtype "
1241 " WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s'"
1242 " WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' END AS \"%s\",\n"
1243 " ",
1244 gettext_noop("Owner"),
1245 gettext_noop("Schema"),
1247 gettext_noop("table"),
1249 gettext_noop("sequence"),
1251 gettext_noop("function"),
1253 gettext_noop("type"),
1255 gettext_noop("schema"),
1257 gettext_noop("large object"),
1258 gettext_noop("Type"));
1259
1260 printACLColumn(&buf, "d.defaclacl");
1261
1262 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_default_acl d\n"
1263 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.defaclnamespace\n");
1264
1265 if (!validateSQLNamePattern(&buf, pattern, false, false,
1266 NULL,
1267 "n.nspname",
1268 "pg_catalog.pg_get_userbyid(d.defaclrole)",
1269 NULL,
1270 NULL, 3))
1271 goto error_return;
1272
1273 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
1274
1275 res = PSQLexec(buf.data);
1276 if (!res)
1277 goto error_return;
1278
1279 printfPQExpBuffer(&buf, _("Default access privileges"));
1280 myopt.title = buf.data;
1281 myopt.translate_header = true;
1282 myopt.translate_columns = translate_columns;
1283 myopt.n_translate_columns = lengthof(translate_columns);
1284
1285 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
1286
1288 PQclear(res);
1289 return true;
1290
1293 return false;
1294}

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

4794{
4796 PGresult *res;
4798
4800
4801 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching domains"));
4803 "SELECT n.nspname as \"%s\",\n"
4804 " t.typname as \"%s\",\n"
4805 " pg_catalog.format_type(t.typbasetype, t.typtypmod) as \"%s\",\n"
4806 " (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type bt\n"
4807 " WHERE c.oid = t.typcollation AND bt.oid = t.typbasetype AND t.typcollation <> bt.typcollation) as \"%s\",\n"
4808 " CASE WHEN t.typnotnull THEN 'not null' END as \"%s\",\n"
4809 " t.typdefault as \"%s\",\n"
4810 " pg_catalog.array_to_string(ARRAY(\n"
4811 " 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"
4812 " ), ' ') as \"%s\"",
4813 gettext_noop("Schema"),
4814 gettext_noop("Name"),
4815 gettext_noop("Type"),
4816 gettext_noop("Collation"),
4817 gettext_noop("Nullable"),
4818 gettext_noop("Default"),
4819 gettext_noop("Check"));
4820
4821 if (verbose)
4822 {
4823 appendPQExpBufferStr(&buf, ",\n ");
4824 printACLColumn(&buf, "t.typacl");
4826 ",\n d.description as \"%s\"",
4827 gettext_noop("Description"));
4828 }
4829
4831 "\nFROM pg_catalog.pg_type t\n"
4832 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
4833
4834 if (verbose)
4836 " LEFT JOIN pg_catalog.pg_description d "
4837 "ON d.classoid = t.tableoid AND d.objoid = t.oid "
4838 "AND d.objsubid = 0\n");
4839
4840 appendPQExpBufferStr(&buf, "WHERE t.typtype = 'd'\n");
4841
4842 if (!showSystem && !pattern)
4843 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4844 " AND n.nspname <> 'information_schema'\n");
4845
4846 if (!validateSQLNamePattern(&buf, pattern, true, false,
4847 "n.nspname", "t.typname", NULL,
4848 "pg_catalog.pg_type_is_visible(t.oid)",
4849 NULL, 3))
4850 {
4852 return false;
4853 }
4854
4855 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4856
4857 res = PSQLexec(buf.data);
4859 if (!res)
4860 return false;
4861
4862 myopt.title = _("List of domains");
4863 myopt.translate_header = true;
4864
4865 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4866
4867 PQclear(res);
4868 return true;
4869}

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

5030{
5032 PGresult *res;
5034 static const bool translate_columns[] =
5035 {false, false, false, true, false, false, false};
5036
5037 if (pset.sversion < 90300)
5038 {
5039 char sverbuf[32];
5040
5041 pg_log_error("The server (version %s) does not support event triggers.",
5043 sverbuf, sizeof(sverbuf)));
5044 return true;
5045 }
5046
5048
5049 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching event triggers"));
5051 "SELECT evtname as \"%s\", "
5052 "evtevent as \"%s\", "
5053 "pg_catalog.pg_get_userbyid(e.evtowner) as \"%s\",\n"
5054 " case evtenabled when 'O' then '%s'"
5055 " when 'R' then '%s'"
5056 " when 'A' then '%s'"
5057 " when 'D' then '%s' end as \"%s\",\n"
5058 " e.evtfoid::pg_catalog.regproc as \"%s\", "
5059 "pg_catalog.array_to_string(array(select x"
5060 " from pg_catalog.unnest(evttags) as t(x)), ', ') as \"%s\"",
5061 gettext_noop("Name"),
5062 gettext_noop("Event"),
5063 gettext_noop("Owner"),
5064 gettext_noop("enabled"),
5065 gettext_noop("replica"),
5066 gettext_noop("always"),
5067 gettext_noop("disabled"),
5068 gettext_noop("Enabled"),
5069 gettext_noop("Function"),
5070 gettext_noop("Tags"));
5071 if (verbose)
5073 ",\npg_catalog.obj_description(e.oid, 'pg_event_trigger') as \"%s\"",
5074 gettext_noop("Description"));
5076 "\nFROM pg_catalog.pg_event_trigger e ");
5077
5078 if (!validateSQLNamePattern(&buf, pattern, false, false,
5079 NULL, "evtname", NULL, NULL,
5080 NULL, 1))
5081 {
5083 return false;
5084 }
5085
5086 appendPQExpBufferStr(&buf, "ORDER BY 1");
5087
5088 res = PSQLexec(buf.data);
5090 if (!res)
5091 return false;
5092
5093 myopt.title = _("List of event triggers");
5094 myopt.translate_header = true;
5095 myopt.translate_columns = translate_columns;
5096 myopt.n_translate_columns = lengthof(translate_columns);
5097
5098 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5099
5100 PQclear(res);
5101 return true;
5102}

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

Referenced by exec_command_d().

◆ listExtendedStats()

bool listExtendedStats ( const char pattern,
bool  verbose 
)

Definition at line 5110 of file describe.c.

5111{
5113 PGresult *res;
5115
5116 if (pset.sversion < 100000)
5117 {
5118 char sverbuf[32];
5119
5120 pg_log_error("The server (version %s) does not support extended statistics.",
5122 sverbuf, sizeof(sverbuf)));
5123 return true;
5124 }
5125
5127
5128 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching extended statistics"));
5130 "SELECT \n"
5131 "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text AS \"%s\", \n"
5132 "es.stxname AS \"%s\", \n",
5133 gettext_noop("Schema"),
5134 gettext_noop("Name"));
5135
5136 if (pset.sversion >= 140000)
5138 "pg_catalog.format('%%s FROM %%s', \n"
5139 " pg_catalog.pg_get_statisticsobjdef_columns(es.oid), \n"
5140 " es.stxrelid::pg_catalog.regclass) AS \"%s\"",
5141 gettext_noop("Definition"));
5142 else
5144 "pg_catalog.format('%%s FROM %%s', \n"
5145 " (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(a.attname),', ') \n"
5146 " FROM pg_catalog.unnest(es.stxkeys) s(attnum) \n"
5147 " JOIN pg_catalog.pg_attribute a \n"
5148 " ON (es.stxrelid = a.attrelid \n"
5149 " AND a.attnum = s.attnum \n"
5150 " AND NOT a.attisdropped)), \n"
5151 "es.stxrelid::pg_catalog.regclass) AS \"%s\"",
5152 gettext_noop("Definition"));
5153
5155 ",\nCASE WHEN " CppAsString2(STATS_EXT_NDISTINCT) " = any(es.stxkind) THEN 'defined' \n"
5156 "END AS \"%s\", \n"
5157 "CASE WHEN " CppAsString2(STATS_EXT_DEPENDENCIES) " = any(es.stxkind) THEN 'defined' \n"
5158 "END AS \"%s\"",
5159 gettext_noop("Ndistinct"),
5160 gettext_noop("Dependencies"));
5161
5162 /*
5163 * Include the MCV statistics kind.
5164 */
5165 if (pset.sversion >= 120000)
5166 {
5168 ",\nCASE WHEN " CppAsString2(STATS_EXT_MCV) " = any(es.stxkind) THEN 'defined' \n"
5169 "END AS \"%s\" ",
5170 gettext_noop("MCV"));
5171 }
5172
5173 if (verbose)
5175 ", \npg_catalog.obj_description(oid, 'pg_statistic_ext') AS \"%s\"\n",
5176 gettext_noop("Description"));
5177
5179 " \nFROM pg_catalog.pg_statistic_ext es \n");
5180
5181 if (!validateSQLNamePattern(&buf, pattern,
5182 false, false,
5183 "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text", "es.stxname",
5184 NULL, "pg_catalog.pg_statistics_obj_is_visible(es.oid)",
5185 NULL, 3))
5186 {
5188 return false;
5189 }
5190
5191 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5192
5193 res = PSQLexec(buf.data);
5195 if (!res)
5196 return false;
5197
5198 myopt.title = _("List of extended statistics");
5199 myopt.translate_header = true;
5200
5201 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5202
5203 PQclear(res);
5204 return true;
5205}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, fb(), formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), _psqlSettings::logfile, pg_log_error, _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 6516 of file describe.c.

6517{
6519 PGresult *res;
6520 int i;
6521
6523
6524 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching installed extensions"));
6526 "SELECT e.extname, e.oid\n"
6527 "FROM pg_catalog.pg_extension e\n");
6528
6529 if (!validateSQLNamePattern(&buf, pattern,
6530 false, false,
6531 NULL, "e.extname", NULL,
6532 NULL,
6533 NULL, 1))
6534 {
6536 return false;
6537 }
6538
6539 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6540
6541 res = PSQLexec(buf.data);
6543 if (!res)
6544 return false;
6545
6546 if (PQntuples(res) == 0)
6547 {
6548 if (!pset.quiet)
6549 {
6550 if (pattern)
6551 pg_log_error("Did not find any extension named \"%s\".",
6552 pattern);
6553 else
6554 pg_log_error("Did not find any extensions.");
6555 }
6556 PQclear(res);
6557 return false;
6558 }
6559
6560 for (i = 0; i < PQntuples(res); i++)
6561 {
6562 const char *extname;
6563 const char *oid;
6564
6565 extname = PQgetvalue(res, i, 0);
6566 oid = PQgetvalue(res, i, 1);
6567
6568 if (!listOneExtensionContents(extname, oid))
6569 {
6570 PQclear(res);
6571 return false;
6572 }
6573 if (cancel_pressed)
6574 {
6575 PQclear(res);
6576 return false;
6577 }
6578 }
6579
6580 PQclear(res);
6581 return true;
6582}
static bool listOneExtensionContents(const char *extname, const char *oid)
Definition describe.c:6585

References _, appendPQExpBuffer(), 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 6460 of file describe.c.

6461{
6463 PGresult *res;
6465
6467
6468 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching installed extensions"));
6470 "SELECT e.extname AS \"%s\", "
6471 "e.extversion AS \"%s\", ae.default_version AS \"%s\","
6472 "n.nspname AS \"%s\", d.description AS \"%s\"\n"
6473 "FROM pg_catalog.pg_extension e "
6474 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace "
6475 "LEFT JOIN pg_catalog.pg_description d ON d.objoid = e.oid "
6476 "AND d.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass "
6477 "LEFT JOIN pg_catalog.pg_available_extensions() ae(name, default_version, comment) ON ae.name = e.extname\n",
6478 gettext_noop("Name"),
6479 gettext_noop("Version"),
6480 gettext_noop("Default version"),
6481 gettext_noop("Schema"),
6482 gettext_noop("Description"));
6483
6484 if (!validateSQLNamePattern(&buf, pattern,
6485 false, false,
6486 NULL, "e.extname", NULL,
6487 NULL,
6488 NULL, 1))
6489 {
6491 return false;
6492 }
6493
6494 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6495
6496 res = PSQLexec(buf.data);
6498 if (!res)
6499 return false;
6500
6501 myopt.title = _("List of installed extensions");
6502 myopt.translate_header = true;
6503
6504 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6505
6506 PQclear(res);
6507 return true;
6508}

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

6179{
6181 PGresult *res;
6183
6185
6186 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching foreign-data wrappers"));
6188 "SELECT fdw.fdwname AS \"%s\",\n"
6189 " pg_catalog.pg_get_userbyid(fdw.fdwowner) AS \"%s\",\n"
6190 " fdw.fdwhandler::pg_catalog.regproc AS \"%s\",\n"
6191 " fdw.fdwvalidator::pg_catalog.regproc AS \"%s\"",
6192 gettext_noop("Name"),
6193 gettext_noop("Owner"),
6194 gettext_noop("Handler"),
6195 gettext_noop("Validator"));
6196
6197 if (verbose)
6198 {
6199 appendPQExpBufferStr(&buf, ",\n ");
6200 printACLColumn(&buf, "fdwacl");
6202 ",\n CASE WHEN fdwoptions IS NULL THEN '' ELSE "
6203 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6204 " pg_catalog.quote_ident(option_name) || ' ' || "
6205 " pg_catalog.quote_literal(option_value) FROM "
6206 " pg_catalog.pg_options_to_table(fdwoptions)), ', ') || ')' "
6207 " END AS \"%s\""
6208 ",\n d.description AS \"%s\" ",
6209 gettext_noop("FDW options"),
6210 gettext_noop("Description"));
6211 }
6212
6213 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
6214
6215 if (verbose)
6217 "LEFT JOIN pg_catalog.pg_description d\n"
6218 " ON d.classoid = fdw.tableoid "
6219 "AND d.objoid = fdw.oid AND d.objsubid = 0\n");
6220
6221 if (!validateSQLNamePattern(&buf, pattern, false, false,
6222 NULL, "fdwname", NULL, NULL,
6223 NULL, 1))
6224 {
6226 return false;
6227 }
6228
6229 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6230
6231 res = PSQLexec(buf.data);
6233 if (!res)
6234 return false;
6235
6236 myopt.title = _("List of foreign-data wrappers");
6237 myopt.translate_header = true;
6238
6239 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6240
6241 PQclear(res);
6242 return true;
6243}

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

6252{
6254 PGresult *res;
6256
6258
6259 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching foreign servers"));
6261 "SELECT s.srvname AS \"%s\",\n"
6262 " pg_catalog.pg_get_userbyid(s.srvowner) AS \"%s\",\n"
6263 " f.fdwname AS \"%s\"",
6264 gettext_noop("Name"),
6265 gettext_noop("Owner"),
6266 gettext_noop("Foreign-data wrapper"));
6267
6268 if (verbose)
6269 {
6270 appendPQExpBufferStr(&buf, ",\n ");
6271 printACLColumn(&buf, "s.srvacl");
6273 ",\n"
6274 " s.srvtype AS \"%s\",\n"
6275 " s.srvversion AS \"%s\",\n"
6276 " CASE WHEN srvoptions IS NULL THEN '' ELSE "
6277 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6278 " pg_catalog.quote_ident(option_name) || ' ' || "
6279 " pg_catalog.quote_literal(option_value) FROM "
6280 " pg_catalog.pg_options_to_table(srvoptions)), ', ') || ')' "
6281 " END AS \"%s\",\n"
6282 " d.description AS \"%s\"",
6283 gettext_noop("Type"),
6284 gettext_noop("Version"),
6285 gettext_noop("FDW options"),
6286 gettext_noop("Description"));
6287 }
6288
6290 "\nFROM pg_catalog.pg_foreign_server s\n"
6291 " JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid=s.srvfdw\n");
6292
6293 if (verbose)
6295 "LEFT JOIN pg_catalog.pg_description d\n "
6296 "ON d.classoid = s.tableoid AND d.objoid = s.oid "
6297 "AND d.objsubid = 0\n");
6298
6299 if (!validateSQLNamePattern(&buf, pattern, false, false,
6300 NULL, "s.srvname", NULL, NULL,
6301 NULL, 1))
6302 {
6304 return false;
6305 }
6306
6307 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6308
6309 res = PSQLexec(buf.data);
6311 if (!res)
6312 return false;
6313
6314 myopt.title = _("List of foreign servers");
6315 myopt.translate_header = true;
6316
6317 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6318
6319 PQclear(res);
6320 return true;
6321}

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

6387{
6389 PGresult *res;
6391
6393
6394 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching foreign tables"));
6396 "SELECT n.nspname AS \"%s\",\n"
6397 " c.relname AS \"%s\",\n"
6398 " s.srvname AS \"%s\"",
6399 gettext_noop("Schema"),
6400 gettext_noop("Table"),
6401 gettext_noop("Server"));
6402
6403 if (verbose)
6405 ",\n CASE WHEN ftoptions IS NULL THEN '' ELSE "
6406 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6407 " pg_catalog.quote_ident(option_name) || ' ' || "
6408 " pg_catalog.quote_literal(option_value) FROM "
6409 " pg_catalog.pg_options_to_table(ftoptions)), ', ') || ')' "
6410 " END AS \"%s\",\n"
6411 " d.description AS \"%s\"",
6412 gettext_noop("FDW options"),
6413 gettext_noop("Description"));
6414
6416 "\nFROM pg_catalog.pg_foreign_table ft\n"
6417 " INNER JOIN pg_catalog.pg_class c"
6418 " ON c.oid = ft.ftrelid\n"
6419 " INNER JOIN pg_catalog.pg_namespace n"
6420 " ON n.oid = c.relnamespace\n"
6421 " INNER JOIN pg_catalog.pg_foreign_server s"
6422 " ON s.oid = ft.ftserver\n");
6423 if (verbose)
6425 " LEFT JOIN pg_catalog.pg_description d\n"
6426 " ON d.classoid = c.tableoid AND "
6427 "d.objoid = c.oid AND d.objsubid = 0\n");
6428
6429 if (!validateSQLNamePattern(&buf, pattern, false, false,
6430 "n.nspname", "c.relname", NULL,
6431 "pg_catalog.pg_table_is_visible(c.oid)",
6432 NULL, 3))
6433 {
6435 return false;
6436 }
6437
6438 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
6439
6440 res = PSQLexec(buf.data);
6442 if (!res)
6443 return false;
6444
6445 myopt.title = _("List of foreign tables");
6446 myopt.translate_header = true;
6447
6448 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6449
6450 PQclear(res);
6451 return true;
6452}

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

4717{
4719 PGresult *res;
4721
4723
4724 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching procedural languages"));
4726 "SELECT l.lanname AS \"%s\",\n"
4727 " pg_catalog.pg_get_userbyid(l.lanowner) as \"%s\",\n"
4728 " l.lanpltrusted AS \"%s\"",
4729 gettext_noop("Name"),
4730 gettext_noop("Owner"),
4731 gettext_noop("Trusted"));
4732
4733 if (verbose)
4734 {
4736 ",\n NOT l.lanispl AS \"%s\",\n"
4737 " l.lanplcallfoid::pg_catalog.regprocedure AS \"%s\",\n"
4738 " l.lanvalidator::pg_catalog.regprocedure AS \"%s\",\n "
4739 "l.laninline::pg_catalog.regprocedure AS \"%s\",\n ",
4740 gettext_noop("Internal language"),
4741 gettext_noop("Call handler"),
4742 gettext_noop("Validator"),
4743 gettext_noop("Inline handler"));
4744 printACLColumn(&buf, "l.lanacl");
4745 }
4746
4748 ",\n d.description AS \"%s\""
4749 "\nFROM pg_catalog.pg_language l\n"
4750 "LEFT JOIN pg_catalog.pg_description d\n"
4751 " ON d.classoid = l.tableoid AND d.objoid = l.oid\n"
4752 " AND d.objsubid = 0\n",
4753 gettext_noop("Description"));
4754
4755 if (pattern)
4756 {
4757 if (!validateSQLNamePattern(&buf, pattern, false, false,
4758 NULL, "l.lanname", NULL, NULL,
4759 NULL, 2))
4760 {
4762 return false;
4763 }
4764 }
4765
4766 if (!showSystem && !pattern)
4767 appendPQExpBufferStr(&buf, "WHERE l.lanplcallfoid != 0\n");
4768
4769
4770 appendPQExpBufferStr(&buf, "ORDER BY 1;");
4771
4772 res = PSQLexec(buf.data);
4774 if (!res)
4775 return false;
4776
4777 myopt.title = _("List of languages");
4778 myopt.translate_header = true;
4779
4780 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4781
4782 PQclear(res);
4783 return true;
4784}

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

7661{
7663 PGresult *res;
7665
7667
7668 printfPQExpBuffer(&buf, "/* %s */\n", _("Get large objects"));
7670 "SELECT oid as \"%s\",\n"
7671 " pg_catalog.pg_get_userbyid(lomowner) as \"%s\",\n ",
7672 gettext_noop("ID"),
7673 gettext_noop("Owner"));
7674
7675 if (verbose)
7676 {
7677 printACLColumn(&buf, "lomacl");
7678 appendPQExpBufferStr(&buf, ",\n ");
7679 }
7680
7682 "pg_catalog.obj_description(oid, 'pg_largeobject') as \"%s\"\n"
7683 "FROM pg_catalog.pg_largeobject_metadata\n"
7684 "ORDER BY oid",
7685 gettext_noop("Description"));
7686
7687 res = PSQLexec(buf.data);
7689 if (!res)
7690 return false;
7691
7692 myopt.title = _("Large objects");
7693 myopt.translate_header = true;
7694
7695 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7696
7697 PQclear(res);
7698 return true;
7699}

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

6586{
6588 PGresult *res;
6589 PQExpBufferData title;
6591
6593
6594 printfPQExpBuffer(&buf, "/* %s */\n", _("Get installed extension's contents"));
6596 "SELECT pg_catalog.pg_describe_object(classid, objid, 0) AS \"%s\"\n"
6597 "FROM pg_catalog.pg_depend\n"
6598 "WHERE refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass AND refobjid = '%s' AND deptype = 'e'\n"
6599 "ORDER BY 1;",
6600 gettext_noop("Object description"),
6601 oid);
6602
6603 res = PSQLexec(buf.data);
6605 if (!res)
6606 return false;
6607
6608 initPQExpBuffer(&title);
6609 printfPQExpBuffer(&title, _("Objects in extension \"%s\""), extname);
6610 myopt.title = title.data;
6611 myopt.translate_header = true;
6612
6613 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6614
6615 termPQExpBuffer(&title);
6616 PQclear(res);
6617 return true;
6618}

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

7271{
7273 PGresult *res;
7275 bool have_where = false;
7276 static const bool translate_columns[] = {false, false, false, false, false, false, false};
7277
7279
7280 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching operator classes"));
7282 "SELECT\n"
7283 " am.amname AS \"%s\",\n"
7284 " pg_catalog.format_type(c.opcintype, NULL) AS \"%s\",\n"
7285 " CASE\n"
7286 " WHEN c.opckeytype <> 0 AND c.opckeytype <> c.opcintype\n"
7287 " THEN pg_catalog.format_type(c.opckeytype, NULL)\n"
7288 " ELSE NULL\n"
7289 " END AS \"%s\",\n"
7290 " CASE\n"
7291 " WHEN pg_catalog.pg_opclass_is_visible(c.oid)\n"
7292 " THEN pg_catalog.format('%%I', c.opcname)\n"
7293 " ELSE pg_catalog.format('%%I.%%I', n.nspname, c.opcname)\n"
7294 " END AS \"%s\",\n"
7295 " (CASE WHEN c.opcdefault\n"
7296 " THEN '%s'\n"
7297 " ELSE '%s'\n"
7298 " END) AS \"%s\"",
7299 gettext_noop("AM"),
7300 gettext_noop("Input type"),
7301 gettext_noop("Storage type"),
7302 gettext_noop("Operator class"),
7303 gettext_noop("yes"),
7304 gettext_noop("no"),
7305 gettext_noop("Default?"));
7306 if (verbose)
7308 ",\n CASE\n"
7309 " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
7310 " THEN pg_catalog.format('%%I', of.opfname)\n"
7311 " ELSE pg_catalog.format('%%I.%%I', ofn.nspname, of.opfname)\n"
7312 " END AS \"%s\",\n"
7313 " pg_catalog.pg_get_userbyid(c.opcowner) AS \"%s\"\n",
7314 gettext_noop("Operator family"),
7315 gettext_noop("Owner"));
7317 "\nFROM pg_catalog.pg_opclass c\n"
7318 " LEFT JOIN pg_catalog.pg_am am on am.oid = c.opcmethod\n"
7319 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.opcnamespace\n"
7320 " LEFT JOIN pg_catalog.pg_type t ON t.oid = c.opcintype\n"
7321 " LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n");
7322 if (verbose)
7324 " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = c.opcfamily\n"
7325 " LEFT JOIN pg_catalog.pg_namespace ofn ON ofn.oid = of.opfnamespace\n");
7326
7329 false, false, NULL, "am.amname", NULL, NULL,
7330 &have_where, 1))
7331 goto error_return;
7332 if (type_pattern)
7333 {
7334 /* Match type name pattern against either internal or external name */
7336 "tn.nspname", "t.typname",
7337 "pg_catalog.format_type(t.oid, NULL)",
7338 "pg_catalog.pg_type_is_visible(t.oid)",
7339 NULL, 3))
7340 goto error_return;
7341 }
7342
7343 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
7344 res = PSQLexec(buf.data);
7346 if (!res)
7347 return false;
7348
7349 myopt.title = _("List of operator classes");
7350 myopt.translate_header = true;
7351 myopt.translate_columns = translate_columns;
7352 myopt.n_translate_columns = lengthof(translate_columns);
7353
7354 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7355
7356 PQclear(res);
7357 return true;
7358
7361 return false;
7362}

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

7373{
7375 PGresult *res;
7377 bool have_where = false;
7378 static const bool translate_columns[] = {false, false, false, false};
7379
7381
7382 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching operator families"));
7384 "SELECT\n"
7385 " am.amname AS \"%s\",\n"
7386 " CASE\n"
7387 " WHEN pg_catalog.pg_opfamily_is_visible(f.oid)\n"
7388 " THEN pg_catalog.format('%%I', f.opfname)\n"
7389 " ELSE pg_catalog.format('%%I.%%I', n.nspname, f.opfname)\n"
7390 " END AS \"%s\",\n"
7391 " (SELECT\n"
7392 " pg_catalog.string_agg(pg_catalog.format_type(oc.opcintype, NULL), ', ')\n"
7393 " FROM pg_catalog.pg_opclass oc\n"
7394 " WHERE oc.opcfamily = f.oid) \"%s\"",
7395 gettext_noop("AM"),
7396 gettext_noop("Operator family"),
7397 gettext_noop("Applicable types"));
7398 if (verbose)
7400 ",\n pg_catalog.pg_get_userbyid(f.opfowner) AS \"%s\"\n",
7401 gettext_noop("Owner"));
7403 "\nFROM pg_catalog.pg_opfamily f\n"
7404 " LEFT JOIN pg_catalog.pg_am am on am.oid = f.opfmethod\n"
7405 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = f.opfnamespace\n");
7406
7409 false, false, NULL, "am.amname", NULL, NULL,
7410 &have_where, 1))
7411 goto error_return;
7412 if (type_pattern)
7413 {
7415 " %s EXISTS (\n"
7416 " SELECT 1\n"
7417 " FROM pg_catalog.pg_type t\n"
7418 " JOIN pg_catalog.pg_opclass oc ON oc.opcintype = t.oid\n"
7419 " LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n"
7420 " WHERE oc.opcfamily = f.oid\n",
7421 have_where ? "AND" : "WHERE");
7422 /* Match type name pattern against either internal or external name */
7423 if (!validateSQLNamePattern(&buf, type_pattern, true, false,
7424 "tn.nspname", "t.typname",
7425 "pg_catalog.format_type(t.oid, NULL)",
7426 "pg_catalog.pg_type_is_visible(t.oid)",
7427 NULL, 3))
7428 goto error_return;
7429 appendPQExpBufferStr(&buf, " )\n");
7430 }
7431
7432 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
7433 res = PSQLexec(buf.data);
7435 if (!res)
7436 return false;
7437
7438 myopt.title = _("List of operator families");
7439 myopt.translate_header = true;
7440 myopt.translate_columns = translate_columns;
7441 myopt.n_translate_columns = lengthof(translate_columns);
7442
7443 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7444
7445 PQclear(res);
7446 return true;
7447
7450 return false;
7451}

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

7571{
7573 PGresult *res;
7575 bool have_where = false;
7576 static const bool translate_columns[] = {false, false, false, false, false, false};
7577
7579
7580 printfPQExpBuffer(&buf, "/* %s */\n",
7581 _("Get support functions of matching operator families"));
7583 "SELECT\n"
7584 " am.amname AS \"%s\",\n"
7585 " CASE\n"
7586 " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
7587 " THEN pg_catalog.format('%%I', of.opfname)\n"
7588 " ELSE pg_catalog.format('%%I.%%I', ns.nspname, of.opfname)\n"
7589 " END AS \"%s\",\n"
7590 " pg_catalog.format_type(ap.amproclefttype, NULL) AS \"%s\",\n"
7591 " pg_catalog.format_type(ap.amprocrighttype, NULL) AS \"%s\",\n"
7592 " ap.amprocnum AS \"%s\"\n",
7593 gettext_noop("AM"),
7594 gettext_noop("Operator family"),
7595 gettext_noop("Registered left type"),
7596 gettext_noop("Registered right type"),
7597 gettext_noop("Number"));
7598
7599 if (!verbose)
7601 ", p.proname AS \"%s\"\n",
7602 gettext_noop("Function"));
7603 else
7605 ", ap.amproc::pg_catalog.regprocedure AS \"%s\"\n",
7606 gettext_noop("Function"));
7607
7609 "FROM pg_catalog.pg_amproc ap\n"
7610 " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = ap.amprocfamily\n"
7611 " LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod\n"
7612 " LEFT JOIN pg_catalog.pg_namespace ns ON of.opfnamespace = ns.oid\n"
7613 " LEFT JOIN pg_catalog.pg_proc p ON ap.amproc = p.oid\n");
7614
7616 {
7618 false, false, NULL, "am.amname",
7619 NULL, NULL,
7620 &have_where, 1))
7621 goto error_return;
7622 }
7623 if (family_pattern)
7624 {
7626 "ns.nspname", "of.opfname", NULL, NULL,
7627 NULL, 3))
7628 goto error_return;
7629 }
7630
7631 appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
7632 " ap.amproclefttype = ap.amprocrighttype DESC,\n"
7633 " 3, 4, 5;");
7634
7635 res = PSQLexec(buf.data);
7637 if (!res)
7638 return false;
7639
7640 myopt.title = _("List of support functions of operator families");
7641 myopt.translate_header = true;
7642 myopt.translate_columns = translate_columns;
7643 myopt.n_translate_columns = lengthof(translate_columns);
7644
7645 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7646
7647 PQclear(res);
7648 return true;
7649
7652 return false;
7653}

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

7463{
7465 PGresult *res;
7467 bool have_where = false;
7468
7469 static const bool translate_columns[] = {false, false, false, false, false, false, true};
7470
7472
7473 printfPQExpBuffer(&buf, "/* %s */\n", _("Get operators of matching operator families"));
7475 "SELECT\n"
7476 " am.amname AS \"%s\",\n"
7477 " CASE\n"
7478 " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
7479 " THEN pg_catalog.format('%%I', of.opfname)\n"
7480 " ELSE pg_catalog.format('%%I.%%I', nsf.nspname, of.opfname)\n"
7481 " END AS \"%s\",\n"
7482 " o.amopopr::pg_catalog.regoperator AS \"%s\"\n,"
7483 " o.amopstrategy AS \"%s\",\n"
7484 " CASE o.amoppurpose\n"
7485 " WHEN " CppAsString2(AMOP_ORDER) " THEN '%s'\n"
7486 " WHEN " CppAsString2(AMOP_SEARCH) " THEN '%s'\n"
7487 " END AS \"%s\"\n",
7488 gettext_noop("AM"),
7489 gettext_noop("Operator family"),
7490 gettext_noop("Operator"),
7491 gettext_noop("Strategy"),
7492 gettext_noop("ordering"),
7493 gettext_noop("search"),
7494 gettext_noop("Purpose"));
7495
7496 if (verbose)
7498 ", ofs.opfname AS \"%s\",\n"
7499 " CASE\n"
7500 " WHEN p.proleakproof THEN '%s'\n"
7501 " ELSE '%s'\n"
7502 " END AS \"%s\"\n",
7503 gettext_noop("Sort opfamily"),
7504 gettext_noop("yes"),
7505 gettext_noop("no"),
7506 gettext_noop("Leakproof?"));
7508 "FROM pg_catalog.pg_amop o\n"
7509 " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = o.amopfamily\n"
7510 " LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod AND am.oid = o.amopmethod\n"
7511 " LEFT JOIN pg_catalog.pg_namespace nsf ON of.opfnamespace = nsf.oid\n");
7512 if (verbose)
7514 " LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n"
7515 " LEFT JOIN pg_catalog.pg_operator op ON op.oid = o.amopopr\n"
7516 " LEFT JOIN pg_catalog.pg_proc p ON p.oid = op.oprcode\n");
7517
7519 {
7521 false, false, NULL, "am.amname",
7522 NULL, NULL,
7523 &have_where, 1))
7524 goto error_return;
7525 }
7526
7527 if (family_pattern)
7528 {
7530 "nsf.nspname", "of.opfname", NULL, NULL,
7531 NULL, 3))
7532 goto error_return;
7533 }
7534
7535 appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
7536 " o.amoplefttype = o.amoprighttype DESC,\n"
7537 " pg_catalog.format_type(o.amoplefttype, NULL),\n"
7538 " pg_catalog.format_type(o.amoprighttype, NULL),\n"
7539 " o.amopstrategy;");
7540
7541 res = PSQLexec(buf.data);
7543 if (!res)
7544 return false;
7545
7546 myopt.title = _("List of operators of operator families");
7547 myopt.translate_header = true;
7548 myopt.translate_columns = translate_columns;
7549 myopt.n_translate_columns = lengthof(translate_columns);
7550
7551 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7552
7553 PQclear(res);
7554 return true;
7555
7558 return false;
7559}

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

4505{
4506 bool showTables = strchr(reltypes, 't') != NULL;
4507 bool showIndexes = strchr(reltypes, 'i') != NULL;
4508 bool showNested = strchr(reltypes, 'n') != NULL;
4510 PQExpBufferData title;
4511 PGresult *res;
4513 bool translate_columns[] = {false, false, false, false, false, false, false, false, false, false};
4514 const char *tabletitle;
4515 bool mixed_output = false;
4516
4517 /*
4518 * Note: Declarative table partitioning is only supported as of Pg 10.0.
4519 */
4520 if (pset.sversion < 100000)
4521 {
4522 char sverbuf[32];
4523
4524 pg_log_error("The server (version %s) does not support declarative table partitioning.",
4526 sverbuf, sizeof(sverbuf)));
4527 return true;
4528 }
4529
4530 /* If no relation kind was selected, show them all */
4531 if (!showTables && !showIndexes)
4532 showTables = showIndexes = true;
4533
4534 if (showIndexes && !showTables)
4535 tabletitle = _("List of partitioned indexes"); /* \dPi */
4536 else if (showTables && !showIndexes)
4537 tabletitle = _("List of partitioned tables"); /* \dPt */
4538 else
4539 {
4540 /* show all kinds */
4541 tabletitle = _("List of partitioned relations");
4542 mixed_output = true;
4543 }
4544
4546
4547 printfPQExpBuffer(&buf, "/* %s */\n",
4548 _("Get matching partitioned relations"));
4550 "SELECT n.nspname as \"%s\",\n"
4551 " c.relname as \"%s\",\n"
4552 " pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"",
4553 gettext_noop("Schema"),
4554 gettext_noop("Name"),
4555 gettext_noop("Owner"));
4556
4557 if (mixed_output)
4558 {
4560 ",\n CASE c.relkind"
4561 " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
4562 " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
4563 " END as \"%s\"",
4564 gettext_noop("partitioned table"),
4565 gettext_noop("partitioned index"),
4566 gettext_noop("Type"));
4567
4568 translate_columns[3] = true;
4569 }
4570
4571 if (showNested || pattern)
4573 ",\n inh.inhparent::pg_catalog.regclass as \"%s\"",
4574 gettext_noop("Parent name"));
4575
4576 if (showIndexes)
4578 ",\n c2.oid::pg_catalog.regclass as \"%s\"",
4579 gettext_noop("Table"));
4580
4581 if (verbose)
4582 {
4583 /*
4584 * Table access methods were introduced in v12, and can be set on
4585 * partitioned tables since v17.
4586 */
4587 appendPQExpBuffer(&buf, ",\n am.amname as \"%s\"",
4588 gettext_noop("Access method"));
4589
4590 if (showNested)
4591 {
4593 ",\n s.dps as \"%s\"",
4594 gettext_noop("Leaf partition size"));
4596 ",\n s.tps as \"%s\"",
4597 gettext_noop("Total size"));
4598 }
4599 else
4600 /* Sizes of all partitions are considered in this case. */
4602 ",\n s.tps as \"%s\"",
4603 gettext_noop("Total size"));
4604
4606 ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"",
4607 gettext_noop("Description"));
4608 }
4609
4611 "\nFROM pg_catalog.pg_class c"
4612 "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace");
4613
4614 if (showIndexes)
4616 "\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid"
4617 "\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid");
4618
4619 if (showNested || pattern)
4621 "\n LEFT JOIN pg_catalog.pg_inherits inh ON c.oid = inh.inhrelid");
4622
4623 if (verbose)
4624 {
4626 "\n LEFT JOIN pg_catalog.pg_am am ON c.relam = am.oid");
4627
4628 if (pset.sversion < 120000)
4629 {
4631 ",\n LATERAL (WITH RECURSIVE d\n"
4632 " AS (SELECT inhrelid AS oid, 1 AS level\n"
4633 " FROM pg_catalog.pg_inherits\n"
4634 " WHERE inhparent = c.oid\n"
4635 " UNION ALL\n"
4636 " SELECT inhrelid, level + 1\n"
4637 " FROM pg_catalog.pg_inherits i\n"
4638 " JOIN d ON i.inhparent = d.oid)\n"
4639 " SELECT pg_catalog.pg_size_pretty(sum(pg_catalog.pg_table_size("
4640 "d.oid))) AS tps,\n"
4641 " pg_catalog.pg_size_pretty(sum("
4642 "\n CASE WHEN d.level = 1"
4643 " THEN pg_catalog.pg_table_size(d.oid) ELSE 0 END)) AS dps\n"
4644 " FROM d) s");
4645 }
4646 else
4647 {
4648 /* PostgreSQL 12 has pg_partition_tree function */
4650 ",\n LATERAL (SELECT pg_catalog.pg_size_pretty(sum("
4651 "\n CASE WHEN ppt.isleaf AND ppt.level = 1"
4652 "\n THEN pg_catalog.pg_table_size(ppt.relid)"
4653 " ELSE 0 END)) AS dps"
4654 ",\n pg_catalog.pg_size_pretty(sum("
4655 "pg_catalog.pg_table_size(ppt.relid))) AS tps"
4656 "\n FROM pg_catalog.pg_partition_tree(c.oid) ppt) s");
4657 }
4658 }
4659
4660 appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
4661 if (showTables)
4663 if (showIndexes)
4665 appendPQExpBufferStr(&buf, "''"); /* dummy */
4666 appendPQExpBufferStr(&buf, ")\n");
4667
4668 appendPQExpBufferStr(&buf, !showNested && !pattern ?
4669 " AND NOT c.relispartition\n" : "");
4670
4671 if (!pattern)
4672 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4673 " AND n.nspname !~ '^pg_toast'\n"
4674 " AND n.nspname <> 'information_schema'\n");
4675
4676 if (!validateSQLNamePattern(&buf, pattern, true, false,
4677 "n.nspname", "c.relname", NULL,
4678 "pg_catalog.pg_table_is_visible(c.oid)",
4679 NULL, 3))
4680 {
4682 return false;
4683 }
4684
4685 appendPQExpBuffer(&buf, "ORDER BY \"Schema\", %s%s\"Name\";",
4686 mixed_output ? "\"Type\" DESC, " : "",
4687 showNested || pattern ? "\"Parent name\" NULLS FIRST, " : "");
4688
4689 res = PSQLexec(buf.data);
4691 if (!res)
4692 return false;
4693
4694 initPQExpBuffer(&title);
4696
4697 myopt.title = title.data;
4698 myopt.translate_header = true;
4699 myopt.translate_columns = translate_columns;
4700 myopt.n_translate_columns = lengthof(translate_columns);
4701
4702 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4703
4704 termPQExpBuffer(&title);
4705
4706 PQclear(res);
4707 return true;
4708}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, CppAsString2, PQExpBufferData::data, fb(), formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, pg_log_error, _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 6684 of file describe.c.

6685{
6687 PGresult *res;
6689 static const bool translate_columns[] = {false, false, false, false, false, false, false, false, false, false};
6690
6691 if (pset.sversion < 100000)
6692 {
6693 char sverbuf[32];
6694
6695 pg_log_error("The server (version %s) does not support publications.",
6697 sverbuf, sizeof(sverbuf)));
6698 return true;
6699 }
6700
6702
6703 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching publications"));
6705 "SELECT pubname AS \"%s\",\n"
6706 " pg_catalog.pg_get_userbyid(pubowner) AS \"%s\",\n"
6707 " puballtables AS \"%s\"",
6708 gettext_noop("Name"),
6709 gettext_noop("Owner"),
6710 gettext_noop("All tables"));
6711
6712 if (pset.sversion >= 190000)
6714 ",\n puballsequences AS \"%s\"",
6715 gettext_noop("All sequences"));
6716
6718 ",\n pubinsert AS \"%s\",\n"
6719 " pubupdate AS \"%s\",\n"
6720 " pubdelete AS \"%s\"",
6721 gettext_noop("Inserts"),
6722 gettext_noop("Updates"),
6723 gettext_noop("Deletes"));
6724 if (pset.sversion >= 110000)
6726 ",\n pubtruncate AS \"%s\"",
6727 gettext_noop("Truncates"));
6728 if (pset.sversion >= 180000)
6730 ",\n (CASE pubgencols\n"
6731 " WHEN '%c' THEN 'none'\n"
6732 " WHEN '%c' THEN 'stored'\n"
6733 " END) AS \"%s\"",
6736 gettext_noop("Generated columns"));
6737 if (pset.sversion >= 130000)
6739 ",\n pubviaroot AS \"%s\"",
6740 gettext_noop("Via root"));
6741
6743 "\nFROM pg_catalog.pg_publication\n");
6744
6745 if (!validateSQLNamePattern(&buf, pattern, false, false,
6746 NULL, "pubname", NULL,
6747 NULL,
6748 NULL, 1))
6749 {
6751 return false;
6752 }
6753
6754 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6755
6756 res = PSQLexec(buf.data);
6758 if (!res)
6759 return false;
6760
6761 myopt.title = _("List of publications");
6762 myopt.translate_header = true;
6763 myopt.translate_columns = translate_columns;
6764 myopt.n_translate_columns = lengthof(translate_columns);
6765
6766 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6767
6768 PQclear(res);
6769
6770 return true;
6771}

References _, appendPQExpBuffer(), appendPQExpBufferStr(), buf, fb(), formatPGVersionNumber(), gettext_noop, initPQExpBuffer(), lengthof, _psqlSettings::logfile, pg_log_error, _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 5462 of file describe.c.

5463{
5465 PGresult *res;
5467 int pub_schema_tuples = 0;
5468 char **footers = NULL;
5469
5471
5472 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching schemas"));
5474 "SELECT n.nspname AS \"%s\",\n"
5475 " pg_catalog.pg_get_userbyid(n.nspowner) AS \"%s\"",
5476 gettext_noop("Name"),
5477 gettext_noop("Owner"));
5478
5479 if (verbose)
5480 {
5481 appendPQExpBufferStr(&buf, ",\n ");
5482 printACLColumn(&buf, "n.nspacl");
5484 ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"",
5485 gettext_noop("Description"));
5486 }
5487
5489 "\nFROM pg_catalog.pg_namespace n\n");
5490
5491 if (!showSystem && !pattern)
5493 "WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'\n");
5494
5495 if (!validateSQLNamePattern(&buf, pattern,
5496 !showSystem && !pattern, false,
5497 NULL, "n.nspname", NULL,
5498 NULL,
5499 NULL, 2))
5500 goto error_return;
5501
5502 appendPQExpBufferStr(&buf, "ORDER BY 1;");
5503
5504 res = PSQLexec(buf.data);
5505 if (!res)
5506 goto error_return;
5507
5508 myopt.title = _("List of schemas");
5509 myopt.translate_header = true;
5510
5511 if (pattern && pset.sversion >= 150000)
5512 {
5514 int i;
5515
5516 printfPQExpBuffer(&buf, "/* %s */\n",
5517 _("Get publications that publish this schema"));
5519 "SELECT pubname \n"
5520 "FROM pg_catalog.pg_publication p\n"
5521 " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
5522 " JOIN pg_catalog.pg_namespace n ON n.oid = pn.pnnspid \n"
5523 "WHERE n.nspname = '%s'\n"
5524 "ORDER BY 1",
5525 pattern);
5526 result = PSQLexec(buf.data);
5527 if (!result)
5528 goto error_return;
5529 else
5531
5532 if (pub_schema_tuples > 0)
5533 {
5534 /*
5535 * Allocate memory for footers. Size of footers will be 1 (for
5536 * storing "Publications:" string) + publication schema mapping
5537 * count + 1 (for storing NULL).
5538 */
5539 footers = pg_malloc_array(char *, 1 + pub_schema_tuples + 1);
5540 footers[0] = pg_strdup(_("Publications:"));
5541
5542 /* Might be an empty set - that's ok */
5543 for (i = 0; i < pub_schema_tuples; i++)
5544 {
5545 printfPQExpBuffer(&buf, " \"%s\"",
5546 PQgetvalue(result, i, 0));
5547
5548 footers[i + 1] = pg_strdup(buf.data);
5549 }
5550
5551 footers[i + 1] = NULL;
5552 myopt.footers = footers;
5553 }
5554
5555 PQclear(result);
5556 }
5557
5558 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5559
5561 PQclear(res);
5562
5563 /* Free the memory allocated for the footer */
5564 if (footers)
5565 {
5566 char **footer = NULL;
5567
5568 for (footer = footers; *footer; footer++)
5569 pg_free(*footer);
5570
5571 pg_free(footers);
5572 }
5573
5574 return true;
5575
5578 return false;
5579}
void pg_free(void *ptr)
#define pg_malloc_array(type, count)
Definition fe_memutils.h:56

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

4238{
4239 bool showTables = strchr(tabtypes, 't') != NULL;
4240 bool showIndexes = strchr(tabtypes, 'i') != NULL;
4241 bool showViews = strchr(tabtypes, 'v') != NULL;
4242 bool showMatViews = strchr(tabtypes, 'm') != NULL;
4243 bool showSeq = strchr(tabtypes, 's') != NULL;
4244 bool showForeign = strchr(tabtypes, 'E') != NULL;
4245 bool showPropGraphs = strchr(tabtypes, 'G') != NULL;
4246
4247 int ntypes;
4249 PGresult *res;
4251 int cols_so_far;
4252 bool translate_columns[] = {false, false, true, false, false, false, false, false, false};
4253
4254 /* Count the number of explicitly-requested relation types */
4257 /* If none, we default to \dtvmsEG (but see also command.c) */
4258 if (ntypes == 0)
4260
4262
4263 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching relations"));
4265 "SELECT n.nspname as \"%s\",\n"
4266 " c.relname as \"%s\",\n"
4267 " CASE c.relkind"
4268 " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'"
4269 " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'"
4270 " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'"
4271 " WHEN " CppAsString2(RELKIND_INDEX) " THEN '%s'"
4272 " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'"
4273 " WHEN " CppAsString2(RELKIND_TOASTVALUE) " THEN '%s'"
4274 " WHEN " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN '%s'"
4275 " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
4276 " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
4277 " WHEN " CppAsString2(RELKIND_PROPGRAPH) " THEN '%s'"
4278 " END as \"%s\",\n"
4279 " pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"",
4280 gettext_noop("Schema"),
4281 gettext_noop("Name"),
4282 gettext_noop("table"),
4283 gettext_noop("view"),
4284 gettext_noop("materialized view"),
4285 gettext_noop("index"),
4286 gettext_noop("sequence"),
4287 gettext_noop("TOAST table"),
4288 gettext_noop("foreign table"),
4289 gettext_noop("partitioned table"),
4290 gettext_noop("partitioned index"),
4291 gettext_noop("property graph"),
4292 gettext_noop("Type"),
4293 gettext_noop("Owner"));
4294 cols_so_far = 4;
4295
4296 if (showIndexes)
4297 {
4299 ",\n c2.relname as \"%s\"",
4300 gettext_noop("Table"));
4301 cols_so_far++;
4302 }
4303
4304 if (verbose)
4305 {
4306 /*
4307 * Show whether a relation is permanent, temporary, or unlogged.
4308 */
4310 ",\n CASE c.relpersistence "
4311 "WHEN " CppAsString2(RELPERSISTENCE_PERMANENT) " THEN '%s' "
4312 "WHEN " CppAsString2(RELPERSISTENCE_TEMP) " THEN '%s' "
4313 "WHEN " CppAsString2(RELPERSISTENCE_UNLOGGED) " THEN '%s' "
4314 "END as \"%s\"",
4315 gettext_noop("permanent"),
4316 gettext_noop("temporary"),
4317 gettext_noop("unlogged"),
4318 gettext_noop("Persistence"));
4319 translate_columns[cols_so_far] = true;
4320
4321 /*
4322 * We don't bother to count cols_so_far below here, as there's no need
4323 * to; this might change with future additions to the output columns.
4324 */
4325
4326 /*
4327 * Access methods exist for tables, materialized views and indexes.
4328 * This has been introduced in PostgreSQL 12 for tables.
4329 */
4330 if (pset.sversion >= 120000 && !pset.hide_tableam &&
4333 ",\n am.amname as \"%s\"",
4334 gettext_noop("Access method"));
4335
4337 ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\""
4338 ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"",
4339 gettext_noop("Size"),
4340 gettext_noop("Description"));
4341 }
4342
4344 "\nFROM pg_catalog.pg_class c"
4345 "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace");
4346
4347 if (pset.sversion >= 120000 && !pset.hide_tableam &&
4350 "\n LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam");
4351
4352 if (showIndexes)
4354 "\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid"
4355 "\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid");
4356
4357 appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
4358 if (showTables)
4359 {
4362 /* with 'S' or a pattern, allow 't' to match TOAST tables too */
4363 if (showSystem || pattern)
4365 }
4366 if (showViews)
4368 if (showMatViews)
4370 if (showIndexes)
4373 if (showSeq)
4375 if (showSystem || pattern)
4376 appendPQExpBufferStr(&buf, "'s',"); /* was RELKIND_SPECIAL */
4377 if (showForeign)
4379 if (showPropGraphs)
4381
4382 appendPQExpBufferStr(&buf, "''"); /* dummy */
4383 appendPQExpBufferStr(&buf, ")\n");
4384
4385 if (!showSystem && !pattern)
4386 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4387 " AND n.nspname !~ '^pg_toast'\n"
4388 " AND n.nspname <> 'information_schema'\n");
4389
4390 if (!validateSQLNamePattern(&buf, pattern, true, false,
4391 "n.nspname", "c.relname", NULL,
4392 "pg_catalog.pg_table_is_visible(c.oid)",
4393 NULL, 3))
4394 {
4396 return false;
4397 }
4398
4399 appendPQExpBufferStr(&buf, "ORDER BY 1,2;");
4400
4401 res = PSQLexec(buf.data);
4403 if (!res)
4404 return false;
4405
4406 /*
4407 * Most functions in this file are content to print an empty table when
4408 * there are no matching objects. We intentionally deviate from that
4409 * here, but only in !quiet mode, for historical reasons.
4410 */
4411 if (PQntuples(res) == 0 && !pset.quiet)
4412 {
4413 if (pattern)
4414 {
4415 if (ntypes != 1)
4416 pg_log_error("Did not find any relations named \"%s\".",
4417 pattern);
4418 else if (showTables)
4419 pg_log_error("Did not find any tables named \"%s\".",
4420 pattern);
4421 else if (showIndexes)
4422 pg_log_error("Did not find any indexes named \"%s\".",
4423 pattern);
4424 else if (showViews)
4425 pg_log_error("Did not find any views named \"%s\".",
4426 pattern);
4427 else if (showMatViews)
4428 pg_log_error("Did not find any materialized views named \"%s\".",
4429 pattern);
4430 else if (showSeq)
4431 pg_log_error("Did not find any sequences named \"%s\".",
4432 pattern);
4433 else if (showForeign)
4434 pg_log_error("Did not find any foreign tables named \"%s\".",
4435 pattern);
4436 else if (showPropGraphs)
4437 pg_log_error("Did not find any property graphs named \"%s\".",
4438 pattern);
4439 else /* should not get here */
4440 pg_log_error_internal("Did not find any ??? named \"%s\".",
4441 pattern);
4442 }
4443 else
4444 {
4445 if (ntypes != 1)
4446 pg_log_error("Did not find any relations.");
4447 else if (showTables)
4448 pg_log_error("Did not find any tables.");
4449 else if (showIndexes)
4450 pg_log_error("Did not find any indexes.");
4451 else if (showViews)
4452 pg_log_error("Did not find any views.");
4453 else if (showMatViews)
4454 pg_log_error("Did not find any materialized views.");
4455 else if (showSeq)
4456 pg_log_error("Did not find any sequences.");
4457 else if (showForeign)
4458 pg_log_error("Did not find any foreign tables.");
4459 else if (showPropGraphs)
4460 pg_log_error("Did not find any property graphs.");
4461 else /* should not get here */
4462 pg_log_error_internal("Did not find any ??? relations.");
4463 }
4464 }
4465 else
4466 {
4467 myopt.title =
4468 (ntypes != 1) ? _("List of relations") :
4469 (showTables) ? _("List of tables") :
4470 (showIndexes) ? _("List of indexes") :
4471 (showViews) ? _("List of views") :
4472 (showMatViews) ? _("List of materialized views") :
4473 (showSeq) ? _("List of sequences") :
4474 (showForeign) ? _("List of foreign tables") :
4475 (showPropGraphs) ? _("List of property graphs") :
4476 "List of ???"; /* should not get here */
4477 myopt.translate_header = true;
4478 myopt.translate_columns = translate_columns;
4479 myopt.n_translate_columns = lengthof(translate_columns);
4480
4481 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4482 }
4483
4484 PQclear(res);
4485 return true;
4486}
#define pg_log_error_internal(...)
Definition logging.h:160

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

5972{
5974 PGresult *res;
5976
5977 if (verbose)
5978 return listTSConfigsVerbose(pattern);
5979
5981
5982 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching text search configurations"));
5984 "SELECT\n"
5985 " n.nspname as \"%s\",\n"
5986 " c.cfgname as \"%s\",\n"
5987 " pg_catalog.obj_description(c.oid, 'pg_ts_config') as \"%s\"\n"
5988 "FROM pg_catalog.pg_ts_config c\n"
5989 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace\n",
5990 gettext_noop("Schema"),
5991 gettext_noop("Name"),
5992 gettext_noop("Description")
5993 );
5994
5995 if (!validateSQLNamePattern(&buf, pattern, false, false,
5996 "n.nspname", "c.cfgname", NULL,
5997 "pg_catalog.pg_ts_config_is_visible(c.oid)",
5998 NULL, 3))
5999 {
6001 return false;
6002 }
6003
6004 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
6005
6006 res = PSQLexec(buf.data);
6008 if (!res)
6009 return false;
6010
6011 myopt.title = _("List of text search configurations");
6012 myopt.translate_header = true;
6013
6014 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6015
6016 PQclear(res);
6017 return true;
6018}
static bool listTSConfigsVerbose(const char *pattern)
Definition describe.c:6021

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

6022{
6024 PGresult *res;
6025 int i;
6026
6028
6029 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching text search configurations"));
6031 "SELECT c.oid, c.cfgname,\n"
6032 " n.nspname,\n"
6033 " p.prsname,\n"
6034 " np.nspname as pnspname\n"
6035 "FROM pg_catalog.pg_ts_config c\n"
6036 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace,\n"
6037 " pg_catalog.pg_ts_parser p\n"
6038 " LEFT JOIN pg_catalog.pg_namespace np ON np.oid = p.prsnamespace\n"
6039 "WHERE p.oid = c.cfgparser\n"
6040 );
6041
6042 if (!validateSQLNamePattern(&buf, pattern, true, false,
6043 "n.nspname", "c.cfgname", NULL,
6044 "pg_catalog.pg_ts_config_is_visible(c.oid)",
6045 NULL, 3))
6046 {
6048 return false;
6049 }
6050
6051 appendPQExpBufferStr(&buf, "ORDER BY 3, 2;");
6052
6053 res = PSQLexec(buf.data);
6055 if (!res)
6056 return false;
6057
6058 if (PQntuples(res) == 0)
6059 {
6060 if (!pset.quiet)
6061 {
6062 if (pattern)
6063 pg_log_error("Did not find any text search configuration named \"%s\".",
6064 pattern);
6065 else
6066 pg_log_error("Did not find any text search configurations.");
6067 }
6068 PQclear(res);
6069 return false;
6070 }
6071
6072 for (i = 0; i < PQntuples(res); i++)
6073 {
6074 const char *oid;
6075 const char *cfgname;
6076 const char *nspname = NULL;
6077 const char *prsname;
6078 const char *pnspname = NULL;
6079
6080 oid = PQgetvalue(res, i, 0);
6081 cfgname = PQgetvalue(res, i, 1);
6082 if (!PQgetisnull(res, i, 2))
6083 nspname = PQgetvalue(res, i, 2);
6084 prsname = PQgetvalue(res, i, 3);
6085 if (!PQgetisnull(res, i, 4))
6086 pnspname = PQgetvalue(res, i, 4);
6087
6088 if (!describeOneTSConfig(oid, nspname, cfgname, pnspname, prsname))
6089 {
6090 PQclear(res);
6091 return false;
6092 }
6093
6094 if (cancel_pressed)
6095 {
6096 PQclear(res);
6097 return false;
6098 }
6099 }
6100
6101 PQclear(res);
6102 return true;
6103}
static bool describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname, const char *pnspname, const char *prsname)
Definition describe.c:6106

References _, appendPQExpBuffer(), 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 5839 of file describe.c.

5840{
5842 PGresult *res;
5844
5846
5847 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching text search dictionaries"));
5849 "SELECT\n"
5850 " n.nspname as \"%s\",\n"
5851 " d.dictname as \"%s\",\n",
5852 gettext_noop("Schema"),
5853 gettext_noop("Name"));
5854
5855 if (verbose)
5856 {
5858 " ( SELECT COALESCE(nt.nspname, '(null)')::pg_catalog.text || '.' || t.tmplname FROM\n"
5859 " pg_catalog.pg_ts_template t\n"
5860 " LEFT JOIN pg_catalog.pg_namespace nt ON nt.oid = t.tmplnamespace\n"
5861 " WHERE d.dicttemplate = t.oid ) AS \"%s\",\n"
5862 " d.dictinitoption as \"%s\",\n",
5863 gettext_noop("Template"),
5864 gettext_noop("Init options"));
5865 }
5866
5868 " pg_catalog.obj_description(d.oid, 'pg_ts_dict') as \"%s\"\n",
5869 gettext_noop("Description"));
5870
5871 appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_dict d\n"
5872 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace\n");
5873
5874 if (!validateSQLNamePattern(&buf, pattern, false, false,
5875 "n.nspname", "d.dictname", NULL,
5876 "pg_catalog.pg_ts_dict_is_visible(d.oid)",
5877 NULL, 3))
5878 {
5880 return false;
5881 }
5882
5883 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5884
5885 res = PSQLexec(buf.data);
5887 if (!res)
5888 return false;
5889
5890 myopt.title = _("List of text search dictionaries");
5891 myopt.translate_header = true;
5892
5893 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5894
5895 PQclear(res);
5896 return true;
5897}

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

5588{
5590 PGresult *res;
5592
5593 if (verbose)
5594 return listTSParsersVerbose(pattern);
5595
5597
5598 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching text search parsers"));
5600 "SELECT\n"
5601 " n.nspname as \"%s\",\n"
5602 " p.prsname as \"%s\",\n"
5603 " pg_catalog.obj_description(p.oid, 'pg_ts_parser') as \"%s\"\n"
5604 "FROM pg_catalog.pg_ts_parser p\n"
5605 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n",
5606 gettext_noop("Schema"),
5607 gettext_noop("Name"),
5608 gettext_noop("Description")
5609 );
5610
5611 if (!validateSQLNamePattern(&buf, pattern, false, false,
5612 "n.nspname", "p.prsname", NULL,
5613 "pg_catalog.pg_ts_parser_is_visible(p.oid)",
5614 NULL, 3))
5615 {
5617 return false;
5618 }
5619
5620 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5621
5622 res = PSQLexec(buf.data);
5624 if (!res)
5625 return false;
5626
5627 myopt.title = _("List of text search parsers");
5628 myopt.translate_header = true;
5629
5630 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5631
5632 PQclear(res);
5633 return true;
5634}
static bool listTSParsersVerbose(const char *pattern)
Definition describe.c:5640

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

5641{
5643 PGresult *res;
5644 int i;
5645
5647
5648 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching text search parsers"));
5650 "SELECT p.oid,\n"
5651 " n.nspname,\n"
5652 " p.prsname\n"
5653 "FROM pg_catalog.pg_ts_parser p\n"
5654 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n"
5655 );
5656
5657 if (!validateSQLNamePattern(&buf, pattern, false, false,
5658 "n.nspname", "p.prsname", NULL,
5659 "pg_catalog.pg_ts_parser_is_visible(p.oid)",
5660 NULL, 3))
5661 {
5663 return false;
5664 }
5665
5666 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5667
5668 res = PSQLexec(buf.data);
5670 if (!res)
5671 return false;
5672
5673 if (PQntuples(res) == 0)
5674 {
5675 if (!pset.quiet)
5676 {
5677 if (pattern)
5678 pg_log_error("Did not find any text search parser named \"%s\".",
5679 pattern);
5680 else
5681 pg_log_error("Did not find any text search parsers.");
5682 }
5683 PQclear(res);
5684 return false;
5685 }
5686
5687 for (i = 0; i < PQntuples(res); i++)
5688 {
5689 const char *oid;
5690 const char *nspname = NULL;
5691 const char *prsname;
5692
5693 oid = PQgetvalue(res, i, 0);
5694 if (!PQgetisnull(res, i, 1))
5695 nspname = PQgetvalue(res, i, 1);
5696 prsname = PQgetvalue(res, i, 2);
5697
5698 if (!describeOneTSParser(oid, nspname, prsname))
5699 {
5700 PQclear(res);
5701 return false;
5702 }
5703
5704 if (cancel_pressed)
5705 {
5706 PQclear(res);
5707 return false;
5708 }
5709 }
5710
5711 PQclear(res);
5712 return true;
5713}
static bool describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
Definition describe.c:5716

References _, appendPQExpBuffer(), 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 5905 of file describe.c.

5906{
5908 PGresult *res;
5910
5912
5913 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching text search templates"));
5914 if (verbose)
5916 "SELECT\n"
5917 " n.nspname AS \"%s\",\n"
5918 " t.tmplname AS \"%s\",\n"
5919 " t.tmplinit::pg_catalog.regproc AS \"%s\",\n"
5920 " t.tmpllexize::pg_catalog.regproc AS \"%s\",\n"
5921 " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
5922 gettext_noop("Schema"),
5923 gettext_noop("Name"),
5924 gettext_noop("Init"),
5925 gettext_noop("Lexize"),
5926 gettext_noop("Description"));
5927 else
5929 "SELECT\n"
5930 " n.nspname AS \"%s\",\n"
5931 " t.tmplname AS \"%s\",\n"
5932 " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
5933 gettext_noop("Schema"),
5934 gettext_noop("Name"),
5935 gettext_noop("Description"));
5936
5937 appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_template t\n"
5938 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.tmplnamespace\n");
5939
5940 if (!validateSQLNamePattern(&buf, pattern, false, false,
5941 "n.nspname", "t.tmplname", NULL,
5942 "pg_catalog.pg_ts_template_is_visible(t.oid)",
5943 NULL, 3))
5944 {
5946 return false;
5947 }
5948
5949 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5950
5951 res = PSQLexec(buf.data);
5953 if (!res)
5954 return false;
5955
5956 myopt.title = _("List of text search templates");
5957 myopt.translate_header = true;
5958
5959 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5960
5961 PQclear(res);
5962 return true;
5963}

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

6330{
6332 PGresult *res;
6334
6336
6337 printfPQExpBuffer(&buf, "/* %s */\n", _("Get matching user mappings"));
6339 "SELECT um.srvname AS \"%s\",\n"
6340 " um.usename AS \"%s\"",
6341 gettext_noop("Server"),
6342 gettext_noop("User name"));
6343
6344 if (verbose)
6346 ",\n CASE WHEN umoptions IS NULL THEN '' ELSE "
6347 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6348 " pg_catalog.quote_ident(option_name) || ' ' || "
6349 " pg_catalog.quote_literal(option_value) FROM "
6350 " pg_catalog.pg_options_to_table(umoptions)), ', ') || ')' "
6351 " END AS \"%s\"",
6352 gettext_noop("FDW options"));
6353
6354 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_user_mappings um\n");
6355
6356 if (!validateSQLNamePattern(&buf, pattern, false, false,
6357 NULL, "um.srvname", "um.usename", NULL,
6358 NULL, 1))
6359 {
6361 return false;
6362 }
6363
6364 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
6365
6366 res = PSQLexec(buf.data);
6368 if (!res)
6369 return false;
6370
6371 myopt.title = _("List of user mappings");
6372 myopt.translate_header = true;
6373
6374 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6375
6376 PQclear(res);
6377 return true;
6378}

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

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

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

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

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

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

7252{
7254 "CASE"
7255 " WHEN pg_catalog.array_length(%s, 1) = 0 THEN '%s'"
7256 " ELSE pg_catalog.array_to_string(%s, E'\\n')"
7257 " END AS \"%s\"",
7258 colname, gettext_noop("(none)"),
7259 colname, gettext_noop("Access privileges"));
7260}

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

6636{
6638 int dotcnt;
6639 bool added;
6640
6645 if (added_clause != NULL)
6647
6648 if (dotcnt >= maxparts)
6649 {
6650 pg_log_error("improper qualified name (too many dotted names): %s",
6651 pattern);
6652 goto error_return;
6653 }
6654
6655 if (maxparts > 1 && dotcnt == maxparts - 1)
6656 {
6657 if (PQdb(pset.db) == NULL)
6658 {
6659 pg_log_error("You are currently not connected to a database.");
6660 goto error_return;
6661 }
6662 if (strcmp(PQdb(pset.db), dbbuf.data) != 0)
6663 {
6664 pg_log_error("cross-database references are not implemented: %s",
6665 pattern);
6666 goto error_return;
6667 }
6668 }
6670 return true;
6671
6674 return false;
6675}
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().