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

4016{
4017 if (buf->len > 0)
4019
4021}
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 3815 of file describe.c.

3817{
3818 /* relkinds for which we support tablespaces */
3819 if (relkind == RELKIND_RELATION ||
3820 relkind == RELKIND_MATVIEW ||
3821 relkind == RELKIND_INDEX ||
3822 relkind == RELKIND_PARTITIONED_TABLE ||
3823 relkind == RELKIND_PARTITIONED_INDEX ||
3824 relkind == RELKIND_TOASTVALUE)
3825 {
3826 /*
3827 * We ignore the database default tablespace so that users not using
3828 * tablespaces don't need to know about them.
3829 */
3830 if (tablespace != 0)
3831 {
3832 PGresult *result = NULL;
3834
3837 "SELECT spcname FROM pg_catalog.pg_tablespace\n"
3838 "WHERE oid = '%u';", tablespace);
3839 result = PSQLexec(buf.data);
3840 if (!result)
3841 {
3843 return;
3844 }
3845 /* Should always be the case, but.... */
3846 if (PQntuples(result) > 0)
3847 {
3848 if (newline)
3849 {
3850 /* Add the tablespace as a new footer */
3851 printfPQExpBuffer(&buf, _("Tablespace: \"%s\""),
3852 PQgetvalue(result, 0, 0));
3854 }
3855 else
3856 {
3857 /* Append the tablespace to the latest footer */
3858 printfPQExpBuffer(&buf, "%s", cont->footer->data);
3859
3860 /*-------
3861 translator: before this string there's an index description like
3862 '"foo_pkey" PRIMARY KEY, btree (a)' */
3863 appendPQExpBuffer(&buf, _(", tablespace \"%s\""),
3864 PQgetvalue(result, 0, 0));
3866 }
3867 }
3868 PQclear(result);
3870 }
3871 }
3872}
PGresult * PSQLexec(const char *query)
Definition common.c:655
#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(), 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 6673 of file describe.c.

6675{
6676 PGresult *res;
6677 int count = 0;
6678 int i = 0;
6679
6680 res = PSQLexec(buf->data);
6681 if (!res)
6682 return false;
6683 else
6684 count = PQntuples(res);
6685
6686 if (count > 0)
6688
6689 for (i = 0; i < count; i++)
6690 {
6691 if (as_schema)
6692 printfPQExpBuffer(buf, " \"%s\"", PQgetvalue(res, i, 0));
6693 else
6694 {
6695 printfPQExpBuffer(buf, " \"%s.%s\"", PQgetvalue(res, i, 0),
6696 PQgetvalue(res, i, 1));
6697
6698 if (!PQgetisnull(res, i, 3))
6699 appendPQExpBuffer(buf, " (%s)", PQgetvalue(res, i, 3));
6700
6701 if (!PQgetisnull(res, i, 2))
6702 appendPQExpBuffer(buf, " WHERE %s", PQgetvalue(res, i, 2));
6703 }
6704
6706 }
6707
6708 PQclear(res);
6709 return true;
6710}
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 149 of file describe.c.

150{
152 PGresult *res;
154 static const bool translate_columns[] = {false, true, false, false};
155
156 if (pset.sversion < 90600)
157 {
158 char sverbuf[32];
159
160 pg_log_error("The server (version %s) does not support access methods.",
162 sverbuf, sizeof(sverbuf)));
163 return true;
164 }
165
167
169 "SELECT amname AS \"%s\",\n"
170 " CASE amtype"
171 " WHEN " CppAsString2(AMTYPE_INDEX) " THEN '%s'"
172 " WHEN " CppAsString2(AMTYPE_TABLE) " THEN '%s'"
173 " END AS \"%s\"",
174 gettext_noop("Name"),
175 gettext_noop("Index"),
176 gettext_noop("Table"),
177 gettext_noop("Type"));
178
179 if (verbose)
180 {
182 ",\n amhandler AS \"%s\",\n"
183 " pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"",
184 gettext_noop("Handler"),
185 gettext_noop("Description"));
186 }
187
189 "\nFROM pg_catalog.pg_am\n");
190
191 if (!validateSQLNamePattern(&buf, pattern, false, false,
192 NULL, "amname", NULL,
193 NULL,
194 NULL, 1))
195 {
197 return false;
198 }
199
200 appendPQExpBufferStr(&buf, "ORDER BY 1;");
201
202 res = PSQLexec(buf.data);
204 if (!res)
205 return false;
206
207 myopt.title = _("List of access methods");
208 myopt.translate_header = true;
209 myopt.translate_columns = translate_columns;
210 myopt.n_translate_columns = lengthof(translate_columns);
211
212 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
213
214 PQclear(res);
215 return true;
216}
#define gettext_noop(x)
Definition c.h:1287
#define CppAsString2(x)
Definition c.h:500
#define lengthof(array)
Definition c.h:875
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:6528
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:32
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
88 "SELECT n.nspname as \"%s\",\n"
89 " p.proname AS \"%s\",\n"
90 " pg_catalog.format_type(p.prorettype, NULL) AS \"%s\",\n"
91 " CASE WHEN p.pronargs = 0\n"
92 " THEN CAST('*' AS pg_catalog.text)\n"
93 " ELSE pg_catalog.pg_get_function_arguments(p.oid)\n"
94 " END AS \"%s\",\n",
95 gettext_noop("Schema"),
96 gettext_noop("Name"),
97 gettext_noop("Result data type"),
98 gettext_noop("Argument data types"));
99
100 if (pset.sversion >= 110000)
102 " pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"\n"
103 "FROM pg_catalog.pg_proc p\n"
104 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"
105 "WHERE p.prokind = " CppAsString2(PROKIND_AGGREGATE) "\n",
106 gettext_noop("Description"));
107 else
109 " pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"\n"
110 "FROM pg_catalog.pg_proc p\n"
111 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"
112 "WHERE p.proisagg\n",
113 gettext_noop("Description"));
114
115 if (!showSystem && !pattern)
116 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
117 " AND n.nspname <> 'information_schema'\n");
118
119 if (!validateSQLNamePattern(&buf, pattern, true, false,
120 "n.nspname", "p.proname", NULL,
121 "pg_catalog.pg_function_is_visible(p.oid)",
122 NULL, 3))
123 {
125 return false;
126 }
127
128 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
129
130 res = PSQLexec(buf.data);
132 if (!res)
133 return false;
134
135 myopt.title = _("List of aggregate functions");
136 myopt.translate_header = true;
137
138 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
139
140 PQclear(res);
141 return true;
142}

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

4893{
4895 PGresult *res;
4897
4900 "SELECT s.name AS \"%s\", "
4901 "pg_catalog.current_setting(s.name) AS \"%s\"",
4902 gettext_noop("Parameter"),
4903 gettext_noop("Value"));
4904
4905 if (verbose)
4906 {
4908 ", s.vartype AS \"%s\", s.context AS \"%s\", ",
4909 gettext_noop("Type"),
4910 gettext_noop("Context"));
4911 if (pset.sversion >= 150000)
4912 printACLColumn(&buf, "p.paracl");
4913 else
4914 appendPQExpBuffer(&buf, "NULL AS \"%s\"",
4915 gettext_noop("Access privileges"));
4916 }
4917
4918 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_settings s\n");
4919
4920 if (verbose && pset.sversion >= 150000)
4922 " LEFT JOIN pg_catalog.pg_parameter_acl p\n"
4923 " ON pg_catalog.lower(s.name) = p.parname\n");
4924
4925 if (pattern)
4926 processSQLNamePattern(pset.db, &buf, pattern,
4927 false, false,
4928 NULL, "pg_catalog.lower(s.name)", NULL,
4929 NULL, NULL, NULL);
4930 else
4931 appendPQExpBufferStr(&buf, "WHERE s.source <> 'default' AND\n"
4932 " s.setting IS DISTINCT FROM s.boot_val\n");
4933
4934 appendPQExpBufferStr(&buf, "ORDER BY 1;");
4935
4936 res = PSQLexec(buf.data);
4938 if (!res)
4939 return false;
4940
4941 if (pattern)
4942 myopt.title = _("List of configuration parameters");
4943 else
4944 myopt.title = _("List of non-default configuration parameters");
4945 myopt.translate_header = true;
4946
4947 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4948
4949 PQclear(res);
4950 return true;
4951}
static void printACLColumn(PQExpBuffer buf, const char *colname)
Definition describe.c:7140
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 296 of file describe.c.

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

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

References _, add_tablespace_footer(), appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), Assert, atooid, buf, CppAsString2, StringInfoData::data, PQExpBufferData::data, _psqlSettings::encoding, fb(), fmtId(), free, gettext_noop, _psqlSettings::hide_compression, _psqlSettings::hide_tableam, i, initPQExpBuffer(), lengthof, _psqlSettings::logfile, pg_log_error, pg_strdup(), pg_wcswidth(), _psqlSettings::popt, PQclear, PQfnumber(), PQgetisnull, PQgetvalue, PQntuples, printfPQExpBuffer(), printQuery(), printTable(), printTableAddCell(), printTableAddFooter(), printTableAddHeader(), printTableCleanup(), printTableInit(), pset, psprintf(), PSQLexec(), _psqlSettings::queryFout, _psqlSettings::quiet, relname, resetPQExpBuffer(), storage, _psqlSettings::sversion, tablespace, termPQExpBuffer(), 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 6018 of file describe.c.

6020{
6022 title;
6023 PGresult *res;
6025
6027
6029 "SELECT\n"
6030 " ( SELECT t.alias FROM\n"
6031 " pg_catalog.ts_token_type(c.cfgparser) AS t\n"
6032 " WHERE t.tokid = m.maptokentype ) AS \"%s\",\n"
6033 " pg_catalog.btrim(\n"
6034 " ARRAY( SELECT mm.mapdict::pg_catalog.regdictionary\n"
6035 " FROM pg_catalog.pg_ts_config_map AS mm\n"
6036 " WHERE mm.mapcfg = m.mapcfg AND mm.maptokentype = m.maptokentype\n"
6037 " ORDER BY mapcfg, maptokentype, mapseqno\n"
6038 " ) :: pg_catalog.text,\n"
6039 " '{}') AS \"%s\"\n"
6040 "FROM pg_catalog.pg_ts_config AS c, pg_catalog.pg_ts_config_map AS m\n"
6041 "WHERE c.oid = '%s' AND m.mapcfg = c.oid\n"
6042 "GROUP BY m.mapcfg, m.maptokentype, c.cfgparser\n"
6043 "ORDER BY 1;",
6044 gettext_noop("Token"),
6045 gettext_noop("Dictionaries"),
6046 oid);
6047
6048 res = PSQLexec(buf.data);
6050 if (!res)
6051 return false;
6052
6053 initPQExpBuffer(&title);
6054
6055 if (nspname)
6056 appendPQExpBuffer(&title, _("Text search configuration \"%s.%s\""),
6057 nspname, cfgname);
6058 else
6059 appendPQExpBuffer(&title, _("Text search configuration \"%s\""),
6060 cfgname);
6061
6062 if (pnspname)
6063 appendPQExpBuffer(&title, _("\nParser: \"%s.%s\""),
6064 pnspname, prsname);
6065 else
6066 appendPQExpBuffer(&title, _("\nParser: \"%s\""),
6067 prsname);
6068
6069 myopt.title = title.data;
6070 myopt.footers = NULL;
6071 myopt.topt.default_footer = false;
6072 myopt.translate_header = true;
6073
6074 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6075
6076 termPQExpBuffer(&title);
6077
6078 PQclear(res);
6079 return true;
6080}

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

5636{
5638 PGresult *res;
5639 PQExpBufferData title;
5641 static const bool translate_columns[] = {true, false, false};
5642
5644
5646 "SELECT '%s' AS \"%s\",\n"
5647 " p.prsstart::pg_catalog.regproc AS \"%s\",\n"
5648 " pg_catalog.obj_description(p.prsstart, 'pg_proc') as \"%s\"\n"
5649 " FROM pg_catalog.pg_ts_parser p\n"
5650 " WHERE p.oid = '%s'\n"
5651 "UNION ALL\n"
5652 "SELECT '%s',\n"
5653 " p.prstoken::pg_catalog.regproc,\n"
5654 " pg_catalog.obj_description(p.prstoken, 'pg_proc')\n"
5655 " FROM pg_catalog.pg_ts_parser p\n"
5656 " WHERE p.oid = '%s'\n"
5657 "UNION ALL\n"
5658 "SELECT '%s',\n"
5659 " p.prsend::pg_catalog.regproc,\n"
5660 " pg_catalog.obj_description(p.prsend, 'pg_proc')\n"
5661 " FROM pg_catalog.pg_ts_parser p\n"
5662 " WHERE p.oid = '%s'\n"
5663 "UNION ALL\n"
5664 "SELECT '%s',\n"
5665 " p.prsheadline::pg_catalog.regproc,\n"
5666 " pg_catalog.obj_description(p.prsheadline, 'pg_proc')\n"
5667 " FROM pg_catalog.pg_ts_parser p\n"
5668 " WHERE p.oid = '%s'\n"
5669 "UNION ALL\n"
5670 "SELECT '%s',\n"
5671 " p.prslextype::pg_catalog.regproc,\n"
5672 " pg_catalog.obj_description(p.prslextype, 'pg_proc')\n"
5673 " FROM pg_catalog.pg_ts_parser p\n"
5674 " WHERE p.oid = '%s';",
5675 gettext_noop("Start parse"),
5676 gettext_noop("Method"),
5677 gettext_noop("Function"),
5678 gettext_noop("Description"),
5679 oid,
5680 gettext_noop("Get next token"),
5681 oid,
5682 gettext_noop("End parse"),
5683 oid,
5684 gettext_noop("Get headline"),
5685 oid,
5686 gettext_noop("Get token types"),
5687 oid);
5688
5689 res = PSQLexec(buf.data);
5691 if (!res)
5692 return false;
5693
5694 initPQExpBuffer(&title);
5695 if (nspname)
5696 printfPQExpBuffer(&title, _("Text search parser \"%s.%s\""),
5697 nspname, prsname);
5698 else
5699 printfPQExpBuffer(&title, _("Text search parser \"%s\""), prsname);
5700 myopt.title = title.data;
5701 myopt.footers = NULL;
5702 myopt.topt.default_footer = false;
5703 myopt.translate_header = true;
5704 myopt.translate_columns = translate_columns;
5705 myopt.n_translate_columns = lengthof(translate_columns);
5706
5707 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5708
5709 PQclear(res);
5710
5712
5714 "SELECT t.alias as \"%s\",\n"
5715 " t.description as \"%s\"\n"
5716 "FROM pg_catalog.ts_token_type( '%s'::pg_catalog.oid ) as t\n"
5717 "ORDER BY 1;",
5718 gettext_noop("Token name"),
5719 gettext_noop("Description"),
5720 oid);
5721
5722 res = PSQLexec(buf.data);
5724 if (!res)
5725 {
5726 termPQExpBuffer(&title);
5727 return false;
5728 }
5729
5730 if (nspname)
5731 printfPQExpBuffer(&title, _("Token types for parser \"%s.%s\""),
5732 nspname, prsname);
5733 else
5734 printfPQExpBuffer(&title, _("Token types for parser \"%s\""), prsname);
5735 myopt.title = title.data;
5736 myopt.footers = NULL;
5737 myopt.topt.default_footer = true;
5738 myopt.translate_header = true;
5739 myopt.translate_columns = NULL;
5740 myopt.n_translate_columns = 0;
5741
5742 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5743
5744 termPQExpBuffer(&title);
5745 PQclear(res);
5746 return true;
5747}

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

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

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

6720{
6722 int i;
6723 PGresult *res;
6724 bool has_pubtruncate;
6725 bool has_pubgencols;
6726 bool has_pubviaroot;
6727 bool has_pubsequence;
6728 int ncols = 6;
6729 int nrows = 1;
6730
6731 PQExpBufferData title;
6733
6734 if (pset.sversion < 100000)
6735 {
6736 char sverbuf[32];
6737
6738 pg_log_error("The server (version %s) does not support publications.",
6740 sverbuf, sizeof(sverbuf)));
6741 return true;
6742 }
6743
6744 has_pubsequence = (pset.sversion >= 190000);
6745 has_pubtruncate = (pset.sversion >= 110000);
6746 has_pubgencols = (pset.sversion >= 180000);
6747 has_pubviaroot = (pset.sversion >= 130000);
6748
6750
6752 "SELECT oid, pubname,\n"
6753 " pg_catalog.pg_get_userbyid(pubowner) AS owner,\n"
6754 " puballtables");
6755
6756 if (has_pubsequence)
6758 ", puballsequences");
6759 else
6761 ", false AS puballsequences");
6762
6764 ", pubinsert, pubupdate, pubdelete");
6765
6766 if (has_pubtruncate)
6768 ", pubtruncate");
6769 else
6771 ", false AS pubtruncate");
6772
6773 if (has_pubgencols)
6775 ", (CASE pubgencols\n"
6776 " WHEN '%c' THEN 'none'\n"
6777 " WHEN '%c' THEN 'stored'\n"
6778 " END) AS \"%s\"\n",
6781 gettext_noop("Generated columns"));
6782 else
6784 ", 'none' AS pubgencols");
6785
6786 if (has_pubviaroot)
6788 ", pubviaroot");
6789 else
6791 ", false AS pubviaroot");
6792
6794 ", pg_catalog.obj_description(oid, 'pg_publication')");
6795
6797 "\nFROM pg_catalog.pg_publication\n");
6798
6799 if (!validateSQLNamePattern(&buf, pattern, false, false,
6800 NULL, "pubname", NULL,
6801 NULL,
6802 NULL, 1))
6803 {
6805 return false;
6806 }
6807
6808 appendPQExpBufferStr(&buf, "ORDER BY 2;");
6809
6810 res = PSQLexec(buf.data);
6811 if (!res)
6812 {
6814 return false;
6815 }
6816
6817 if (PQntuples(res) == 0)
6818 {
6819 if (!pset.quiet)
6820 {
6821 if (pattern)
6822 pg_log_error("Did not find any publication named \"%s\".",
6823 pattern);
6824 else
6825 pg_log_error("Did not find any publications.");
6826 }
6827
6829 PQclear(res);
6830 return false;
6831 }
6832
6833 if (has_pubsequence)
6834 ncols++;
6835 if (has_pubtruncate)
6836 ncols++;
6837 if (has_pubgencols)
6838 ncols++;
6839 if (has_pubviaroot)
6840 ncols++;
6841
6842 for (i = 0; i < PQntuples(res); i++)
6843 {
6844 const char align = 'l';
6845 char *pubid = PQgetvalue(res, i, 0);
6846 char *pubname = PQgetvalue(res, i, 1);
6847 bool puballtables = strcmp(PQgetvalue(res, i, 3), "t") == 0;
6849
6850 initPQExpBuffer(&title);
6851 printfPQExpBuffer(&title, _("Publication %s"), pubname);
6852 printTableInit(&cont, &myopt, title.data, ncols, nrows);
6853
6854 printTableAddHeader(&cont, gettext_noop("Owner"), true, align);
6855 printTableAddHeader(&cont, gettext_noop("All tables"), true, align);
6856 if (has_pubsequence)
6857 printTableAddHeader(&cont, gettext_noop("All sequences"), true, align);
6858 printTableAddHeader(&cont, gettext_noop("Inserts"), true, align);
6859 printTableAddHeader(&cont, gettext_noop("Updates"), true, align);
6860 printTableAddHeader(&cont, gettext_noop("Deletes"), true, align);
6861 if (has_pubtruncate)
6862 printTableAddHeader(&cont, gettext_noop("Truncates"), true, align);
6863 if (has_pubgencols)
6864 printTableAddHeader(&cont, gettext_noop("Generated columns"), true, align);
6865 if (has_pubviaroot)
6866 printTableAddHeader(&cont, gettext_noop("Via root"), true, align);
6867 printTableAddHeader(&cont, gettext_noop("Description"), true, align);
6868
6869 printTableAddCell(&cont, PQgetvalue(res, i, 2), false, false);
6870 printTableAddCell(&cont, PQgetvalue(res, i, 3), false, false);
6871 if (has_pubsequence)
6872 printTableAddCell(&cont, PQgetvalue(res, i, 4), false, false);
6873 printTableAddCell(&cont, PQgetvalue(res, i, 5), false, false);
6874 printTableAddCell(&cont, PQgetvalue(res, i, 6), false, false);
6875 printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false);
6876 if (has_pubtruncate)
6877 printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
6878 if (has_pubgencols)
6879 printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
6880 if (has_pubviaroot)
6881 printTableAddCell(&cont, PQgetvalue(res, i, 10), false, false);
6882 printTableAddCell(&cont, PQgetvalue(res, i, 11), false, false);
6883
6884 if (!puballtables)
6885 {
6886 /* Get the tables for the specified publication */
6888 "SELECT n.nspname, c.relname");
6889 if (pset.sversion >= 150000)
6890 {
6892 ", pg_get_expr(pr.prqual, c.oid)");
6894 ", (CASE WHEN pr.prattrs IS NOT NULL THEN\n"
6895 " pg_catalog.array_to_string("
6896 " ARRAY(SELECT attname\n"
6897 " FROM\n"
6898 " pg_catalog.generate_series(0, pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n"
6899 " pg_catalog.pg_attribute\n"
6900 " WHERE attrelid = c.oid AND attnum = prattrs[s]), ', ')\n"
6901 " ELSE NULL END)");
6902 }
6903 else
6905 ", NULL, NULL");
6907 "\nFROM pg_catalog.pg_class c,\n"
6908 " pg_catalog.pg_namespace n,\n"
6909 " pg_catalog.pg_publication_rel pr\n"
6910 "WHERE c.relnamespace = n.oid\n"
6911 " AND c.oid = pr.prrelid\n"
6912 " AND pr.prpubid = '%s'\n", pubid);
6913
6914 if (pset.sversion >= 190000)
6915 appendPQExpBuffer(&buf, " AND NOT pr.prexcept\n");
6916
6917 appendPQExpBuffer(&buf, "ORDER BY 1,2");
6918 if (!addFooterToPublicationDesc(&buf, _("Tables:"), false, &cont))
6919 goto error_return;
6920
6921 if (pset.sversion >= 150000)
6922 {
6923 /* Get the schemas for the specified publication */
6925 "SELECT n.nspname\n"
6926 "FROM pg_catalog.pg_namespace n\n"
6927 " JOIN pg_catalog.pg_publication_namespace pn ON n.oid = pn.pnnspid\n"
6928 "WHERE pn.pnpubid = '%s'\n"
6929 "ORDER BY 1", pubid);
6930 if (!addFooterToPublicationDesc(&buf, _("Tables from schemas:"),
6931 true, &cont))
6932 goto error_return;
6933 }
6934 }
6935 else
6936 {
6937 if (pset.sversion >= 190000)
6938 {
6939 /* Get tables in the EXCEPT clause for this publication */
6941 "SELECT n.nspname || '.' || c.relname\n"
6942 "FROM pg_catalog.pg_class c\n"
6943 " JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
6944 " JOIN pg_catalog.pg_publication_rel pr ON c.oid = pr.prrelid\n"
6945 "WHERE pr.prpubid = '%s' AND pr.prexcept\n"
6946 "ORDER BY 1", pubid);
6947 if (!addFooterToPublicationDesc(&buf, _("Except tables:"),
6948 true, &cont))
6949 goto error_return;
6950 }
6951 }
6952
6955
6956 termPQExpBuffer(&title);
6957 }
6958
6960 PQclear(res);
6961
6962 return true;
6963
6966 PQclear(res);
6968 termPQExpBuffer(&title);
6969 return false;
6970}
static bool addFooterToPublicationDesc(PQExpBuffer buf, const char *footermsg, bool as_schema, printTableContent *const cont)
Definition describe.c:6673

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

4097{
4099 PGresult *res;
4101
4104 "SELECT m.rolname AS \"%s\", r.rolname AS \"%s\",\n"
4105 " pg_catalog.concat_ws(', ',\n",
4106 gettext_noop("Role name"),
4107 gettext_noop("Member of"));
4108
4109 if (pset.sversion >= 160000)
4111 " CASE WHEN pam.admin_option THEN 'ADMIN' END,\n"
4112 " CASE WHEN pam.inherit_option THEN 'INHERIT' END,\n"
4113 " CASE WHEN pam.set_option THEN 'SET' END\n");
4114 else
4116 " CASE WHEN pam.admin_option THEN 'ADMIN' END,\n"
4117 " CASE WHEN m.rolinherit THEN 'INHERIT' END,\n"
4118 " 'SET'\n");
4119
4121 " ) AS \"%s\",\n"
4122 " g.rolname AS \"%s\"\n",
4123 gettext_noop("Options"),
4124 gettext_noop("Grantor"));
4125
4127 "FROM pg_catalog.pg_roles m\n"
4128 " JOIN pg_catalog.pg_auth_members pam ON (pam.member = m.oid)\n"
4129 " LEFT JOIN pg_catalog.pg_roles r ON (pam.roleid = r.oid)\n"
4130 " LEFT JOIN pg_catalog.pg_roles g ON (pam.grantor = g.oid)\n");
4131
4132 if (!showSystem && !pattern)
4133 appendPQExpBufferStr(&buf, "WHERE m.rolname !~ '^pg_'\n");
4134
4135 if (!validateSQLNamePattern(&buf, pattern, false, false,
4136 NULL, "m.rolname", NULL, NULL,
4137 NULL, 1))
4138 {
4140 return false;
4141 }
4142
4143 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;\n");
4144
4145 res = PSQLexec(buf.data);
4147 if (!res)
4148 return false;
4149
4150 myopt.title = _("List of role grants");
4151 myopt.translate_header = true;
4152
4153 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4154
4155 PQclear(res);
4156 return true;
4157}

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

3881{
3883 PGresult *res;
3886 int ncols = 2;
3887 int nrows = 0;
3888 int i;
3889 int conns;
3890 const char align = 'l';
3891 char **attr;
3892
3893 myopt.default_footer = false;
3894
3896
3898 "SELECT r.rolname, r.rolsuper, r.rolinherit,\n"
3899 " r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,\n"
3900 " r.rolconnlimit, r.rolvaliduntil");
3901
3902 if (verbose)
3903 {
3904 appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
3905 ncols++;
3906 }
3907 appendPQExpBufferStr(&buf, "\n, r.rolreplication");
3908
3909 if (pset.sversion >= 90500)
3910 {
3911 appendPQExpBufferStr(&buf, "\n, r.rolbypassrls");
3912 }
3913
3914 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_roles r\n");
3915
3916 if (!showSystem && !pattern)
3917 appendPQExpBufferStr(&buf, "WHERE r.rolname !~ '^pg_'\n");
3918
3919 if (!validateSQLNamePattern(&buf, pattern, false, false,
3920 NULL, "r.rolname", NULL, NULL,
3921 NULL, 1))
3922 {
3924 return false;
3925 }
3926
3927 appendPQExpBufferStr(&buf, "ORDER BY 1;");
3928
3929 res = PSQLexec(buf.data);
3930 if (!res)
3931 return false;
3932
3933 nrows = PQntuples(res);
3934 attr = pg_malloc0_array(char *, nrows + 1);
3935
3936 printTableInit(&cont, &myopt, _("List of roles"), ncols, nrows);
3937
3938 printTableAddHeader(&cont, gettext_noop("Role name"), true, align);
3939 printTableAddHeader(&cont, gettext_noop("Attributes"), true, align);
3940
3941 if (verbose)
3942 printTableAddHeader(&cont, gettext_noop("Description"), true, align);
3943
3944 for (i = 0; i < nrows; i++)
3945 {
3946 printTableAddCell(&cont, PQgetvalue(res, i, 0), false, false);
3947
3949 if (strcmp(PQgetvalue(res, i, 1), "t") == 0)
3950 add_role_attribute(&buf, _("Superuser"));
3951
3952 if (strcmp(PQgetvalue(res, i, 2), "t") != 0)
3953 add_role_attribute(&buf, _("No inheritance"));
3954
3955 if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
3956 add_role_attribute(&buf, _("Create role"));
3957
3958 if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
3959 add_role_attribute(&buf, _("Create DB"));
3960
3961 if (strcmp(PQgetvalue(res, i, 5), "t") != 0)
3962 add_role_attribute(&buf, _("Cannot login"));
3963
3964 if (strcmp(PQgetvalue(res, i, (verbose ? 9 : 8)), "t") == 0)
3965 add_role_attribute(&buf, _("Replication"));
3966
3967 if (pset.sversion >= 90500)
3968 if (strcmp(PQgetvalue(res, i, (verbose ? 10 : 9)), "t") == 0)
3969 add_role_attribute(&buf, _("Bypass RLS"));
3970
3971 conns = atoi(PQgetvalue(res, i, 6));
3972 if (conns >= 0)
3973 {
3974 if (buf.len > 0)
3975 appendPQExpBufferChar(&buf, '\n');
3976
3977 if (conns == 0)
3978 appendPQExpBufferStr(&buf, _("No connections"));
3979 else
3980 appendPQExpBuffer(&buf, ngettext("%d connection",
3981 "%d connections",
3982 conns),
3983 conns);
3984 }
3985
3986 if (strcmp(PQgetvalue(res, i, 7), "") != 0)
3987 {
3988 if (buf.len > 0)
3989 appendPQExpBufferChar(&buf, '\n');
3990 appendPQExpBufferStr(&buf, _("Password valid until "));
3992 }
3993
3994 attr[i] = pg_strdup(buf.data);
3995
3996 printTableAddCell(&cont, attr[i], false, false);
3997
3998 if (verbose)
3999 printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
4000 }
4002
4005
4006 for (i = 0; i < nrows; i++)
4007 free(attr[i]);
4008 free(attr);
4009
4010 PQclear(res);
4011 return true;
4012}
#define ngettext(s, p, n)
Definition c.h:1272
static void add_role_attribute(PQExpBuffer buf, const char *const str)
Definition describe.c:4015
#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 6979 of file describe.c.

6980{
6982 PGresult *res;
6984 static const bool translate_columns[] = {false, false, false, false,
6985 false, false, false, false, false, false, false, false, false, false,
6986 false, false, false, false, false, false, false};
6987
6988 if (pset.sversion < 100000)
6989 {
6990 char sverbuf[32];
6991
6992 pg_log_error("The server (version %s) does not support subscriptions.",
6994 sverbuf, sizeof(sverbuf)));
6995 return true;
6996 }
6997
6999
7001 "SELECT subname AS \"%s\"\n"
7002 ", pg_catalog.pg_get_userbyid(subowner) AS \"%s\"\n"
7003 ", subenabled AS \"%s\"\n"
7004 ", subpublications AS \"%s\"\n",
7005 gettext_noop("Name"),
7006 gettext_noop("Owner"),
7007 gettext_noop("Enabled"),
7008 gettext_noop("Publication"));
7009
7010 if (verbose)
7011 {
7012 /* Binary mode and streaming are only supported in v14 and higher */
7013 if (pset.sversion >= 140000)
7014 {
7016 ", subbinary AS \"%s\"\n",
7017 gettext_noop("Binary"));
7018
7019 if (pset.sversion >= 160000)
7021 ", (CASE substream\n"
7022 " WHEN " CppAsString2(LOGICALREP_STREAM_OFF) " THEN 'off'\n"
7023 " WHEN " CppAsString2(LOGICALREP_STREAM_ON) " THEN 'on'\n"
7024 " WHEN " CppAsString2(LOGICALREP_STREAM_PARALLEL) " THEN 'parallel'\n"
7025 " END) AS \"%s\"\n",
7026 gettext_noop("Streaming"));
7027 else
7029 ", substream AS \"%s\"\n",
7030 gettext_noop("Streaming"));
7031 }
7032
7033 /* Two_phase and disable_on_error are only supported in v15 and higher */
7034 if (pset.sversion >= 150000)
7036 ", subtwophasestate AS \"%s\"\n"
7037 ", subdisableonerr AS \"%s\"\n",
7038 gettext_noop("Two-phase commit"),
7039 gettext_noop("Disable on error"));
7040
7041 if (pset.sversion >= 160000)
7043 ", suborigin AS \"%s\"\n"
7044 ", subpasswordrequired AS \"%s\"\n"
7045 ", subrunasowner AS \"%s\"\n",
7046 gettext_noop("Origin"),
7047 gettext_noop("Password required"),
7048 gettext_noop("Run as owner?"));
7049
7050 if (pset.sversion >= 170000)
7052 ", subfailover AS \"%s\"\n",
7053 gettext_noop("Failover"));
7054 if (pset.sversion >= 190000)
7055 {
7057 ", (select srvname from pg_foreign_server where oid=subserver) AS \"%s\"\n",
7058 gettext_noop("Server"));
7059
7061 ", subretaindeadtuples AS \"%s\"\n",
7062 gettext_noop("Retain dead tuples"));
7063
7065 ", submaxretention AS \"%s\"\n",
7066 gettext_noop("Max retention duration"));
7067
7069 ", subretentionactive AS \"%s\"\n",
7070 gettext_noop("Retention active"));
7071 }
7072
7074 ", subsynccommit AS \"%s\"\n"
7075 ", subconninfo AS \"%s\"\n",
7076 gettext_noop("Synchronous commit"),
7077 gettext_noop("Conninfo"));
7078
7079 if (pset.sversion >= 190000)
7081 ", subwalrcvtimeout AS \"%s\"\n",
7082 gettext_noop("Receiver timeout"));
7083
7084 /* Skip LSN is only supported in v15 and higher */
7085 if (pset.sversion >= 150000)
7087 ", subskiplsn AS \"%s\"\n",
7088 gettext_noop("Skip LSN"));
7089
7091 ", pg_catalog.obj_description(oid, 'pg_subscription') AS \"%s\"\n",
7092 gettext_noop("Description"));
7093 }
7094
7095 /* Only display subscriptions in current database. */
7097 "FROM pg_catalog.pg_subscription\n"
7098 "WHERE subdbid = (SELECT oid\n"
7099 " FROM pg_catalog.pg_database\n"
7100 " WHERE datname = pg_catalog.current_database())");
7101
7102 if (!validateSQLNamePattern(&buf, pattern, true, false,
7103 NULL, "subname", NULL,
7104 NULL,
7105 NULL, 1))
7106 {
7108 return false;
7109 }
7110
7111 appendPQExpBufferStr(&buf, "ORDER BY 1;");
7112
7113 res = PSQLexec(buf.data);
7115 if (!res)
7116 return false;
7117
7118 myopt.title = _("List of subscriptions");
7119 myopt.translate_header = true;
7120 myopt.translate_columns = translate_columns;
7121 myopt.n_translate_columns = lengthof(translate_columns);
7122
7123 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7124
7125 PQclear(res);
7126 return true;
7127}

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

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

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

Referenced by exec_command_d().

◆ describeTablespaces()

bool describeTablespaces ( const char pattern,
bool  verbose 
)

Definition at line 223 of file describe.c.

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

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

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

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

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

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

5141{
5143 PGresult *res;
5145 static const bool translate_columns[] = {false, false, false, true, true, false};
5146
5148
5150 "SELECT pg_catalog.format_type(castsource, NULL) AS \"%s\",\n"
5151 " pg_catalog.format_type(casttarget, NULL) AS \"%s\",\n",
5152 gettext_noop("Source type"),
5153 gettext_noop("Target type"));
5154
5155 /*
5156 * We don't attempt to localize '(binary coercible)' or '(with inout)',
5157 * because there's too much risk of gettext translating a function name
5158 * that happens to match some string in the PO database.
5159 */
5161 " CASE WHEN c.castmethod = '%c' THEN '(binary coercible)'\n"
5162 " WHEN c.castmethod = '%c' THEN '(with inout)'\n"
5163 " ELSE p.proname\n"
5164 " END AS \"%s\",\n",
5167 gettext_noop("Function"));
5168
5170 " CASE WHEN c.castcontext = '%c' THEN '%s'\n"
5171 " WHEN c.castcontext = '%c' THEN '%s'\n"
5172 " ELSE '%s'\n"
5173 " END AS \"%s\"",
5175 gettext_noop("no"),
5177 gettext_noop("in assignment"),
5178 gettext_noop("yes"),
5179 gettext_noop("Implicit?"));
5180
5181 if (verbose)
5183 ",\n CASE WHEN p.proleakproof THEN '%s'\n"
5184 " ELSE '%s'\n"
5185 " END AS \"%s\",\n"
5186 " d.description AS \"%s\"",
5187 gettext_noop("yes"),
5188 gettext_noop("no"),
5189 gettext_noop("Leakproof?"),
5190 gettext_noop("Description"));
5191
5192 /*
5193 * We need a left join to pg_proc for binary casts; the others are just
5194 * paranoia.
5195 */
5197 "\nFROM pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p\n"
5198 " ON c.castfunc = p.oid\n"
5199 " LEFT JOIN pg_catalog.pg_type ts\n"
5200 " ON c.castsource = ts.oid\n"
5201 " LEFT JOIN pg_catalog.pg_namespace ns\n"
5202 " ON ns.oid = ts.typnamespace\n"
5203 " LEFT JOIN pg_catalog.pg_type tt\n"
5204 " ON c.casttarget = tt.oid\n"
5205 " LEFT JOIN pg_catalog.pg_namespace nt\n"
5206 " ON nt.oid = tt.typnamespace\n");
5207
5208 if (verbose)
5210 " LEFT JOIN pg_catalog.pg_description d\n"
5211 " ON d.classoid = c.tableoid AND d.objoid = "
5212 "c.oid AND d.objsubid = 0\n");
5213
5214 appendPQExpBufferStr(&buf, "WHERE ( (true");
5215
5216 /*
5217 * Match name pattern against either internal or external name of either
5218 * castsource or casttarget
5219 */
5220 if (!validateSQLNamePattern(&buf, pattern, true, false,
5221 "ns.nspname", "ts.typname",
5222 "pg_catalog.format_type(ts.oid, NULL)",
5223 "pg_catalog.pg_type_is_visible(ts.oid)",
5224 NULL, 3))
5225 goto error_return;
5226
5227 appendPQExpBufferStr(&buf, ") OR (true");
5228
5229 if (!validateSQLNamePattern(&buf, pattern, true, false,
5230 "nt.nspname", "tt.typname",
5231 "pg_catalog.format_type(tt.oid, NULL)",
5232 "pg_catalog.pg_type_is_visible(tt.oid)",
5233 NULL, 3))
5234 goto error_return;
5235
5236 appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;");
5237
5238 res = PSQLexec(buf.data);
5240 if (!res)
5241 return false;
5242
5243 myopt.title = _("List of casts");
5244 myopt.translate_header = true;
5245 myopt.translate_columns = translate_columns;
5246 myopt.n_translate_columns = lengthof(translate_columns);
5247
5248 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5249
5250 PQclear(res);
5251 return true;
5252
5255 return false;
5256}

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

5265{
5267 PGresult *res;
5269 static const bool translate_columns[] = {false, false, false, false, false, false, false, true, false};
5270
5272
5274 "SELECT\n"
5275 " n.nspname AS \"%s\",\n"
5276 " c.collname AS \"%s\",\n",
5277 gettext_noop("Schema"),
5278 gettext_noop("Name"));
5279
5280 if (pset.sversion >= 100000)
5282 " CASE c.collprovider "
5283 "WHEN " CppAsString2(COLLPROVIDER_DEFAULT) " THEN 'default' "
5284 "WHEN " CppAsString2(COLLPROVIDER_BUILTIN) " THEN 'builtin' "
5285 "WHEN " CppAsString2(COLLPROVIDER_LIBC) " THEN 'libc' "
5286 "WHEN " CppAsString2(COLLPROVIDER_ICU) " THEN 'icu' "
5287 "END AS \"%s\",\n",
5288 gettext_noop("Provider"));
5289 else
5291 " 'libc' AS \"%s\",\n",
5292 gettext_noop("Provider"));
5293
5295 " c.collcollate AS \"%s\",\n"
5296 " c.collctype AS \"%s\",\n",
5297 gettext_noop("Collate"),
5298 gettext_noop("Ctype"));
5299
5300 if (pset.sversion >= 170000)
5302 " c.colllocale AS \"%s\",\n",
5303 gettext_noop("Locale"));
5304 else if (pset.sversion >= 150000)
5306 " c.colliculocale AS \"%s\",\n",
5307 gettext_noop("Locale"));
5308 else
5310 " c.collcollate AS \"%s\",\n",
5311 gettext_noop("Locale"));
5312
5313 if (pset.sversion >= 160000)
5315 " c.collicurules AS \"%s\",\n",
5316 gettext_noop("ICU Rules"));
5317 else
5319 " NULL AS \"%s\",\n",
5320 gettext_noop("ICU Rules"));
5321
5322 if (pset.sversion >= 120000)
5324 " CASE WHEN c.collisdeterministic THEN '%s' ELSE '%s' END AS \"%s\"",
5325 gettext_noop("yes"), gettext_noop("no"),
5326 gettext_noop("Deterministic?"));
5327 else
5329 " '%s' AS \"%s\"",
5330 gettext_noop("yes"),
5331 gettext_noop("Deterministic?"));
5332
5333 if (verbose)
5335 ",\n pg_catalog.obj_description(c.oid, 'pg_collation') AS \"%s\"",
5336 gettext_noop("Description"));
5337
5339 "\nFROM pg_catalog.pg_collation c, pg_catalog.pg_namespace n\n"
5340 "WHERE n.oid = c.collnamespace\n");
5341
5342 if (!showSystem && !pattern)
5343 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
5344 " AND n.nspname <> 'information_schema'\n");
5345
5346 /*
5347 * Hide collations that aren't usable in the current database's encoding.
5348 * If you think to change this, note that pg_collation_is_visible rejects
5349 * unusable collations, so you will need to hack name pattern processing
5350 * somehow to avoid inconsistent behavior.
5351 */
5352 appendPQExpBufferStr(&buf, " AND c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))\n");
5353
5354 if (!validateSQLNamePattern(&buf, pattern, true, false,
5355 "n.nspname", "c.collname", NULL,
5356 "pg_catalog.pg_collation_is_visible(c.oid)",
5357 NULL, 3))
5358 {
5360 return false;
5361 }
5362
5363 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5364
5365 res = PSQLexec(buf.data);
5367 if (!res)
5368 return false;
5369
5370 myopt.title = _("List of collations");
5371 myopt.translate_header = true;
5372 myopt.translate_columns = translate_columns;
5373 myopt.n_translate_columns = lengthof(translate_columns);
5374
5375 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5376
5377 PQclear(res);
5378 return true;
5379}

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

4812{
4814 PGresult *res;
4816 static const bool translate_columns[] =
4817 {false, false, false, false, true, false};
4818
4820
4822 "SELECT n.nspname AS \"%s\",\n"
4823 " c.conname AS \"%s\",\n"
4824 " pg_catalog.pg_encoding_to_char(c.conforencoding) AS \"%s\",\n"
4825 " pg_catalog.pg_encoding_to_char(c.contoencoding) AS \"%s\",\n"
4826 " CASE WHEN c.condefault THEN '%s'\n"
4827 " ELSE '%s' END AS \"%s\"",
4828 gettext_noop("Schema"),
4829 gettext_noop("Name"),
4830 gettext_noop("Source"),
4831 gettext_noop("Destination"),
4832 gettext_noop("yes"), gettext_noop("no"),
4833 gettext_noop("Default?"));
4834
4835 if (verbose)
4837 ",\n d.description AS \"%s\"",
4838 gettext_noop("Description"));
4839
4841 "\nFROM pg_catalog.pg_conversion c\n"
4842 " JOIN pg_catalog.pg_namespace n "
4843 "ON n.oid = c.connamespace\n");
4844
4845 if (verbose)
4847 "LEFT JOIN pg_catalog.pg_description d "
4848 "ON d.classoid = c.tableoid\n"
4849 " AND d.objoid = c.oid "
4850 "AND d.objsubid = 0\n");
4851
4852 appendPQExpBufferStr(&buf, "WHERE true\n");
4853
4854 if (!showSystem && !pattern)
4855 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4856 " AND n.nspname <> 'information_schema'\n");
4857
4858 if (!validateSQLNamePattern(&buf, pattern, true, false,
4859 "n.nspname", "c.conname", NULL,
4860 "pg_catalog.pg_conversion_is_visible(c.oid)",
4861 NULL, 3))
4862 {
4864 return false;
4865 }
4866
4867 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4868
4869 res = PSQLexec(buf.data);
4871 if (!res)
4872 return false;
4873
4874 myopt.title = _("List of conversions");
4875 myopt.translate_header = true;
4876 myopt.translate_columns = translate_columns;
4877 myopt.n_translate_columns = lengthof(translate_columns);
4878
4879 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4880
4881 PQclear(res);
4882 return true;
4883}

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

4028{
4030 PGresult *res;
4032 bool havewhere;
4033
4035
4036 printfPQExpBuffer(&buf, "SELECT rolname AS \"%s\", datname AS \"%s\",\n"
4037 "pg_catalog.array_to_string(setconfig, E'\\n') AS \"%s\"\n"
4038 "FROM pg_catalog.pg_db_role_setting s\n"
4039 "LEFT JOIN pg_catalog.pg_database d ON d.oid = setdatabase\n"
4040 "LEFT JOIN pg_catalog.pg_roles r ON r.oid = setrole\n",
4041 gettext_noop("Role"),
4042 gettext_noop("Database"),
4043 gettext_noop("Settings"));
4044 if (!validateSQLNamePattern(&buf, pattern, false, false,
4045 NULL, "r.rolname", NULL, NULL, &havewhere, 1))
4046 goto error_return;
4048 NULL, "d.datname", NULL, NULL,
4049 NULL, 1))
4050 goto error_return;
4051 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4052
4053 res = PSQLexec(buf.data);
4055 if (!res)
4056 return false;
4057
4058 /*
4059 * Most functions in this file are content to print an empty table when
4060 * there are no matching objects. We intentionally deviate from that
4061 * here, but only in !quiet mode, because of the possibility that the user
4062 * is confused about what the two pattern arguments mean.
4063 */
4064 if (PQntuples(res) == 0 && !pset.quiet)
4065 {
4066 if (pattern && pattern2)
4067 pg_log_error("Did not find any settings for role \"%s\" and database \"%s\".",
4068 pattern, pattern2);
4069 else if (pattern)
4070 pg_log_error("Did not find any settings for role \"%s\".",
4071 pattern);
4072 else
4073 pg_log_error("Did not find any settings.");
4074 }
4075 else
4076 {
4077 myopt.title = _("List of settings");
4078 myopt.translate_header = true;
4079
4080 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4081 }
4082
4083 PQclear(res);
4084 return true;
4085
4088 return false;
4089}

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

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

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

4729{
4731 PGresult *res;
4733
4735
4737 "SELECT n.nspname as \"%s\",\n"
4738 " t.typname as \"%s\",\n"
4739 " pg_catalog.format_type(t.typbasetype, t.typtypmod) as \"%s\",\n"
4740 " (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type bt\n"
4741 " WHERE c.oid = t.typcollation AND bt.oid = t.typbasetype AND t.typcollation <> bt.typcollation) as \"%s\",\n"
4742 " CASE WHEN t.typnotnull THEN 'not null' END as \"%s\",\n"
4743 " t.typdefault as \"%s\",\n"
4744 " pg_catalog.array_to_string(ARRAY(\n"
4745 " 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"
4746 " ), ' ') as \"%s\"",
4747 gettext_noop("Schema"),
4748 gettext_noop("Name"),
4749 gettext_noop("Type"),
4750 gettext_noop("Collation"),
4751 gettext_noop("Nullable"),
4752 gettext_noop("Default"),
4753 gettext_noop("Check"));
4754
4755 if (verbose)
4756 {
4757 appendPQExpBufferStr(&buf, ",\n ");
4758 printACLColumn(&buf, "t.typacl");
4760 ",\n d.description as \"%s\"",
4761 gettext_noop("Description"));
4762 }
4763
4765 "\nFROM pg_catalog.pg_type t\n"
4766 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
4767
4768 if (verbose)
4770 " LEFT JOIN pg_catalog.pg_description d "
4771 "ON d.classoid = t.tableoid AND d.objoid = t.oid "
4772 "AND d.objsubid = 0\n");
4773
4774 appendPQExpBufferStr(&buf, "WHERE t.typtype = 'd'\n");
4775
4776 if (!showSystem && !pattern)
4777 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4778 " AND n.nspname <> 'information_schema'\n");
4779
4780 if (!validateSQLNamePattern(&buf, pattern, true, false,
4781 "n.nspname", "t.typname", NULL,
4782 "pg_catalog.pg_type_is_visible(t.oid)",
4783 NULL, 3))
4784 {
4786 return false;
4787 }
4788
4789 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
4790
4791 res = PSQLexec(buf.data);
4793 if (!res)
4794 return false;
4795
4796 myopt.title = _("List of domains");
4797 myopt.translate_header = true;
4798
4799 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4800
4801 PQclear(res);
4802 return true;
4803}

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

4960{
4962 PGresult *res;
4964 static const bool translate_columns[] =
4965 {false, false, false, true, false, false, false};
4966
4967 if (pset.sversion < 90300)
4968 {
4969 char sverbuf[32];
4970
4971 pg_log_error("The server (version %s) does not support event triggers.",
4973 sverbuf, sizeof(sverbuf)));
4974 return true;
4975 }
4976
4978
4980 "SELECT evtname as \"%s\", "
4981 "evtevent as \"%s\", "
4982 "pg_catalog.pg_get_userbyid(e.evtowner) as \"%s\",\n"
4983 " case evtenabled when 'O' then '%s'"
4984 " when 'R' then '%s'"
4985 " when 'A' then '%s'"
4986 " when 'D' then '%s' end as \"%s\",\n"
4987 " e.evtfoid::pg_catalog.regproc as \"%s\", "
4988 "pg_catalog.array_to_string(array(select x"
4989 " from pg_catalog.unnest(evttags) as t(x)), ', ') as \"%s\"",
4990 gettext_noop("Name"),
4991 gettext_noop("Event"),
4992 gettext_noop("Owner"),
4993 gettext_noop("enabled"),
4994 gettext_noop("replica"),
4995 gettext_noop("always"),
4996 gettext_noop("disabled"),
4997 gettext_noop("Enabled"),
4998 gettext_noop("Function"),
4999 gettext_noop("Tags"));
5000 if (verbose)
5002 ",\npg_catalog.obj_description(e.oid, 'pg_event_trigger') as \"%s\"",
5003 gettext_noop("Description"));
5005 "\nFROM pg_catalog.pg_event_trigger e ");
5006
5007 if (!validateSQLNamePattern(&buf, pattern, false, false,
5008 NULL, "evtname", NULL, NULL,
5009 NULL, 1))
5010 {
5012 return false;
5013 }
5014
5015 appendPQExpBufferStr(&buf, "ORDER BY 1");
5016
5017 res = PSQLexec(buf.data);
5019 if (!res)
5020 return false;
5021
5022 myopt.title = _("List of event triggers");
5023 myopt.translate_header = true;
5024 myopt.translate_columns = translate_columns;
5025 myopt.n_translate_columns = lengthof(translate_columns);
5026
5027 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5028
5029 PQclear(res);
5030 return true;
5031}

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

5040{
5042 PGresult *res;
5044
5045 if (pset.sversion < 100000)
5046 {
5047 char sverbuf[32];
5048
5049 pg_log_error("The server (version %s) does not support extended statistics.",
5051 sverbuf, sizeof(sverbuf)));
5052 return true;
5053 }
5054
5057 "SELECT \n"
5058 "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text AS \"%s\", \n"
5059 "es.stxname AS \"%s\", \n",
5060 gettext_noop("Schema"),
5061 gettext_noop("Name"));
5062
5063 if (pset.sversion >= 140000)
5065 "pg_catalog.format('%%s FROM %%s', \n"
5066 " pg_catalog.pg_get_statisticsobjdef_columns(es.oid), \n"
5067 " es.stxrelid::pg_catalog.regclass) AS \"%s\"",
5068 gettext_noop("Definition"));
5069 else
5071 "pg_catalog.format('%%s FROM %%s', \n"
5072 " (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(a.attname),', ') \n"
5073 " FROM pg_catalog.unnest(es.stxkeys) s(attnum) \n"
5074 " JOIN pg_catalog.pg_attribute a \n"
5075 " ON (es.stxrelid = a.attrelid \n"
5076 " AND a.attnum = s.attnum \n"
5077 " AND NOT a.attisdropped)), \n"
5078 "es.stxrelid::pg_catalog.regclass) AS \"%s\"",
5079 gettext_noop("Definition"));
5080
5082 ",\nCASE WHEN " CppAsString2(STATS_EXT_NDISTINCT) " = any(es.stxkind) THEN 'defined' \n"
5083 "END AS \"%s\", \n"
5084 "CASE WHEN " CppAsString2(STATS_EXT_DEPENDENCIES) " = any(es.stxkind) THEN 'defined' \n"
5085 "END AS \"%s\"",
5086 gettext_noop("Ndistinct"),
5087 gettext_noop("Dependencies"));
5088
5089 /*
5090 * Include the MCV statistics kind.
5091 */
5092 if (pset.sversion >= 120000)
5093 {
5095 ",\nCASE WHEN " CppAsString2(STATS_EXT_MCV) " = any(es.stxkind) THEN 'defined' \n"
5096 "END AS \"%s\" ",
5097 gettext_noop("MCV"));
5098 }
5099
5100 if (verbose)
5102 ", \npg_catalog.obj_description(oid, 'pg_statistic_ext') AS \"%s\"\n",
5103 gettext_noop("Description"));
5104
5106 " \nFROM pg_catalog.pg_statistic_ext es \n");
5107
5108 if (!validateSQLNamePattern(&buf, pattern,
5109 false, false,
5110 "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text", "es.stxname",
5111 NULL, "pg_catalog.pg_statistics_obj_is_visible(es.oid)",
5112 NULL, 3))
5113 {
5115 return false;
5116 }
5117
5118 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5119
5120 res = PSQLexec(buf.data);
5122 if (!res)
5123 return false;
5124
5125 myopt.title = _("List of extended statistics");
5126 myopt.translate_header = true;
5127
5128 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5129
5130 PQclear(res);
5131 return true;
5132}

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

6418{
6420 PGresult *res;
6421 int i;
6422
6425 "SELECT e.extname, e.oid\n"
6426 "FROM pg_catalog.pg_extension e\n");
6427
6428 if (!validateSQLNamePattern(&buf, pattern,
6429 false, false,
6430 NULL, "e.extname", NULL,
6431 NULL,
6432 NULL, 1))
6433 {
6435 return false;
6436 }
6437
6438 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6439
6440 res = PSQLexec(buf.data);
6442 if (!res)
6443 return false;
6444
6445 if (PQntuples(res) == 0)
6446 {
6447 if (!pset.quiet)
6448 {
6449 if (pattern)
6450 pg_log_error("Did not find any extension named \"%s\".",
6451 pattern);
6452 else
6453 pg_log_error("Did not find any extensions.");
6454 }
6455 PQclear(res);
6456 return false;
6457 }
6458
6459 for (i = 0; i < PQntuples(res); i++)
6460 {
6461 const char *extname;
6462 const char *oid;
6463
6464 extname = PQgetvalue(res, i, 0);
6465 oid = PQgetvalue(res, i, 1);
6466
6467 if (!listOneExtensionContents(extname, oid))
6468 {
6469 PQclear(res);
6470 return false;
6471 }
6472 if (cancel_pressed)
6473 {
6474 PQclear(res);
6475 return false;
6476 }
6477 }
6478
6479 PQclear(res);
6480 return true;
6481}
static bool listOneExtensionContents(const char *extname, const char *oid)
Definition describe.c:6484

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

Referenced by exec_command_d().

◆ listExtensions()

bool listExtensions ( const char pattern)

Definition at line 6363 of file describe.c.

6364{
6366 PGresult *res;
6368
6371 "SELECT e.extname AS \"%s\", "
6372 "e.extversion AS \"%s\", ae.default_version AS \"%s\","
6373 "n.nspname AS \"%s\", d.description AS \"%s\"\n"
6374 "FROM pg_catalog.pg_extension e "
6375 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace "
6376 "LEFT JOIN pg_catalog.pg_description d ON d.objoid = e.oid "
6377 "AND d.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass "
6378 "LEFT JOIN pg_catalog.pg_available_extensions() ae(name, default_version, comment) ON ae.name = e.extname\n",
6379 gettext_noop("Name"),
6380 gettext_noop("Version"),
6381 gettext_noop("Default version"),
6382 gettext_noop("Schema"),
6383 gettext_noop("Description"));
6384
6385 if (!validateSQLNamePattern(&buf, pattern,
6386 false, false,
6387 NULL, "e.extname", NULL,
6388 NULL,
6389 NULL, 1))
6390 {
6392 return false;
6393 }
6394
6395 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6396
6397 res = PSQLexec(buf.data);
6399 if (!res)
6400 return false;
6401
6402 myopt.title = _("List of installed extensions");
6403 myopt.translate_header = true;
6404
6405 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6406
6407 PQclear(res);
6408 return true;
6409}

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

6090{
6092 PGresult *res;
6094
6097 "SELECT fdw.fdwname AS \"%s\",\n"
6098 " pg_catalog.pg_get_userbyid(fdw.fdwowner) AS \"%s\",\n"
6099 " fdw.fdwhandler::pg_catalog.regproc AS \"%s\",\n"
6100 " fdw.fdwvalidator::pg_catalog.regproc AS \"%s\"",
6101 gettext_noop("Name"),
6102 gettext_noop("Owner"),
6103 gettext_noop("Handler"),
6104 gettext_noop("Validator"));
6105
6106 if (verbose)
6107 {
6108 appendPQExpBufferStr(&buf, ",\n ");
6109 printACLColumn(&buf, "fdwacl");
6111 ",\n CASE WHEN fdwoptions IS NULL THEN '' ELSE "
6112 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6113 " pg_catalog.quote_ident(option_name) || ' ' || "
6114 " pg_catalog.quote_literal(option_value) FROM "
6115 " pg_catalog.pg_options_to_table(fdwoptions)), ', ') || ')' "
6116 " END AS \"%s\""
6117 ",\n d.description AS \"%s\" ",
6118 gettext_noop("FDW options"),
6119 gettext_noop("Description"));
6120 }
6121
6122 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
6123
6124 if (verbose)
6126 "LEFT JOIN pg_catalog.pg_description d\n"
6127 " ON d.classoid = fdw.tableoid "
6128 "AND d.objoid = fdw.oid AND d.objsubid = 0\n");
6129
6130 if (!validateSQLNamePattern(&buf, pattern, false, false,
6131 NULL, "fdwname", NULL, NULL,
6132 NULL, 1))
6133 {
6135 return false;
6136 }
6137
6138 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6139
6140 res = PSQLexec(buf.data);
6142 if (!res)
6143 return false;
6144
6145 myopt.title = _("List of foreign-data wrappers");
6146 myopt.translate_header = true;
6147
6148 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6149
6150 PQclear(res);
6151 return true;
6152}

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

6161{
6163 PGresult *res;
6165
6168 "SELECT s.srvname AS \"%s\",\n"
6169 " pg_catalog.pg_get_userbyid(s.srvowner) AS \"%s\",\n"
6170 " f.fdwname AS \"%s\"",
6171 gettext_noop("Name"),
6172 gettext_noop("Owner"),
6173 gettext_noop("Foreign-data wrapper"));
6174
6175 if (verbose)
6176 {
6177 appendPQExpBufferStr(&buf, ",\n ");
6178 printACLColumn(&buf, "s.srvacl");
6180 ",\n"
6181 " s.srvtype AS \"%s\",\n"
6182 " s.srvversion AS \"%s\",\n"
6183 " CASE WHEN srvoptions IS NULL THEN '' ELSE "
6184 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6185 " pg_catalog.quote_ident(option_name) || ' ' || "
6186 " pg_catalog.quote_literal(option_value) FROM "
6187 " pg_catalog.pg_options_to_table(srvoptions)), ', ') || ')' "
6188 " END AS \"%s\",\n"
6189 " d.description AS \"%s\"",
6190 gettext_noop("Type"),
6191 gettext_noop("Version"),
6192 gettext_noop("FDW options"),
6193 gettext_noop("Description"));
6194 }
6195
6197 "\nFROM pg_catalog.pg_foreign_server s\n"
6198 " JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid=s.srvfdw\n");
6199
6200 if (verbose)
6202 "LEFT JOIN pg_catalog.pg_description d\n "
6203 "ON d.classoid = s.tableoid AND d.objoid = s.oid "
6204 "AND d.objsubid = 0\n");
6205
6206 if (!validateSQLNamePattern(&buf, pattern, false, false,
6207 NULL, "s.srvname", NULL, NULL,
6208 NULL, 1))
6209 {
6211 return false;
6212 }
6213
6214 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6215
6216 res = PSQLexec(buf.data);
6218 if (!res)
6219 return false;
6220
6221 myopt.title = _("List of foreign servers");
6222 myopt.translate_header = true;
6223
6224 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6225
6226 PQclear(res);
6227 return true;
6228}

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

6292{
6294 PGresult *res;
6296
6299 "SELECT n.nspname AS \"%s\",\n"
6300 " c.relname AS \"%s\",\n"
6301 " s.srvname AS \"%s\"",
6302 gettext_noop("Schema"),
6303 gettext_noop("Table"),
6304 gettext_noop("Server"));
6305
6306 if (verbose)
6308 ",\n CASE WHEN ftoptions IS NULL THEN '' ELSE "
6309 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6310 " pg_catalog.quote_ident(option_name) || ' ' || "
6311 " pg_catalog.quote_literal(option_value) FROM "
6312 " pg_catalog.pg_options_to_table(ftoptions)), ', ') || ')' "
6313 " END AS \"%s\",\n"
6314 " d.description AS \"%s\"",
6315 gettext_noop("FDW options"),
6316 gettext_noop("Description"));
6317
6319 "\nFROM pg_catalog.pg_foreign_table ft\n"
6320 " INNER JOIN pg_catalog.pg_class c"
6321 " ON c.oid = ft.ftrelid\n"
6322 " INNER JOIN pg_catalog.pg_namespace n"
6323 " ON n.oid = c.relnamespace\n"
6324 " INNER JOIN pg_catalog.pg_foreign_server s"
6325 " ON s.oid = ft.ftserver\n");
6326 if (verbose)
6328 " LEFT JOIN pg_catalog.pg_description d\n"
6329 " ON d.classoid = c.tableoid AND "
6330 "d.objoid = c.oid AND d.objsubid = 0\n");
6331
6332 if (!validateSQLNamePattern(&buf, pattern, false, false,
6333 "n.nspname", "c.relname", NULL,
6334 "pg_catalog.pg_table_is_visible(c.oid)",
6335 NULL, 3))
6336 {
6338 return false;
6339 }
6340
6341 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
6342
6343 res = PSQLexec(buf.data);
6345 if (!res)
6346 return false;
6347
6348 myopt.title = _("List of foreign tables");
6349 myopt.translate_header = true;
6350
6351 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6352
6353 PQclear(res);
6354 return true;
6355}

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

4653{
4655 PGresult *res;
4657
4659
4661 "SELECT l.lanname AS \"%s\",\n"
4662 " pg_catalog.pg_get_userbyid(l.lanowner) as \"%s\",\n"
4663 " l.lanpltrusted AS \"%s\"",
4664 gettext_noop("Name"),
4665 gettext_noop("Owner"),
4666 gettext_noop("Trusted"));
4667
4668 if (verbose)
4669 {
4671 ",\n NOT l.lanispl AS \"%s\",\n"
4672 " l.lanplcallfoid::pg_catalog.regprocedure AS \"%s\",\n"
4673 " l.lanvalidator::pg_catalog.regprocedure AS \"%s\",\n "
4674 "l.laninline::pg_catalog.regprocedure AS \"%s\",\n ",
4675 gettext_noop("Internal language"),
4676 gettext_noop("Call handler"),
4677 gettext_noop("Validator"),
4678 gettext_noop("Inline handler"));
4679 printACLColumn(&buf, "l.lanacl");
4680 }
4681
4683 ",\n d.description AS \"%s\""
4684 "\nFROM pg_catalog.pg_language l\n"
4685 "LEFT JOIN pg_catalog.pg_description d\n"
4686 " ON d.classoid = l.tableoid AND d.objoid = l.oid\n"
4687 " AND d.objsubid = 0\n",
4688 gettext_noop("Description"));
4689
4690 if (pattern)
4691 {
4692 if (!validateSQLNamePattern(&buf, pattern, false, false,
4693 NULL, "l.lanname", NULL, NULL,
4694 NULL, 2))
4695 {
4697 return false;
4698 }
4699 }
4700
4701 if (!showSystem && !pattern)
4702 appendPQExpBufferStr(&buf, "WHERE l.lanplcallfoid != 0\n");
4703
4704
4705 appendPQExpBufferStr(&buf, "ORDER BY 1;");
4706
4707 res = PSQLexec(buf.data);
4709 if (!res)
4710 return false;
4711
4712 myopt.title = _("List of languages");
4713 myopt.translate_header = true;
4714
4715 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4716
4717 PQclear(res);
4718 return true;
4719}

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

7545{
7547 PGresult *res;
7549
7551
7553 "SELECT oid as \"%s\",\n"
7554 " pg_catalog.pg_get_userbyid(lomowner) as \"%s\",\n ",
7555 gettext_noop("ID"),
7556 gettext_noop("Owner"));
7557
7558 if (verbose)
7559 {
7560 printACLColumn(&buf, "lomacl");
7561 appendPQExpBufferStr(&buf, ",\n ");
7562 }
7563
7565 "pg_catalog.obj_description(oid, 'pg_largeobject') as \"%s\"\n"
7566 "FROM pg_catalog.pg_largeobject_metadata\n"
7567 "ORDER BY oid",
7568 gettext_noop("Description"));
7569
7570 res = PSQLexec(buf.data);
7572 if (!res)
7573 return false;
7574
7575 myopt.title = _("Large objects");
7576 myopt.translate_header = true;
7577
7578 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7579
7580 PQclear(res);
7581 return true;
7582}

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

6485{
6487 PGresult *res;
6488 PQExpBufferData title;
6490
6493 "SELECT pg_catalog.pg_describe_object(classid, objid, 0) AS \"%s\"\n"
6494 "FROM pg_catalog.pg_depend\n"
6495 "WHERE refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass AND refobjid = '%s' AND deptype = 'e'\n"
6496 "ORDER BY 1;",
6497 gettext_noop("Object description"),
6498 oid);
6499
6500 res = PSQLexec(buf.data);
6502 if (!res)
6503 return false;
6504
6505 initPQExpBuffer(&title);
6506 printfPQExpBuffer(&title, _("Objects in extension \"%s\""), extname);
6507 myopt.title = title.data;
6508 myopt.translate_header = true;
6509
6510 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6511
6512 termPQExpBuffer(&title);
6513 PQclear(res);
6514 return true;
6515}

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

7160{
7162 PGresult *res;
7164 bool have_where = false;
7165 static const bool translate_columns[] = {false, false, false, false, false, false, false};
7166
7168
7170 "SELECT\n"
7171 " am.amname AS \"%s\",\n"
7172 " pg_catalog.format_type(c.opcintype, NULL) AS \"%s\",\n"
7173 " CASE\n"
7174 " WHEN c.opckeytype <> 0 AND c.opckeytype <> c.opcintype\n"
7175 " THEN pg_catalog.format_type(c.opckeytype, NULL)\n"
7176 " ELSE NULL\n"
7177 " END AS \"%s\",\n"
7178 " CASE\n"
7179 " WHEN pg_catalog.pg_opclass_is_visible(c.oid)\n"
7180 " THEN pg_catalog.format('%%I', c.opcname)\n"
7181 " ELSE pg_catalog.format('%%I.%%I', n.nspname, c.opcname)\n"
7182 " END AS \"%s\",\n"
7183 " (CASE WHEN c.opcdefault\n"
7184 " THEN '%s'\n"
7185 " ELSE '%s'\n"
7186 " END) AS \"%s\"",
7187 gettext_noop("AM"),
7188 gettext_noop("Input type"),
7189 gettext_noop("Storage type"),
7190 gettext_noop("Operator class"),
7191 gettext_noop("yes"),
7192 gettext_noop("no"),
7193 gettext_noop("Default?"));
7194 if (verbose)
7196 ",\n CASE\n"
7197 " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
7198 " THEN pg_catalog.format('%%I', of.opfname)\n"
7199 " ELSE pg_catalog.format('%%I.%%I', ofn.nspname, of.opfname)\n"
7200 " END AS \"%s\",\n"
7201 " pg_catalog.pg_get_userbyid(c.opcowner) AS \"%s\"\n",
7202 gettext_noop("Operator family"),
7203 gettext_noop("Owner"));
7205 "\nFROM pg_catalog.pg_opclass c\n"
7206 " LEFT JOIN pg_catalog.pg_am am on am.oid = c.opcmethod\n"
7207 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.opcnamespace\n"
7208 " LEFT JOIN pg_catalog.pg_type t ON t.oid = c.opcintype\n"
7209 " LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n");
7210 if (verbose)
7212 " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = c.opcfamily\n"
7213 " LEFT JOIN pg_catalog.pg_namespace ofn ON ofn.oid = of.opfnamespace\n");
7214
7217 false, false, NULL, "am.amname", NULL, NULL,
7218 &have_where, 1))
7219 goto error_return;
7220 if (type_pattern)
7221 {
7222 /* Match type name pattern against either internal or external name */
7224 "tn.nspname", "t.typname",
7225 "pg_catalog.format_type(t.oid, NULL)",
7226 "pg_catalog.pg_type_is_visible(t.oid)",
7227 NULL, 3))
7228 goto error_return;
7229 }
7230
7231 appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
7232 res = PSQLexec(buf.data);
7234 if (!res)
7235 return false;
7236
7237 myopt.title = _("List of operator classes");
7238 myopt.translate_header = true;
7239 myopt.translate_columns = translate_columns;
7240 myopt.n_translate_columns = lengthof(translate_columns);
7241
7242 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7243
7244 PQclear(res);
7245 return true;
7246
7249 return false;
7250}

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

7261{
7263 PGresult *res;
7265 bool have_where = false;
7266 static const bool translate_columns[] = {false, false, false, false};
7267
7269
7271 "SELECT\n"
7272 " am.amname AS \"%s\",\n"
7273 " CASE\n"
7274 " WHEN pg_catalog.pg_opfamily_is_visible(f.oid)\n"
7275 " THEN pg_catalog.format('%%I', f.opfname)\n"
7276 " ELSE pg_catalog.format('%%I.%%I', n.nspname, f.opfname)\n"
7277 " END AS \"%s\",\n"
7278 " (SELECT\n"
7279 " pg_catalog.string_agg(pg_catalog.format_type(oc.opcintype, NULL), ', ')\n"
7280 " FROM pg_catalog.pg_opclass oc\n"
7281 " WHERE oc.opcfamily = f.oid) \"%s\"",
7282 gettext_noop("AM"),
7283 gettext_noop("Operator family"),
7284 gettext_noop("Applicable types"));
7285 if (verbose)
7287 ",\n pg_catalog.pg_get_userbyid(f.opfowner) AS \"%s\"\n",
7288 gettext_noop("Owner"));
7290 "\nFROM pg_catalog.pg_opfamily f\n"
7291 " LEFT JOIN pg_catalog.pg_am am on am.oid = f.opfmethod\n"
7292 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = f.opfnamespace\n");
7293
7296 false, false, NULL, "am.amname", NULL, NULL,
7297 &have_where, 1))
7298 goto error_return;
7299 if (type_pattern)
7300 {
7302 " %s EXISTS (\n"
7303 " SELECT 1\n"
7304 " FROM pg_catalog.pg_type t\n"
7305 " JOIN pg_catalog.pg_opclass oc ON oc.opcintype = t.oid\n"
7306 " LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n"
7307 " WHERE oc.opcfamily = f.oid\n",
7308 have_where ? "AND" : "WHERE");
7309 /* Match type name pattern against either internal or external name */
7310 if (!validateSQLNamePattern(&buf, type_pattern, true, false,
7311 "tn.nspname", "t.typname",
7312 "pg_catalog.format_type(t.oid, NULL)",
7313 "pg_catalog.pg_type_is_visible(t.oid)",
7314 NULL, 3))
7315 goto error_return;
7316 appendPQExpBufferStr(&buf, " )\n");
7317 }
7318
7319 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
7320 res = PSQLexec(buf.data);
7322 if (!res)
7323 return false;
7324
7325 myopt.title = _("List of operator families");
7326 myopt.translate_header = true;
7327 myopt.translate_columns = translate_columns;
7328 myopt.n_translate_columns = lengthof(translate_columns);
7329
7330 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7331
7332 PQclear(res);
7333 return true;
7334
7337 return false;
7338}

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

7457{
7459 PGresult *res;
7461 bool have_where = false;
7462 static const bool translate_columns[] = {false, false, false, false, false, false};
7463
7465
7467 "SELECT\n"
7468 " am.amname AS \"%s\",\n"
7469 " CASE\n"
7470 " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
7471 " THEN pg_catalog.format('%%I', of.opfname)\n"
7472 " ELSE pg_catalog.format('%%I.%%I', ns.nspname, of.opfname)\n"
7473 " END AS \"%s\",\n"
7474 " pg_catalog.format_type(ap.amproclefttype, NULL) AS \"%s\",\n"
7475 " pg_catalog.format_type(ap.amprocrighttype, NULL) AS \"%s\",\n"
7476 " ap.amprocnum AS \"%s\"\n",
7477 gettext_noop("AM"),
7478 gettext_noop("Operator family"),
7479 gettext_noop("Registered left type"),
7480 gettext_noop("Registered right type"),
7481 gettext_noop("Number"));
7482
7483 if (!verbose)
7485 ", p.proname AS \"%s\"\n",
7486 gettext_noop("Function"));
7487 else
7489 ", ap.amproc::pg_catalog.regprocedure AS \"%s\"\n",
7490 gettext_noop("Function"));
7491
7493 "FROM pg_catalog.pg_amproc ap\n"
7494 " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = ap.amprocfamily\n"
7495 " LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod\n"
7496 " LEFT JOIN pg_catalog.pg_namespace ns ON of.opfnamespace = ns.oid\n"
7497 " LEFT JOIN pg_catalog.pg_proc p ON ap.amproc = p.oid\n");
7498
7500 {
7502 false, false, NULL, "am.amname",
7503 NULL, NULL,
7504 &have_where, 1))
7505 goto error_return;
7506 }
7507 if (family_pattern)
7508 {
7510 "ns.nspname", "of.opfname", NULL, NULL,
7511 NULL, 3))
7512 goto error_return;
7513 }
7514
7515 appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
7516 " ap.amproclefttype = ap.amprocrighttype DESC,\n"
7517 " 3, 4, 5;");
7518
7519 res = PSQLexec(buf.data);
7521 if (!res)
7522 return false;
7523
7524 myopt.title = _("List of support functions of operator families");
7525 myopt.translate_header = true;
7526 myopt.translate_columns = translate_columns;
7527 myopt.n_translate_columns = lengthof(translate_columns);
7528
7529 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7530
7531 PQclear(res);
7532 return true;
7533
7536 return false;
7537}

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

7350{
7352 PGresult *res;
7354 bool have_where = false;
7355
7356 static const bool translate_columns[] = {false, false, false, false, false, false, true};
7357
7359
7361 "SELECT\n"
7362 " am.amname AS \"%s\",\n"
7363 " CASE\n"
7364 " WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
7365 " THEN pg_catalog.format('%%I', of.opfname)\n"
7366 " ELSE pg_catalog.format('%%I.%%I', nsf.nspname, of.opfname)\n"
7367 " END AS \"%s\",\n"
7368 " o.amopopr::pg_catalog.regoperator AS \"%s\"\n,"
7369 " o.amopstrategy AS \"%s\",\n"
7370 " CASE o.amoppurpose\n"
7371 " WHEN " CppAsString2(AMOP_ORDER) " THEN '%s'\n"
7372 " WHEN " CppAsString2(AMOP_SEARCH) " THEN '%s'\n"
7373 " END AS \"%s\"\n",
7374 gettext_noop("AM"),
7375 gettext_noop("Operator family"),
7376 gettext_noop("Operator"),
7377 gettext_noop("Strategy"),
7378 gettext_noop("ordering"),
7379 gettext_noop("search"),
7380 gettext_noop("Purpose"));
7381
7382 if (verbose)
7384 ", ofs.opfname AS \"%s\",\n"
7385 " CASE\n"
7386 " WHEN p.proleakproof THEN '%s'\n"
7387 " ELSE '%s'\n"
7388 " END AS \"%s\"\n",
7389 gettext_noop("Sort opfamily"),
7390 gettext_noop("yes"),
7391 gettext_noop("no"),
7392 gettext_noop("Leakproof?"));
7394 "FROM pg_catalog.pg_amop o\n"
7395 " LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = o.amopfamily\n"
7396 " LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod AND am.oid = o.amopmethod\n"
7397 " LEFT JOIN pg_catalog.pg_namespace nsf ON of.opfnamespace = nsf.oid\n");
7398 if (verbose)
7400 " LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n"
7401 " LEFT JOIN pg_catalog.pg_operator op ON op.oid = o.amopopr\n"
7402 " LEFT JOIN pg_catalog.pg_proc p ON p.oid = op.oprcode\n");
7403
7405 {
7407 false, false, NULL, "am.amname",
7408 NULL, NULL,
7409 &have_where, 1))
7410 goto error_return;
7411 }
7412
7413 if (family_pattern)
7414 {
7416 "nsf.nspname", "of.opfname", NULL, NULL,
7417 NULL, 3))
7418 goto error_return;
7419 }
7420
7421 appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
7422 " o.amoplefttype = o.amoprighttype DESC,\n"
7423 " pg_catalog.format_type(o.amoplefttype, NULL),\n"
7424 " pg_catalog.format_type(o.amoprighttype, NULL),\n"
7425 " o.amopstrategy;");
7426
7427 res = PSQLexec(buf.data);
7429 if (!res)
7430 return false;
7431
7432 myopt.title = _("List of operators of operator families");
7433 myopt.translate_header = true;
7434 myopt.translate_columns = translate_columns;
7435 myopt.n_translate_columns = lengthof(translate_columns);
7436
7437 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
7438
7439 PQclear(res);
7440 return true;
7441
7444 return false;
7445}

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

4443{
4444 bool showTables = strchr(reltypes, 't') != NULL;
4445 bool showIndexes = strchr(reltypes, 'i') != NULL;
4446 bool showNested = strchr(reltypes, 'n') != NULL;
4448 PQExpBufferData title;
4449 PGresult *res;
4451 bool translate_columns[] = {false, false, false, false, false, false, false, false, false, false};
4452 const char *tabletitle;
4453 bool mixed_output = false;
4454
4455 /*
4456 * Note: Declarative table partitioning is only supported as of Pg 10.0.
4457 */
4458 if (pset.sversion < 100000)
4459 {
4460 char sverbuf[32];
4461
4462 pg_log_error("The server (version %s) does not support declarative table partitioning.",
4464 sverbuf, sizeof(sverbuf)));
4465 return true;
4466 }
4467
4468 /* If no relation kind was selected, show them all */
4469 if (!showTables && !showIndexes)
4470 showTables = showIndexes = true;
4471
4472 if (showIndexes && !showTables)
4473 tabletitle = _("List of partitioned indexes"); /* \dPi */
4474 else if (showTables && !showIndexes)
4475 tabletitle = _("List of partitioned tables"); /* \dPt */
4476 else
4477 {
4478 /* show all kinds */
4479 tabletitle = _("List of partitioned relations");
4480 mixed_output = true;
4481 }
4482
4484
4486 "SELECT n.nspname as \"%s\",\n"
4487 " c.relname as \"%s\",\n"
4488 " pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"",
4489 gettext_noop("Schema"),
4490 gettext_noop("Name"),
4491 gettext_noop("Owner"));
4492
4493 if (mixed_output)
4494 {
4496 ",\n CASE c.relkind"
4497 " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
4498 " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
4499 " END as \"%s\"",
4500 gettext_noop("partitioned table"),
4501 gettext_noop("partitioned index"),
4502 gettext_noop("Type"));
4503
4504 translate_columns[3] = true;
4505 }
4506
4507 if (showNested || pattern)
4509 ",\n inh.inhparent::pg_catalog.regclass as \"%s\"",
4510 gettext_noop("Parent name"));
4511
4512 if (showIndexes)
4514 ",\n c2.oid::pg_catalog.regclass as \"%s\"",
4515 gettext_noop("Table"));
4516
4517 if (verbose)
4518 {
4519 /*
4520 * Table access methods were introduced in v12, and can be set on
4521 * partitioned tables since v17.
4522 */
4523 appendPQExpBuffer(&buf, ",\n am.amname as \"%s\"",
4524 gettext_noop("Access method"));
4525
4526 if (showNested)
4527 {
4529 ",\n s.dps as \"%s\"",
4530 gettext_noop("Leaf partition size"));
4532 ",\n s.tps as \"%s\"",
4533 gettext_noop("Total size"));
4534 }
4535 else
4536 /* Sizes of all partitions are considered in this case. */
4538 ",\n s.tps as \"%s\"",
4539 gettext_noop("Total size"));
4540
4542 ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"",
4543 gettext_noop("Description"));
4544 }
4545
4547 "\nFROM pg_catalog.pg_class c"
4548 "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace");
4549
4550 if (showIndexes)
4552 "\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid"
4553 "\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid");
4554
4555 if (showNested || pattern)
4557 "\n LEFT JOIN pg_catalog.pg_inherits inh ON c.oid = inh.inhrelid");
4558
4559 if (verbose)
4560 {
4562 "\n LEFT JOIN pg_catalog.pg_am am ON c.relam = am.oid");
4563
4564 if (pset.sversion < 120000)
4565 {
4567 ",\n LATERAL (WITH RECURSIVE d\n"
4568 " AS (SELECT inhrelid AS oid, 1 AS level\n"
4569 " FROM pg_catalog.pg_inherits\n"
4570 " WHERE inhparent = c.oid\n"
4571 " UNION ALL\n"
4572 " SELECT inhrelid, level + 1\n"
4573 " FROM pg_catalog.pg_inherits i\n"
4574 " JOIN d ON i.inhparent = d.oid)\n"
4575 " SELECT pg_catalog.pg_size_pretty(sum(pg_catalog.pg_table_size("
4576 "d.oid))) AS tps,\n"
4577 " pg_catalog.pg_size_pretty(sum("
4578 "\n CASE WHEN d.level = 1"
4579 " THEN pg_catalog.pg_table_size(d.oid) ELSE 0 END)) AS dps\n"
4580 " FROM d) s");
4581 }
4582 else
4583 {
4584 /* PostgreSQL 12 has pg_partition_tree function */
4586 ",\n LATERAL (SELECT pg_catalog.pg_size_pretty(sum("
4587 "\n CASE WHEN ppt.isleaf AND ppt.level = 1"
4588 "\n THEN pg_catalog.pg_table_size(ppt.relid)"
4589 " ELSE 0 END)) AS dps"
4590 ",\n pg_catalog.pg_size_pretty(sum("
4591 "pg_catalog.pg_table_size(ppt.relid))) AS tps"
4592 "\n FROM pg_catalog.pg_partition_tree(c.oid) ppt) s");
4593 }
4594 }
4595
4596 appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
4597 if (showTables)
4599 if (showIndexes)
4601 appendPQExpBufferStr(&buf, "''"); /* dummy */
4602 appendPQExpBufferStr(&buf, ")\n");
4603
4604 appendPQExpBufferStr(&buf, !showNested && !pattern ?
4605 " AND NOT c.relispartition\n" : "");
4606
4607 if (!pattern)
4608 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4609 " AND n.nspname !~ '^pg_toast'\n"
4610 " AND n.nspname <> 'information_schema'\n");
4611
4612 if (!validateSQLNamePattern(&buf, pattern, true, false,
4613 "n.nspname", "c.relname", NULL,
4614 "pg_catalog.pg_table_is_visible(c.oid)",
4615 NULL, 3))
4616 {
4618 return false;
4619 }
4620
4621 appendPQExpBuffer(&buf, "ORDER BY \"Schema\", %s%s\"Name\";",
4622 mixed_output ? "\"Type\" DESC, " : "",
4623 showNested || pattern ? "\"Parent name\" NULLS FIRST, " : "");
4624
4625 res = PSQLexec(buf.data);
4627 if (!res)
4628 return false;
4629
4630 initPQExpBuffer(&title);
4632
4633 myopt.title = title.data;
4634 myopt.translate_header = true;
4635 myopt.translate_columns = translate_columns;
4636 myopt.n_translate_columns = lengthof(translate_columns);
4637
4638 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4639
4640 termPQExpBuffer(&title);
4641
4642 PQclear(res);
4643 return true;
4644}

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

6582{
6584 PGresult *res;
6586 static const bool translate_columns[] = {false, false, false, false, false, false, false, false, false, false};
6587
6588 if (pset.sversion < 100000)
6589 {
6590 char sverbuf[32];
6591
6592 pg_log_error("The server (version %s) does not support publications.",
6594 sverbuf, sizeof(sverbuf)));
6595 return true;
6596 }
6597
6599
6601 "SELECT pubname AS \"%s\",\n"
6602 " pg_catalog.pg_get_userbyid(pubowner) AS \"%s\",\n"
6603 " puballtables AS \"%s\"",
6604 gettext_noop("Name"),
6605 gettext_noop("Owner"),
6606 gettext_noop("All tables"));
6607
6608 if (pset.sversion >= 190000)
6610 ",\n puballsequences AS \"%s\"",
6611 gettext_noop("All sequences"));
6612
6614 ",\n pubinsert AS \"%s\",\n"
6615 " pubupdate AS \"%s\",\n"
6616 " pubdelete AS \"%s\"",
6617 gettext_noop("Inserts"),
6618 gettext_noop("Updates"),
6619 gettext_noop("Deletes"));
6620 if (pset.sversion >= 110000)
6622 ",\n pubtruncate AS \"%s\"",
6623 gettext_noop("Truncates"));
6624 if (pset.sversion >= 180000)
6626 ",\n (CASE pubgencols\n"
6627 " WHEN '%c' THEN 'none'\n"
6628 " WHEN '%c' THEN 'stored'\n"
6629 " END) AS \"%s\"",
6632 gettext_noop("Generated columns"));
6633 if (pset.sversion >= 130000)
6635 ",\n pubviaroot AS \"%s\"",
6636 gettext_noop("Via root"));
6637
6639 "\nFROM pg_catalog.pg_publication\n");
6640
6641 if (!validateSQLNamePattern(&buf, pattern, false, false,
6642 NULL, "pubname", NULL,
6643 NULL,
6644 NULL, 1))
6645 {
6647 return false;
6648 }
6649
6650 appendPQExpBufferStr(&buf, "ORDER BY 1;");
6651
6652 res = PSQLexec(buf.data);
6654 if (!res)
6655 return false;
6656
6657 myopt.title = _("List of publications");
6658 myopt.translate_header = true;
6659 myopt.translate_columns = translate_columns;
6660 myopt.n_translate_columns = lengthof(translate_columns);
6661
6662 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6663
6664 PQclear(res);
6665
6666 return true;
6667}

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

5388{
5390 PGresult *res;
5392 int pub_schema_tuples = 0;
5393 char **footers = NULL;
5394
5397 "SELECT n.nspname AS \"%s\",\n"
5398 " pg_catalog.pg_get_userbyid(n.nspowner) AS \"%s\"",
5399 gettext_noop("Name"),
5400 gettext_noop("Owner"));
5401
5402 if (verbose)
5403 {
5404 appendPQExpBufferStr(&buf, ",\n ");
5405 printACLColumn(&buf, "n.nspacl");
5407 ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"",
5408 gettext_noop("Description"));
5409 }
5410
5412 "\nFROM pg_catalog.pg_namespace n\n");
5413
5414 if (!showSystem && !pattern)
5416 "WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'\n");
5417
5418 if (!validateSQLNamePattern(&buf, pattern,
5419 !showSystem && !pattern, false,
5420 NULL, "n.nspname", NULL,
5421 NULL,
5422 NULL, 2))
5423 goto error_return;
5424
5425 appendPQExpBufferStr(&buf, "ORDER BY 1;");
5426
5427 res = PSQLexec(buf.data);
5428 if (!res)
5429 goto error_return;
5430
5431 myopt.title = _("List of schemas");
5432 myopt.translate_header = true;
5433
5434 if (pattern && pset.sversion >= 150000)
5435 {
5436 PGresult *result;
5437 int i;
5438
5440 "SELECT pubname \n"
5441 "FROM pg_catalog.pg_publication p\n"
5442 " JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
5443 " JOIN pg_catalog.pg_namespace n ON n.oid = pn.pnnspid \n"
5444 "WHERE n.nspname = '%s'\n"
5445 "ORDER BY 1",
5446 pattern);
5447 result = PSQLexec(buf.data);
5448 if (!result)
5449 goto error_return;
5450 else
5451 pub_schema_tuples = PQntuples(result);
5452
5453 if (pub_schema_tuples > 0)
5454 {
5455 /*
5456 * Allocate memory for footers. Size of footers will be 1 (for
5457 * storing "Publications:" string) + publication schema mapping
5458 * count + 1 (for storing NULL).
5459 */
5460 footers = pg_malloc_array(char *, 1 + pub_schema_tuples + 1);
5461 footers[0] = pg_strdup(_("Publications:"));
5462
5463 /* Might be an empty set - that's ok */
5464 for (i = 0; i < pub_schema_tuples; i++)
5465 {
5466 printfPQExpBuffer(&buf, " \"%s\"",
5467 PQgetvalue(result, i, 0));
5468
5469 footers[i + 1] = pg_strdup(buf.data);
5470 }
5471
5472 footers[i + 1] = NULL;
5473 myopt.footers = footers;
5474 }
5475
5476 PQclear(result);
5477 }
5478
5479 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5480
5482 PQclear(res);
5483
5484 /* Free the memory allocated for the footer */
5485 if (footers)
5486 {
5487 char **footer = NULL;
5488
5489 for (footer = footers; *footer; footer++)
5490 pg_free(*footer);
5491
5492 pg_free(footers);
5493 }
5494
5495 return true;
5496
5499 return false;
5500}
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, _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 4176 of file describe.c.

4177{
4178 bool showTables = strchr(tabtypes, 't') != NULL;
4179 bool showIndexes = strchr(tabtypes, 'i') != NULL;
4180 bool showViews = strchr(tabtypes, 'v') != NULL;
4181 bool showMatViews = strchr(tabtypes, 'm') != NULL;
4182 bool showSeq = strchr(tabtypes, 's') != NULL;
4183 bool showForeign = strchr(tabtypes, 'E') != NULL;
4184 bool showPropGraphs = strchr(tabtypes, 'G') != NULL;
4185
4186 int ntypes;
4188 PGresult *res;
4190 int cols_so_far;
4191 bool translate_columns[] = {false, false, true, false, false, false, false, false, false};
4192
4193 /* Count the number of explicitly-requested relation types */
4196 /* If none, we default to \dtvmsEG (but see also command.c) */
4197 if (ntypes == 0)
4199
4201
4203 "SELECT n.nspname as \"%s\",\n"
4204 " c.relname as \"%s\",\n"
4205 " CASE c.relkind"
4206 " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'"
4207 " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'"
4208 " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'"
4209 " WHEN " CppAsString2(RELKIND_INDEX) " THEN '%s'"
4210 " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'"
4211 " WHEN " CppAsString2(RELKIND_TOASTVALUE) " THEN '%s'"
4212 " WHEN " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN '%s'"
4213 " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
4214 " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
4215 " WHEN " CppAsString2(RELKIND_PROPGRAPH) " THEN '%s'"
4216 " END as \"%s\",\n"
4217 " pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"",
4218 gettext_noop("Schema"),
4219 gettext_noop("Name"),
4220 gettext_noop("table"),
4221 gettext_noop("view"),
4222 gettext_noop("materialized view"),
4223 gettext_noop("index"),
4224 gettext_noop("sequence"),
4225 gettext_noop("TOAST table"),
4226 gettext_noop("foreign table"),
4227 gettext_noop("partitioned table"),
4228 gettext_noop("partitioned index"),
4229 gettext_noop("property graph"),
4230 gettext_noop("Type"),
4231 gettext_noop("Owner"));
4232 cols_so_far = 4;
4233
4234 if (showIndexes)
4235 {
4237 ",\n c2.relname as \"%s\"",
4238 gettext_noop("Table"));
4239 cols_so_far++;
4240 }
4241
4242 if (verbose)
4243 {
4244 /*
4245 * Show whether a relation is permanent, temporary, or unlogged.
4246 */
4248 ",\n CASE c.relpersistence "
4249 "WHEN " CppAsString2(RELPERSISTENCE_PERMANENT) " THEN '%s' "
4250 "WHEN " CppAsString2(RELPERSISTENCE_TEMP) " THEN '%s' "
4251 "WHEN " CppAsString2(RELPERSISTENCE_UNLOGGED) " THEN '%s' "
4252 "END as \"%s\"",
4253 gettext_noop("permanent"),
4254 gettext_noop("temporary"),
4255 gettext_noop("unlogged"),
4256 gettext_noop("Persistence"));
4257 translate_columns[cols_so_far] = true;
4258
4259 /*
4260 * We don't bother to count cols_so_far below here, as there's no need
4261 * to; this might change with future additions to the output columns.
4262 */
4263
4264 /*
4265 * Access methods exist for tables, materialized views and indexes.
4266 * This has been introduced in PostgreSQL 12 for tables.
4267 */
4268 if (pset.sversion >= 120000 && !pset.hide_tableam &&
4271 ",\n am.amname as \"%s\"",
4272 gettext_noop("Access method"));
4273
4275 ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\""
4276 ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"",
4277 gettext_noop("Size"),
4278 gettext_noop("Description"));
4279 }
4280
4282 "\nFROM pg_catalog.pg_class c"
4283 "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace");
4284
4285 if (pset.sversion >= 120000 && !pset.hide_tableam &&
4288 "\n LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam");
4289
4290 if (showIndexes)
4292 "\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid"
4293 "\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid");
4294
4295 appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
4296 if (showTables)
4297 {
4300 /* with 'S' or a pattern, allow 't' to match TOAST tables too */
4301 if (showSystem || pattern)
4303 }
4304 if (showViews)
4306 if (showMatViews)
4308 if (showIndexes)
4311 if (showSeq)
4313 if (showSystem || pattern)
4314 appendPQExpBufferStr(&buf, "'s',"); /* was RELKIND_SPECIAL */
4315 if (showForeign)
4317 if (showPropGraphs)
4319
4320 appendPQExpBufferStr(&buf, "''"); /* dummy */
4321 appendPQExpBufferStr(&buf, ")\n");
4322
4323 if (!showSystem && !pattern)
4324 appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
4325 " AND n.nspname !~ '^pg_toast'\n"
4326 " AND n.nspname <> 'information_schema'\n");
4327
4328 if (!validateSQLNamePattern(&buf, pattern, true, false,
4329 "n.nspname", "c.relname", NULL,
4330 "pg_catalog.pg_table_is_visible(c.oid)",
4331 NULL, 3))
4332 {
4334 return false;
4335 }
4336
4337 appendPQExpBufferStr(&buf, "ORDER BY 1,2;");
4338
4339 res = PSQLexec(buf.data);
4341 if (!res)
4342 return false;
4343
4344 /*
4345 * Most functions in this file are content to print an empty table when
4346 * there are no matching objects. We intentionally deviate from that
4347 * here, but only in !quiet mode, for historical reasons.
4348 */
4349 if (PQntuples(res) == 0 && !pset.quiet)
4350 {
4351 if (pattern)
4352 {
4353 if (ntypes != 1)
4354 pg_log_error("Did not find any relations named \"%s\".",
4355 pattern);
4356 else if (showTables)
4357 pg_log_error("Did not find any tables named \"%s\".",
4358 pattern);
4359 else if (showIndexes)
4360 pg_log_error("Did not find any indexes named \"%s\".",
4361 pattern);
4362 else if (showViews)
4363 pg_log_error("Did not find any views named \"%s\".",
4364 pattern);
4365 else if (showMatViews)
4366 pg_log_error("Did not find any materialized views named \"%s\".",
4367 pattern);
4368 else if (showSeq)
4369 pg_log_error("Did not find any sequences named \"%s\".",
4370 pattern);
4371 else if (showForeign)
4372 pg_log_error("Did not find any foreign tables named \"%s\".",
4373 pattern);
4374 else if (showPropGraphs)
4375 pg_log_error("Did not find any property graphs named \"%s\".",
4376 pattern);
4377 else /* should not get here */
4378 pg_log_error_internal("Did not find any ??? named \"%s\".",
4379 pattern);
4380 }
4381 else
4382 {
4383 if (ntypes != 1)
4384 pg_log_error("Did not find any relations.");
4385 else if (showTables)
4386 pg_log_error("Did not find any tables.");
4387 else if (showIndexes)
4388 pg_log_error("Did not find any indexes.");
4389 else if (showViews)
4390 pg_log_error("Did not find any views.");
4391 else if (showMatViews)
4392 pg_log_error("Did not find any materialized views.");
4393 else if (showSeq)
4394 pg_log_error("Did not find any sequences.");
4395 else if (showForeign)
4396 pg_log_error("Did not find any foreign tables.");
4397 else if (showPropGraphs)
4398 pg_log_error("Did not find any property graphs.");
4399 else /* should not get here */
4400 pg_log_error_internal("Did not find any ??? relations.");
4401 }
4402 }
4403 else
4404 {
4405 myopt.title =
4406 (ntypes != 1) ? _("List of relations") :
4407 (showTables) ? _("List of tables") :
4408 (showIndexes) ? _("List of indexes") :
4409 (showViews) ? _("List of views") :
4410 (showMatViews) ? _("List of materialized views") :
4411 (showSeq) ? _("List of sequences") :
4412 (showForeign) ? _("List of foreign tables") :
4413 (showPropGraphs) ? _("List of property graphs") :
4414 "List of ???"; /* should not get here */
4415 myopt.translate_header = true;
4416 myopt.translate_columns = translate_columns;
4417 myopt.n_translate_columns = lengthof(translate_columns);
4418
4419 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
4420 }
4421
4422 PQclear(res);
4423 return true;
4424}
#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 5885 of file describe.c.

5886{
5888 PGresult *res;
5890
5891 if (verbose)
5892 return listTSConfigsVerbose(pattern);
5893
5895
5897 "SELECT\n"
5898 " n.nspname as \"%s\",\n"
5899 " c.cfgname as \"%s\",\n"
5900 " pg_catalog.obj_description(c.oid, 'pg_ts_config') as \"%s\"\n"
5901 "FROM pg_catalog.pg_ts_config c\n"
5902 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace\n",
5903 gettext_noop("Schema"),
5904 gettext_noop("Name"),
5905 gettext_noop("Description")
5906 );
5907
5908 if (!validateSQLNamePattern(&buf, pattern, false, false,
5909 "n.nspname", "c.cfgname", NULL,
5910 "pg_catalog.pg_ts_config_is_visible(c.oid)",
5911 NULL, 3))
5912 {
5914 return false;
5915 }
5916
5917 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5918
5919 res = PSQLexec(buf.data);
5921 if (!res)
5922 return false;
5923
5924 myopt.title = _("List of text search configurations");
5925 myopt.translate_header = true;
5926
5927 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5928
5929 PQclear(res);
5930 return true;
5931}
static bool listTSConfigsVerbose(const char *pattern)
Definition describe.c:5934

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

5935{
5937 PGresult *res;
5938 int i;
5939
5941
5943 "SELECT c.oid, c.cfgname,\n"
5944 " n.nspname,\n"
5945 " p.prsname,\n"
5946 " np.nspname as pnspname\n"
5947 "FROM pg_catalog.pg_ts_config c\n"
5948 " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace,\n"
5949 " pg_catalog.pg_ts_parser p\n"
5950 " LEFT JOIN pg_catalog.pg_namespace np ON np.oid = p.prsnamespace\n"
5951 "WHERE p.oid = c.cfgparser\n"
5952 );
5953
5954 if (!validateSQLNamePattern(&buf, pattern, true, false,
5955 "n.nspname", "c.cfgname", NULL,
5956 "pg_catalog.pg_ts_config_is_visible(c.oid)",
5957 NULL, 3))
5958 {
5960 return false;
5961 }
5962
5963 appendPQExpBufferStr(&buf, "ORDER BY 3, 2;");
5964
5965 res = PSQLexec(buf.data);
5967 if (!res)
5968 return false;
5969
5970 if (PQntuples(res) == 0)
5971 {
5972 if (!pset.quiet)
5973 {
5974 if (pattern)
5975 pg_log_error("Did not find any text search configuration named \"%s\".",
5976 pattern);
5977 else
5978 pg_log_error("Did not find any text search configurations.");
5979 }
5980 PQclear(res);
5981 return false;
5982 }
5983
5984 for (i = 0; i < PQntuples(res); i++)
5985 {
5986 const char *oid;
5987 const char *cfgname;
5988 const char *nspname = NULL;
5989 const char *prsname;
5990 const char *pnspname = NULL;
5991
5992 oid = PQgetvalue(res, i, 0);
5993 cfgname = PQgetvalue(res, i, 1);
5994 if (!PQgetisnull(res, i, 2))
5995 nspname = PQgetvalue(res, i, 2);
5996 prsname = PQgetvalue(res, i, 3);
5997 if (!PQgetisnull(res, i, 4))
5998 pnspname = PQgetvalue(res, i, 4);
5999
6000 if (!describeOneTSConfig(oid, nspname, cfgname, pnspname, prsname))
6001 {
6002 PQclear(res);
6003 return false;
6004 }
6005
6006 if (cancel_pressed)
6007 {
6008 PQclear(res);
6009 return false;
6010 }
6011 }
6012
6013 PQclear(res);
6014 return true;
6015}
static bool describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname, const char *pnspname, const char *prsname)
Definition describe.c:6018

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

Referenced by listTSConfigs().

◆ listTSDictionaries()

bool listTSDictionaries ( const char pattern,
bool  verbose 
)

Definition at line 5755 of file describe.c.

5756{
5758 PGresult *res;
5760
5762
5764 "SELECT\n"
5765 " n.nspname as \"%s\",\n"
5766 " d.dictname as \"%s\",\n",
5767 gettext_noop("Schema"),
5768 gettext_noop("Name"));
5769
5770 if (verbose)
5771 {
5773 " ( SELECT COALESCE(nt.nspname, '(null)')::pg_catalog.text || '.' || t.tmplname FROM\n"
5774 " pg_catalog.pg_ts_template t\n"
5775 " LEFT JOIN pg_catalog.pg_namespace nt ON nt.oid = t.tmplnamespace\n"
5776 " WHERE d.dicttemplate = t.oid ) AS \"%s\",\n"
5777 " d.dictinitoption as \"%s\",\n",
5778 gettext_noop("Template"),
5779 gettext_noop("Init options"));
5780 }
5781
5783 " pg_catalog.obj_description(d.oid, 'pg_ts_dict') as \"%s\"\n",
5784 gettext_noop("Description"));
5785
5786 appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_dict d\n"
5787 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace\n");
5788
5789 if (!validateSQLNamePattern(&buf, pattern, false, false,
5790 "n.nspname", "d.dictname", NULL,
5791 "pg_catalog.pg_ts_dict_is_visible(d.oid)",
5792 NULL, 3))
5793 {
5795 return false;
5796 }
5797
5798 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5799
5800 res = PSQLexec(buf.data);
5802 if (!res)
5803 return false;
5804
5805 myopt.title = _("List of text search dictionaries");
5806 myopt.translate_header = true;
5807
5808 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5809
5810 PQclear(res);
5811 return true;
5812}

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

5509{
5511 PGresult *res;
5513
5514 if (verbose)
5515 return listTSParsersVerbose(pattern);
5516
5518
5520 "SELECT\n"
5521 " n.nspname as \"%s\",\n"
5522 " p.prsname as \"%s\",\n"
5523 " pg_catalog.obj_description(p.oid, 'pg_ts_parser') as \"%s\"\n"
5524 "FROM pg_catalog.pg_ts_parser p\n"
5525 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n",
5526 gettext_noop("Schema"),
5527 gettext_noop("Name"),
5528 gettext_noop("Description")
5529 );
5530
5531 if (!validateSQLNamePattern(&buf, pattern, false, false,
5532 "n.nspname", "p.prsname", NULL,
5533 "pg_catalog.pg_ts_parser_is_visible(p.oid)",
5534 NULL, 3))
5535 {
5537 return false;
5538 }
5539
5540 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5541
5542 res = PSQLexec(buf.data);
5544 if (!res)
5545 return false;
5546
5547 myopt.title = _("List of text search parsers");
5548 myopt.translate_header = true;
5549
5550 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5551
5552 PQclear(res);
5553 return true;
5554}
static bool listTSParsersVerbose(const char *pattern)
Definition describe.c:5560

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

5561{
5563 PGresult *res;
5564 int i;
5565
5567
5569 "SELECT p.oid,\n"
5570 " n.nspname,\n"
5571 " p.prsname\n"
5572 "FROM pg_catalog.pg_ts_parser p\n"
5573 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n"
5574 );
5575
5576 if (!validateSQLNamePattern(&buf, pattern, false, false,
5577 "n.nspname", "p.prsname", NULL,
5578 "pg_catalog.pg_ts_parser_is_visible(p.oid)",
5579 NULL, 3))
5580 {
5582 return false;
5583 }
5584
5585 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5586
5587 res = PSQLexec(buf.data);
5589 if (!res)
5590 return false;
5591
5592 if (PQntuples(res) == 0)
5593 {
5594 if (!pset.quiet)
5595 {
5596 if (pattern)
5597 pg_log_error("Did not find any text search parser named \"%s\".",
5598 pattern);
5599 else
5600 pg_log_error("Did not find any text search parsers.");
5601 }
5602 PQclear(res);
5603 return false;
5604 }
5605
5606 for (i = 0; i < PQntuples(res); i++)
5607 {
5608 const char *oid;
5609 const char *nspname = NULL;
5610 const char *prsname;
5611
5612 oid = PQgetvalue(res, i, 0);
5613 if (!PQgetisnull(res, i, 1))
5614 nspname = PQgetvalue(res, i, 1);
5615 prsname = PQgetvalue(res, i, 2);
5616
5617 if (!describeOneTSParser(oid, nspname, prsname))
5618 {
5619 PQclear(res);
5620 return false;
5621 }
5622
5623 if (cancel_pressed)
5624 {
5625 PQclear(res);
5626 return false;
5627 }
5628 }
5629
5630 PQclear(res);
5631 return true;
5632}
static bool describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
Definition describe.c:5635

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

Referenced by listTSParsers().

◆ listTSTemplates()

bool listTSTemplates ( const char pattern,
bool  verbose 
)

Definition at line 5820 of file describe.c.

5821{
5823 PGresult *res;
5825
5827
5828 if (verbose)
5830 "SELECT\n"
5831 " n.nspname AS \"%s\",\n"
5832 " t.tmplname AS \"%s\",\n"
5833 " t.tmplinit::pg_catalog.regproc AS \"%s\",\n"
5834 " t.tmpllexize::pg_catalog.regproc AS \"%s\",\n"
5835 " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
5836 gettext_noop("Schema"),
5837 gettext_noop("Name"),
5838 gettext_noop("Init"),
5839 gettext_noop("Lexize"),
5840 gettext_noop("Description"));
5841 else
5843 "SELECT\n"
5844 " n.nspname AS \"%s\",\n"
5845 " t.tmplname AS \"%s\",\n"
5846 " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
5847 gettext_noop("Schema"),
5848 gettext_noop("Name"),
5849 gettext_noop("Description"));
5850
5851 appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_template t\n"
5852 "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.tmplnamespace\n");
5853
5854 if (!validateSQLNamePattern(&buf, pattern, false, false,
5855 "n.nspname", "t.tmplname", NULL,
5856 "pg_catalog.pg_ts_template_is_visible(t.oid)",
5857 NULL, 3))
5858 {
5860 return false;
5861 }
5862
5863 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
5864
5865 res = PSQLexec(buf.data);
5867 if (!res)
5868 return false;
5869
5870 myopt.title = _("List of text search templates");
5871 myopt.translate_header = true;
5872
5873 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
5874
5875 PQclear(res);
5876 return true;
5877}

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

6237{
6239 PGresult *res;
6241
6244 "SELECT um.srvname AS \"%s\",\n"
6245 " um.usename AS \"%s\"",
6246 gettext_noop("Server"),
6247 gettext_noop("User name"));
6248
6249 if (verbose)
6251 ",\n CASE WHEN umoptions IS NULL THEN '' ELSE "
6252 " '(' || pg_catalog.array_to_string(ARRAY(SELECT "
6253 " pg_catalog.quote_ident(option_name) || ' ' || "
6254 " pg_catalog.quote_literal(option_value) FROM "
6255 " pg_catalog.pg_options_to_table(umoptions)), ', ') || ')' "
6256 " END AS \"%s\"",
6257 gettext_noop("FDW options"));
6258
6259 appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_user_mappings um\n");
6260
6261 if (!validateSQLNamePattern(&buf, pattern, false, false,
6262 NULL, "um.srvname", "um.usename", NULL,
6263 NULL, 1))
6264 {
6266 return false;
6267 }
6268
6269 appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
6270
6271 res = PSQLexec(buf.data);
6273 if (!res)
6274 return false;
6275
6276 myopt.title = _("List of user mappings");
6277 myopt.translate_header = true;
6278
6279 printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
6280
6281 PQclear(res);
6282 return true;
6283}

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

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

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

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

Referenced by exec_command_d().

◆ permissionsList()

bool permissionsList ( const char pattern,
bool  showSystem 
)

Definition at line 1051 of file describe.c.

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

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

7141{
7143 "CASE"
7144 " WHEN pg_catalog.array_length(%s, 1) = 0 THEN '%s'"
7145 " ELSE pg_catalog.array_to_string(%s, E'\\n')"
7146 " END AS \"%s\"",
7147 colname, gettext_noop("(none)"),
7148 colname, gettext_noop("Access privileges"));
7149}

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

6533{
6535 int dotcnt;
6536 bool added;
6537
6542 if (added_clause != NULL)
6544
6545 if (dotcnt >= maxparts)
6546 {
6547 pg_log_error("improper qualified name (too many dotted names): %s",
6548 pattern);
6549 goto error_return;
6550 }
6551
6552 if (maxparts > 1 && dotcnt == maxparts - 1)
6553 {
6554 if (PQdb(pset.db) == NULL)
6555 {
6556 pg_log_error("You are currently not connected to a database.");
6557 goto error_return;
6558 }
6559 if (strcmp(PQdb(pset.db), dbbuf.data) != 0)
6560 {
6561 pg_log_error("cross-database references are not implemented: %s",
6562 pattern);
6563 goto error_return;
6564 }
6565 }
6567 return true;
6568
6571 return false;
6572}
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().