LCOV - differential code coverage report
Current view: top level - src/bin/psql - describe.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 77.2 % 2592 2001 10 92 330 159 117 1078 23 783 304 1112 11 14
Current Date: 2023-04-08 17:13:01 Functions: 88.9 % 54 48 6 43 2 3 6 44
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 35.7 % 14 5 6 2 1 5 1
Legend: Lines: hit not hit (60,120] days: 83.3 % 6 5 1 5
(120,180] days: 100.0 % 5 5 5
(180,240] days: 100.0 % 3 3 3
(240..) days: 77.3 % 2564 1983 3 92 328 158 117 1078 5 783 302 1095
Function coverage date bins:
(60,120] days: 100.0 % 1 1 1
(240..) days: 46.1 % 102 47 6 43 1 3 6 43

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*
                                  2                 :  * psql - the PostgreSQL interactive terminal
                                  3                 :  *
                                  4                 :  * Support for the various \d ("describe") commands.  Note that the current
                                  5                 :  * expectation is that all functions in this file will succeed when working
                                  6                 :  * with servers of versions 9.2 and up.  It's okay to omit irrelevant
                                  7                 :  * information for an old server, but not to fail outright.  (But failing
                                  8                 :  * against a pre-9.2 server is allowed.)
                                  9                 :  *
                                 10                 :  * Copyright (c) 2000-2023, PostgreSQL Global Development Group
                                 11                 :  *
                                 12                 :  * src/bin/psql/describe.c
                                 13                 :  */
                                 14                 : #include "postgres_fe.h"
                                 15                 : 
                                 16                 : #include <ctype.h>
                                 17                 : 
                                 18                 : #include "catalog/pg_am.h"
                                 19                 : #include "catalog/pg_attribute_d.h"
                                 20                 : #include "catalog/pg_cast_d.h"
                                 21                 : #include "catalog/pg_class_d.h"
                                 22                 : #include "catalog/pg_default_acl_d.h"
                                 23                 : #include "common.h"
                                 24                 : #include "common/logging.h"
                                 25                 : #include "describe.h"
                                 26                 : #include "fe_utils/mbprint.h"
                                 27                 : #include "fe_utils/print.h"
                                 28                 : #include "fe_utils/string_utils.h"
                                 29                 : #include "settings.h"
                                 30                 : #include "variables.h"
                                 31                 : 
                                 32                 : static const char *map_typename_pattern(const char *pattern);
                                 33                 : static bool describeOneTableDetails(const char *schemaname,
                                 34                 :                                     const char *relationname,
                                 35                 :                                     const char *oid,
                                 36                 :                                     bool verbose);
                                 37                 : static void add_tablespace_footer(printTableContent *const cont, char relkind,
                                 38                 :                                   Oid tablespace, const bool newline);
                                 39                 : static void add_role_attribute(PQExpBuffer buf, const char *const str);
                                 40                 : static bool listTSParsersVerbose(const char *pattern);
                                 41                 : static bool describeOneTSParser(const char *oid, const char *nspname,
                                 42                 :                                 const char *prsname);
                                 43                 : static bool listTSConfigsVerbose(const char *pattern);
                                 44                 : static bool describeOneTSConfig(const char *oid, const char *nspname,
                                 45                 :                                 const char *cfgname,
                                 46                 :                                 const char *pnspname, const char *prsname);
                                 47                 : static void printACLColumn(PQExpBuffer buf, const char *colname);
                                 48                 : static bool listOneExtensionContents(const char *extname, const char *oid);
                                 49                 : static bool validateSQLNamePattern(PQExpBuffer buf, const char *pattern,
                                 50                 :                                    bool have_where, bool force_escape,
                                 51                 :                                    const char *schemavar, const char *namevar,
                                 52                 :                                    const char *altnamevar,
                                 53                 :                                    const char *visibilityrule,
                                 54                 :                                    bool *added_clause, int maxparts);
                                 55                 : 
                                 56                 : 
                                 57                 : /*----------------
                                 58                 :  * Handlers for various slash commands displaying some sort of list
                                 59                 :  * of things in the database.
                                 60                 :  *
                                 61                 :  * Note: try to format the queries to look nice in -E output.
                                 62                 :  *----------------
                                 63                 :  */
                                 64                 : 
                                 65                 : 
                                 66                 : /*
                                 67                 :  * \da
                                 68                 :  * Takes an optional regexp to select particular aggregates
                                 69                 :  */
                                 70                 : bool
 5206 bruce                      71 CBC          24 : describeAggregates(const char *pattern, bool verbose, bool showSystem)
                                 72                 : {
                                 73                 :     PQExpBufferData buf;
                                 74                 :     PGresult   *res;
 8486 peter_e                    75              24 :     printQueryOpt myopt = pset.popt;
                                 76                 : 
 7655                            77              24 :     initPQExpBuffer(&buf);
                                 78                 : 
                                 79              24 :     printfPQExpBuffer(&buf,
                                 80                 :                       "SELECT n.nspname as \"%s\",\n"
                                 81                 :                       "  p.proname AS \"%s\",\n"
                                 82                 :                       "  pg_catalog.format_type(p.prorettype, NULL) AS \"%s\",\n"
                                 83                 :                       "  CASE WHEN p.pronargs = 0\n"
                                 84                 :                       "    THEN CAST('*' AS pg_catalog.text)\n"
                                 85                 :                       "    ELSE pg_catalog.pg_get_function_arguments(p.oid)\n"
                                 86                 :                       "  END AS \"%s\",\n",
                                 87                 :                       gettext_noop("Schema"),
                                 88                 :                       gettext_noop("Name"),
                                 89                 :                       gettext_noop("Result data type"),
                                 90                 :                       gettext_noop("Argument data types"));
                                 91                 : 
 1864                            92              24 :     if (pset.sversion >= 110000)
                                 93              24 :         appendPQExpBuffer(&buf,
                                 94                 :                           "  pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"\n"
                                 95                 :                           "FROM pg_catalog.pg_proc p\n"
                                 96                 :                           "     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"
                                 97                 :                           "WHERE p.prokind = 'a'\n",
                                 98                 :                           gettext_noop("Description"));
                                 99                 :     else
 1864 peter_e                   100 UBC           0 :         appendPQExpBuffer(&buf,
                                101                 :                           "  pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"\n"
                                102                 :                           "FROM pg_catalog.pg_proc p\n"
                                103                 :                           "     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"
                                104                 :                           "WHERE p.proisagg\n",
                                105                 :                           gettext_noop("Description"));
                                106                 : 
 5050 bruce                     107 CBC          24 :     if (!showSystem && !pattern)
 3429 heikki.linnakangas        108 UBC           0 :         appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
                                109                 :                              "      AND n.nspname <> 'information_schema'\n");
                                110                 : 
  354 rhaas                     111 CBC          24 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
                                112                 :                                 "n.nspname", "p.proname", NULL,
                                113                 :                                 "pg_catalog.pg_function_is_visible(p.oid)",
                                114                 :                                 NULL, 3))
                                115                 :     {
  262 michael                   116              12 :         termPQExpBuffer(&buf);
  354 rhaas                     117              12 :         return false;
                                118                 :     }
                                119                 : 
 3429 heikki.linnakangas        120              12 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
                                121                 : 
 3090 fujii                     122              12 :     res = PSQLexec(buf.data);
 7655 peter_e                   123              12 :     termPQExpBuffer(&buf);
 8557 bruce                     124              12 :     if (!res)
 8557 bruce                     125 UBC           0 :         return false;
                                126                 : 
 8557 bruce                     127 CBC          12 :     myopt.nullPrint = NULL;
 7953 peter_e                   128              12 :     myopt.title = _("List of aggregate functions");
 5382 bruce                     129              12 :     myopt.translate_header = true;
                                130                 : 
 2685 tgl                       131              12 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                                132                 : 
 8557 bruce                     133              12 :     PQclear(res);
                                134              12 :     return true;
                                135                 : }
                                136                 : 
                                137                 : /*
                                138                 :  * \dA
                                139                 :  * Takes an optional regexp to select particular access methods
                                140                 :  */
                                141                 : bool
 2497 alvherre                  142              39 : describeAccessMethods(const char *pattern, bool verbose)
                                143                 : {
                                144                 :     PQExpBufferData buf;
                                145                 :     PGresult   *res;
                                146              39 :     printQueryOpt myopt = pset.popt;
                                147                 :     static const bool translate_columns[] = {false, true, false, false};
                                148                 : 
                                149              39 :     if (pset.sversion < 90600)
                                150                 :     {
                                151                 :         char        sverbuf[32];
                                152                 : 
 1469 peter                     153 UBC           0 :         pg_log_error("The server (version %s) does not support access methods.",
                                154                 :                      formatPGVersionNumber(pset.sversion, false,
                                155                 :                                            sverbuf, sizeof(sverbuf)));
 2497 alvherre                  156               0 :         return true;
                                157                 :     }
                                158                 : 
 2497 alvherre                  159 CBC          39 :     initPQExpBuffer(&buf);
                                160                 : 
                                161              39 :     printfPQExpBuffer(&buf,
                                162                 :                       "SELECT amname AS \"%s\",\n"
                                163                 :                       "  CASE amtype"
                                164                 :                       " WHEN 'i' THEN '%s'"
                                165                 :                       " WHEN 't' THEN '%s'"
                                166                 :                       " END AS \"%s\"",
                                167                 :                       gettext_noop("Name"),
                                168                 :                       gettext_noop("Index"),
                                169                 :                       gettext_noop("Table"),
                                170                 :                       gettext_noop("Type"));
                                171                 : 
                                172              39 :     if (verbose)
                                173                 :     {
                                174              12 :         appendPQExpBuffer(&buf,
                                175                 :                           ",\n  amhandler AS \"%s\",\n"
                                176                 :                           "  pg_catalog.obj_description(oid, 'pg_am') AS \"%s\"",
                                177                 :                           gettext_noop("Handler"),
                                178                 :                           gettext_noop("Description"));
                                179                 :     }
                                180                 : 
                                181              39 :     appendPQExpBufferStr(&buf,
                                182                 :                          "\nFROM pg_catalog.pg_am\n");
                                183                 : 
  354 rhaas                     184              39 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                                185                 :                                 NULL, "amname", NULL,
                                186                 :                                 NULL,
                                187                 :                                 NULL, 1))
                                188                 :     {
  262 michael                   189               9 :         termPQExpBuffer(&buf);
  354 rhaas                     190               9 :         return false;
                                191                 :     }
                                192                 : 
 2497 alvherre                  193              30 :     appendPQExpBufferStr(&buf, "ORDER BY 1;");
                                194                 : 
                                195              30 :     res = PSQLexec(buf.data);
                                196              30 :     termPQExpBuffer(&buf);
                                197              30 :     if (!res)
 2497 alvherre                  198 UBC           0 :         return false;
                                199                 : 
 2497 alvherre                  200 CBC          30 :     myopt.nullPrint = NULL;
                                201              30 :     myopt.title = _("List of access methods");
                                202              30 :     myopt.translate_header = true;
                                203              30 :     myopt.translate_columns = translate_columns;
                                204              30 :     myopt.n_translate_columns = lengthof(translate_columns);
                                205                 : 
                                206              30 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                                207                 : 
                                208              30 :     PQclear(res);
                                209              30 :     return true;
                                210                 : }
                                211                 : 
                                212                 : /*
                                213                 :  * \db
                                214                 :  * Takes an optional regexp to select particular tablespaces
                                215                 :  */
                                216                 : bool
 6842 bruce                     217              12 : describeTablespaces(const char *pattern, bool verbose)
                                218                 : {
                                219                 :     PQExpBufferData buf;
                                220                 :     PGresult   *res;
 6869 tgl                       221              12 :     printQueryOpt myopt = pset.popt;
                                222                 : 
                                223              12 :     initPQExpBuffer(&buf);
                                224                 : 
  479                           225              12 :     printfPQExpBuffer(&buf,
                                226                 :                       "SELECT spcname AS \"%s\",\n"
                                227                 :                       "  pg_catalog.pg_get_userbyid(spcowner) AS \"%s\",\n"
                                228                 :                       "  pg_catalog.pg_tablespace_location(oid) AS \"%s\"",
                                229                 :                       gettext_noop("Name"),
                                230                 :                       gettext_noop("Owner"),
                                231                 :                       gettext_noop("Location"));
                                232                 : 
 6842 bruce                     233              12 :     if (verbose)
                                234                 :     {
 3429 heikki.linnakangas        235 UBC           0 :         appendPQExpBufferStr(&buf, ",\n  ");
 5212 tgl                       236               0 :         printACLColumn(&buf, "spcacl");
 3360 magnus                    237               0 :         appendPQExpBuffer(&buf,
                                238                 :                           ",\n  spcoptions AS \"%s\""
                                239                 :                           ",\n  pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\""
                                240                 :                           ",\n  pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"",
                                241                 :                           gettext_noop("Options"),
                                242                 :                           gettext_noop("Size"),
                                243                 :                           gettext_noop("Description"));
                                244                 :     }
                                245                 : 
 3429 heikki.linnakangas        246 CBC          12 :     appendPQExpBufferStr(&buf,
                                247                 :                          "\nFROM pg_catalog.pg_tablespace\n");
                                248                 : 
  354 rhaas                     249              12 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                                250                 :                                 NULL, "spcname", NULL,
                                251                 :                                 NULL,
                                252                 :                                 NULL, 1))
                                253                 :     {
  262 michael                   254               9 :         termPQExpBuffer(&buf);
  354 rhaas                     255               9 :         return false;
                                256                 :     }
                                257                 : 
 3429 heikki.linnakangas        258               3 :     appendPQExpBufferStr(&buf, "ORDER BY 1;");
                                259                 : 
 3090 fujii                     260               3 :     res = PSQLexec(buf.data);
 6869 tgl                       261               3 :     termPQExpBuffer(&buf);
                                262               3 :     if (!res)
 6869 tgl                       263 UBC           0 :         return false;
                                264                 : 
 6869 tgl                       265 CBC           3 :     myopt.nullPrint = NULL;
                                266               3 :     myopt.title = _("List of tablespaces");
 5382 bruce                     267               3 :     myopt.translate_header = true;
                                268                 : 
 2685 tgl                       269               3 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                                270                 : 
 6869                           271               3 :     PQclear(res);
                                272               3 :     return true;
                                273                 : }
                                274                 : 
                                275                 : 
                                276                 : /*
                                277                 :  * \df
                                278                 :  * Takes an optional regexp to select particular functions.
                                279                 :  *
                                280                 :  * As with \d, you can specify the kinds of functions you want:
                                281                 :  *
                                282                 :  * a for aggregates
                                283                 :  * n for normal
                                284                 :  * p for procedure
                                285                 :  * t for trigger
                                286                 :  * w for window
                                287                 :  *
                                288                 :  * and you can mix and match these in any order.
                                289                 :  */
                                290                 : bool
  732                           291             143 : describeFunctions(const char *functypes, const char *func_pattern,
                                292                 :                   char **arg_patterns, int num_arg_patterns,
                                293                 :                   bool verbose, bool showSystem)
                                294                 : {
 5087                           295             143 :     bool        showAggregate = strchr(functypes, 'a') != NULL;
                                296             143 :     bool        showNormal = strchr(functypes, 'n') != NULL;
 1730 peter_e                   297             143 :     bool        showProcedure = strchr(functypes, 'p') != NULL;
 5087 tgl                       298             143 :     bool        showTrigger = strchr(functypes, 't') != NULL;
                                299             143 :     bool        showWindow = strchr(functypes, 'w') != NULL;
                                300                 :     bool        have_where;
                                301                 :     PQExpBufferData buf;
                                302                 :     PGresult   *res;
 8486 peter_e                   303             143 :     printQueryOpt myopt = pset.popt;
                                304                 :     static const bool translate_columns[] = {false, false, false, false, true, true, true, false, true, false, false, false, false};
                                305                 : 
                                306                 :     /* No "Parallel" column before 9.6 */
                                307                 :     static const bool translate_columns_pre_96[] = {false, false, false, false, true, true, false, true, false, false, false, false};
                                308                 : 
 1730                           309             143 :     if (strlen(functypes) != strspn(functypes, "anptwS+"))
                                310                 :     {
 1469 peter                     311 UBC           0 :         pg_log_error("\\df only takes [anptwS+] as options");
 1730 peter_e                   312               0 :         return true;
                                313                 :     }
                                314                 : 
 1730 peter_e                   315 CBC         143 :     if (showProcedure && pset.sversion < 110000)
                                316                 :     {
                                317                 :         char        sverbuf[32];
                                318                 : 
 1469 peter                     319 UBC           0 :         pg_log_error("\\df does not take a \"%c\" option with server version %s",
                                320                 :                      'p',
                                321                 :                      formatPGVersionNumber(pset.sversion, false,
                                322                 :                                            sverbuf, sizeof(sverbuf)));
 5101 bruce                     323               0 :         return true;
                                324                 :     }
                                325                 : 
 1730 peter_e                   326 CBC         143 :     if (!showAggregate && !showNormal && !showProcedure && !showTrigger && !showWindow)
                                327                 :     {
  479 tgl                       328             134 :         showAggregate = showNormal = showTrigger = showWindow = true;
 1730 peter_e                   329             134 :         if (pset.sversion >= 110000)
                                330             134 :             showProcedure = true;
                                331                 :     }
                                332                 : 
 7655                           333             143 :     initPQExpBuffer(&buf);
                                334                 : 
                                335             143 :     printfPQExpBuffer(&buf,
                                336                 :                       "SELECT n.nspname as \"%s\",\n"
                                337                 :                       "  p.proname as \"%s\",\n",
                                338                 :                       gettext_noop("Schema"),
                                339                 :                       gettext_noop("Name"));
                                340                 : 
 1864                           341             143 :     if (pset.sversion >= 110000)
                                342             143 :         appendPQExpBuffer(&buf,
                                343                 :                           "  pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n"
                                344                 :                           "  pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n"
                                345                 :                           " CASE p.prokind\n"
                                346                 :                           "  WHEN 'a' THEN '%s'\n"
                                347                 :                           "  WHEN 'w' THEN '%s'\n"
                                348                 :                           "  WHEN 'p' THEN '%s'\n"
                                349                 :                           "  ELSE '%s'\n"
                                350                 :                           " END as \"%s\"",
                                351                 :                           gettext_noop("Result data type"),
                                352                 :                           gettext_noop("Argument data types"),
                                353                 :         /* translator: "agg" is short for "aggregate" */
                                354                 :                           gettext_noop("agg"),
                                355                 :                           gettext_noop("window"),
                                356                 :                           gettext_noop("proc"),
                                357                 :                           gettext_noop("func"),
                                358                 :                           gettext_noop("Type"));
                                359                 :     else
 5378 tgl                       360 UBC           0 :         appendPQExpBuffer(&buf,
                                361                 :                           "  pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n"
                                362                 :                           "  pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n"
                                363                 :                           " CASE\n"
                                364                 :                           "  WHEN p.proisagg THEN '%s'\n"
                                365                 :                           "  WHEN p.proiswindow THEN '%s'\n"
                                366                 :                           "  WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN '%s'\n"
                                367                 :                           "  ELSE '%s'\n"
                                368                 :                           " END as \"%s\"",
                                369                 :                           gettext_noop("Result data type"),
                                370                 :                           gettext_noop("Argument data types"),
                                371                 :         /* translator: "agg" is short for "aggregate" */
                                372                 :                           gettext_noop("agg"),
                                373                 :                           gettext_noop("window"),
                                374                 :                           gettext_noop("trigger"),
                                375                 :                           gettext_noop("func"),
                                376                 :                           gettext_noop("Type"));
                                377                 : 
 8397 bruce                     378 CBC         143 :     if (verbose)
                                379                 :     {
 7655 peter_e                   380               3 :         appendPQExpBuffer(&buf,
                                381                 :                           ",\n CASE\n"
                                382                 :                           "  WHEN p.provolatile = 'i' THEN '%s'\n"
                                383                 :                           "  WHEN p.provolatile = 's' THEN '%s'\n"
                                384                 :                           "  WHEN p.provolatile = 'v' THEN '%s'\n"
                                385                 :                           " END as \"%s\"",
                                386                 :                           gettext_noop("immutable"),
                                387                 :                           gettext_noop("stable"),
                                388                 :                           gettext_noop("volatile"),
                                389                 :                           gettext_noop("Volatility"));
 2463 tgl                       390               3 :         if (pset.sversion >= 90600)
                                391               3 :             appendPQExpBuffer(&buf,
                                392                 :                               ",\n CASE\n"
                                393                 :                               "  WHEN p.proparallel = 'r' THEN '%s'\n"
                                394                 :                               "  WHEN p.proparallel = 's' THEN '%s'\n"
                                395                 :                               "  WHEN p.proparallel = 'u' THEN '%s'\n"
                                396                 :                               " END as \"%s\"",
                                397                 :                               gettext_noop("restricted"),
                                398                 :                               gettext_noop("safe"),
                                399                 :                               gettext_noop("unsafe"),
                                400                 :                               gettext_noop("Parallel"));
                                401               3 :         appendPQExpBuffer(&buf,
                                402                 :                           ",\n pg_catalog.pg_get_userbyid(p.proowner) as \"%s\""
                                403                 :                           ",\n CASE WHEN prosecdef THEN '%s' ELSE '%s' END AS \"%s\"",
                                404                 :                           gettext_noop("Owner"),
                                405                 :                           gettext_noop("definer"),
                                406                 :                           gettext_noop("invoker"),
                                407                 :                           gettext_noop("Security"));
                                408               3 :         appendPQExpBufferStr(&buf, ",\n ");
                                409               3 :         printACLColumn(&buf, "p.proacl");
                                410               3 :         appendPQExpBuffer(&buf,
                                411                 :                           ",\n l.lanname as \"%s\"",
                                412                 :                           gettext_noop("Language"));
   38 tgl                       413 GNC           3 :         appendPQExpBuffer(&buf,
                                414                 :                           ",\n CASE WHEN l.lanname IN ('internal', 'c') THEN p.prosrc END as \"%s\"",
                                415                 :                           gettext_noop("Internal name"));
  732 peter                     416 CBC           3 :         appendPQExpBuffer(&buf,
                                417                 :                           ",\n pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"",
                                418                 :                           gettext_noop("Description"));
                                419                 :     }
 8535 bruce                     420 ECB             : 
 3429 heikki.linnakangas        421 GIC         143 :     appendPQExpBufferStr(&buf,
 3429 heikki.linnakangas        422 ECB             :                          "\nFROM pg_catalog.pg_proc p"
                                423                 :                          "\n     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n");
                                424                 : 
  732 tgl                       425 GIC         176 :     for (int i = 0; i < num_arg_patterns; i++)
                                426                 :     {
                                427              33 :         appendPQExpBuffer(&buf,
  732 tgl                       428 ECB             :                           "     LEFT JOIN pg_catalog.pg_type t%d ON t%d.oid = p.proargtypes[%d]\n"
                                429                 :                           "     LEFT JOIN pg_catalog.pg_namespace nt%d ON nt%d.oid = t%d.typnamespace\n",
                                430                 :                           i, i, i, i, i, i);
                                431                 :     }
                                432                 : 
 5393 tgl                       433 GIC         143 :     if (verbose)
 3429 heikki.linnakangas        434               3 :         appendPQExpBufferStr(&buf,
 2118 tgl                       435 ECB             :                              "     LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang\n");
                                436                 : 
 5087 tgl                       437 CBC         143 :     have_where = false;
                                438                 : 
 5087 tgl                       439 ECB             :     /* filter by function type, if requested */
 1730 peter_e                   440 GIC         143 :     if (showNormal && showAggregate && showProcedure && showTrigger && showWindow)
 5050 bruce                     441 ECB             :          /* Do nothing */ ;
 5101 bruce                     442 GBC           9 :     else if (showNormal)
                                443                 :     {
 5101 bruce                     444 GIC           3 :         if (!showAggregate)
 5087 tgl                       445 ECB             :         {
 5087 tgl                       446 CBC           3 :             if (have_where)
 3429 heikki.linnakangas        447 UIC           0 :                 appendPQExpBufferStr(&buf, "      AND ");
 5087 tgl                       448 ECB             :             else
                                449                 :             {
 3429 heikki.linnakangas        450 GIC           3 :                 appendPQExpBufferStr(&buf, "WHERE ");
 5087 tgl                       451 GBC           3 :                 have_where = true;
                                452                 :             }
 1864 peter_e                   453 CBC           3 :             if (pset.sversion >= 110000)
 1864 peter_e                   454 GIC           3 :                 appendPQExpBufferStr(&buf, "p.prokind <> 'a'\n");
 1864 peter_e                   455 ECB             :             else
 1864 peter_e                   456 LBC           0 :                 appendPQExpBufferStr(&buf, "NOT p.proisagg\n");
                                457                 :         }
 1730 peter_e                   458 GIC           3 :         if (!showProcedure && pset.sversion >= 110000)
 1730 peter_e                   459 EUB             :         {
 1730 peter_e                   460 GBC           3 :             if (have_where)
 1730 peter_e                   461 GIC           3 :                 appendPQExpBufferStr(&buf, "      AND ");
 1730 peter_e                   462 ECB             :             else
                                463                 :             {
 1730 peter_e                   464 LBC           0 :                 appendPQExpBufferStr(&buf, "WHERE ");
 1730 peter_e                   465 UIC           0 :                 have_where = true;
 1730 peter_e                   466 ECB             :             }
 1730 peter_e                   467 CBC           3 :             appendPQExpBufferStr(&buf, "p.prokind <> 'p'\n");
                                468                 :         }
 5101 bruce                     469 GIC           3 :         if (!showTrigger)
 5101 bruce                     470 EUB             :         {
 5087 tgl                       471 GBC           3 :             if (have_where)
 3429 heikki.linnakangas        472 GIC           3 :                 appendPQExpBufferStr(&buf, "      AND ");
 5087 tgl                       473 ECB             :             else
                                474                 :             {
 3429 heikki.linnakangas        475 LBC           0 :                 appendPQExpBufferStr(&buf, "WHERE ");
 5087 tgl                       476 UIC           0 :                 have_where = true;
 5087 tgl                       477 ECB             :             }
 3429 heikki.linnakangas        478 CBC           3 :             appendPQExpBufferStr(&buf, "p.prorettype <> 'pg_catalog.trigger'::pg_catalog.regtype\n");
                                479                 :         }
  479 tgl                       480 GIC           3 :         if (!showWindow)
 5087 tgl                       481 EUB             :         {
 5087 tgl                       482 GBC           3 :             if (have_where)
 3429 heikki.linnakangas        483 GIC           3 :                 appendPQExpBufferStr(&buf, "      AND ");
 5101 bruce                     484 ECB             :             else
 5087 tgl                       485                 :             {
 3429 heikki.linnakangas        486 UIC           0 :                 appendPQExpBufferStr(&buf, "WHERE ");
 5087 tgl                       487 UBC           0 :                 have_where = true;
                                488                 :             }
 1864 peter_e                   489 GIC           3 :             if (pset.sversion >= 110000)
                                490               3 :                 appendPQExpBufferStr(&buf, "p.prokind <> 'w'\n");
                                491                 :             else
 1864 peter_e                   492 LBC           0 :                 appendPQExpBufferStr(&buf, "NOT p.proiswindow\n");
                                493                 :         }
 5101 bruce                     494 ECB             :     }
                                495                 :     else
                                496                 :     {
 5050 bruce                     497 CBC           6 :         bool        needs_or = false;
                                498                 : 
 3429 heikki.linnakangas        499               6 :         appendPQExpBufferStr(&buf, "WHERE (\n       ");
 5087 tgl                       500               6 :         have_where = true;
                                501                 :         /* Note: at least one of these must be true ... */
 5101 bruce                     502 GBC           6 :         if (showAggregate)
 5101 bruce                     503 ECB             :         {
 1864 peter_e                   504 GIC           3 :             if (pset.sversion >= 110000)
 1864 peter_e                   505 CBC           3 :                 appendPQExpBufferStr(&buf, "p.prokind = 'a'\n");
                                506                 :             else
 1864 peter_e                   507 UBC           0 :                 appendPQExpBufferStr(&buf, "p.proisagg\n");
 5101 bruce                     508 GBC           3 :             needs_or = true;
 5101 bruce                     509 EUB             :         }
 5101 bruce                     510 GIC           6 :         if (showTrigger)
 5101 bruce                     511 EUB             :         {
 5101 bruce                     512 UIC           0 :             if (needs_or)
 3429 heikki.linnakangas        513 LBC           0 :                 appendPQExpBufferStr(&buf, "       OR ");
 3429 heikki.linnakangas        514 UIC           0 :             appendPQExpBufferStr(&buf,
 2118 tgl                       515 ECB             :                                  "p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype\n");
 5101 bruce                     516 UBC           0 :             needs_or = true;
 5101 bruce                     517 ECB             :         }
 1730 peter_e                   518 CBC           6 :         if (showProcedure)
                                519                 :         {
                                520               3 :             if (needs_or)
 1730 peter_e                   521 UIC           0 :                 appendPQExpBufferStr(&buf, "       OR ");
 1730 peter_e                   522 GBC           3 :             appendPQExpBufferStr(&buf, "p.prokind = 'p'\n");
                                523               3 :             needs_or = true;
 1730 peter_e                   524 EUB             :         }
 5101 bruce                     525 GBC           6 :         if (showWindow)
                                526                 :         {
 5101 bruce                     527 UBC           0 :             if (needs_or)
 3429 heikki.linnakangas        528 UIC           0 :                 appendPQExpBufferStr(&buf, "       OR ");
 1864 peter_e                   529 LBC           0 :             if (pset.sversion >= 110000)
 1864 peter_e                   530 UIC           0 :                 appendPQExpBufferStr(&buf, "p.prokind = 'w'\n");
                                531                 :             else
 1864 peter_e                   532 LBC           0 :                 appendPQExpBufferStr(&buf, "p.proiswindow\n");
                                533                 :         }
 3429 heikki.linnakangas        534 GIC           6 :         appendPQExpBufferStr(&buf, "      )\n");
                                535                 :     }
 7547 tgl                       536 ECB             : 
  354 rhaas                     537 GIC         143 :     if (!validateSQLNamePattern(&buf, func_pattern, have_where, false,
  354 rhaas                     538 ECB             :                                 "n.nspname", "p.proname", NULL,
                                539                 :                                 "pg_catalog.pg_function_is_visible(p.oid)",
                                540                 :                                 NULL, 3))
  262 michael                   541 GIC          12 :         goto error_return;
                                542                 : 
  732 tgl                       543             164 :     for (int i = 0; i < num_arg_patterns; i++)
                                544                 :     {
                                545              33 :         if (strcmp(arg_patterns[i], "-") != 0)
                                546                 :         {
                                547                 :             /*
                                548                 :              * Match type-name patterns against either internal or external
                                549                 :              * name, like \dT.  Unlike \dT, there seems no reason to
                                550                 :              * discriminate against arrays or composite types.
                                551                 :              */
  732 tgl                       552 ECB             :             char        nspname[64];
                                553                 :             char        typname[64];
                                554                 :             char        ft[64];
                                555                 :             char        tiv[64];
                                556                 : 
  732 tgl                       557 GIC          30 :             snprintf(nspname, sizeof(nspname), "nt%d.nspname", i);
  732 tgl                       558 CBC          30 :             snprintf(typname, sizeof(typname), "t%d.typname", i);
                                559              30 :             snprintf(ft, sizeof(ft),
                                560                 :                      "pg_catalog.format_type(t%d.oid, NULL)", i);
  732 tgl                       561 GIC          30 :             snprintf(tiv, sizeof(tiv),
                                562                 :                      "pg_catalog.pg_type_is_visible(t%d.oid)", i);
  354 rhaas                     563 GBC          30 :             if (!validateSQLNamePattern(&buf,
  354 rhaas                     564 GIC          30 :                                         map_typename_pattern(arg_patterns[i]),
                                565                 :                                         true, false,
                                566                 :                                         nspname, typname, ft, tiv,
                                567                 :                                         NULL, 3))
  262 michael                   568 LBC           0 :                 goto error_return;
                                569                 :         }
                                570                 :         else
                                571                 :         {
  732 tgl                       572 ECB             :             /* "-" pattern specifies no such parameter */
  732 tgl                       573 CBC           3 :             appendPQExpBuffer(&buf, "  AND t%d.typname IS NULL\n", i);
                                574                 :         }
                                575                 :     }
  732 tgl                       576 ECB             : 
  732 tgl                       577 GIC         131 :     if (!showSystem && !func_pattern)
 3429 heikki.linnakangas        578 CBC           1 :         appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
 3260 bruce                     579 ECB             :                              "      AND n.nspname <> 'information_schema'\n");
 5206                           580                 : 
 3429 heikki.linnakangas        581 GBC         131 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
                                582                 : 
 3090 fujii                     583 CBC         131 :     res = PSQLexec(buf.data);
 7655 peter_e                   584             131 :     termPQExpBuffer(&buf);
 8557 bruce                     585             131 :     if (!res)
 8557 bruce                     586 LBC           0 :         return false;
                                587                 : 
 8557 bruce                     588 CBC         131 :     myopt.nullPrint = NULL;
 7953 peter_e                   589             131 :     myopt.title = _("List of functions");
 5382 bruce                     590 GIC         131 :     myopt.translate_header = true;
 2463 tgl                       591             131 :     if (pset.sversion >= 90600)
                                592                 :     {
 2463 tgl                       593 GBC         131 :         myopt.translate_columns = translate_columns;
                                594             131 :         myopt.n_translate_columns = lengthof(translate_columns);
                                595                 :     }
                                596                 :     else
 2463 tgl                       597 ECB             :     {
 2463 tgl                       598 UIC           0 :         myopt.translate_columns = translate_columns_pre_96;
 2463 tgl                       599 LBC           0 :         myopt.n_translate_columns = lengthof(translate_columns_pre_96);
 2463 tgl                       600 ECB             :     }
                                601                 : 
 2685 tgl                       602 CBC         131 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 8557 bruce                     603 ECB             : 
 8557 bruce                     604 CBC         131 :     PQclear(res);
 8557 bruce                     605 GIC         131 :     return true;
                                606                 : 
  262 michael                   607              12 : error_return:
                                608              12 :     termPQExpBuffer(&buf);
                                609              12 :     return false;
                                610                 : }
                                611                 : 
                                612                 : 
                                613                 : 
 8557 bruce                     614 ECB             : /*
                                615                 :  * \dT
                                616                 :  * describe types
                                617                 :  */
                                618                 : bool
 5206 bruce                     619 GIC          28 : describeTypes(const char *pattern, bool verbose, bool showSystem)
 8557 bruce                     620 ECB             : {
                                621                 :     PQExpBufferData buf;
                                622                 :     PGresult   *res;
 8486 peter_e                   623 GIC          28 :     printQueryOpt myopt = pset.popt;
                                624                 : 
 7655                           625              28 :     initPQExpBuffer(&buf);
                                626                 : 
 7655 peter_e                   627 CBC          28 :     printfPQExpBuffer(&buf,
                                628                 :                       "SELECT n.nspname as \"%s\",\n"
 6385 bruce                     629 EUB             :                       "  pg_catalog.format_type(t.oid, NULL) AS \"%s\",\n",
                                630                 :                       gettext_noop("Schema"),
                                631                 :                       gettext_noop("Name"));
 8397 bruce                     632 GIC          28 :     if (verbose)
                                633                 :     {
 7655 peter_e                   634 UIC           0 :         appendPQExpBuffer(&buf,
                                635                 :                           "  t.typname AS \"%s\",\n"
                                636                 :                           "  CASE WHEN t.typrelid != 0\n"
                                637                 :                           "      THEN CAST('tuple' AS pg_catalog.text)\n"
                                638                 :                           "    WHEN t.typlen < 0\n"
                                639                 :                           "      THEN CAST('var' AS pg_catalog.text)\n"
                                640                 :                           "    ELSE CAST(t.typlen AS pg_catalog.text)\n"
                                641                 :                           "  END AS \"%s\",\n"
                                642                 :                           "  pg_catalog.array_to_string(\n"
                                643                 :                           "      ARRAY(\n"
                                644                 :                           "          SELECT e.enumlabel\n"
                                645                 :                           "          FROM pg_catalog.pg_enum e\n"
                                646                 :                           "          WHERE e.enumtypid = t.oid\n"
                                647                 :                           "          ORDER BY e.enumsortorder\n"
                                648                 :                           "      ),\n"
                                649                 :                           "      E'\\n'\n"
                                650                 :                           "  ) AS \"%s\",\n"
 2118 tgl                       651 EUB             :                           "  pg_catalog.pg_get_userbyid(t.typowner) AS \"%s\",\n",
  479                           652                 :                           gettext_noop("Internal name"),
                                653                 :                           gettext_noop("Size"),
                                654                 :                           gettext_noop("Elements"),
 2922 magnus                    655 ECB             :                           gettext_noop("Owner"));
 4128 peter_e                   656 UIC           0 :         printACLColumn(&buf, "t.typacl");
 3429 heikki.linnakangas        657               0 :         appendPQExpBufferStr(&buf, ",\n  ");
                                658                 :     }
 5393 tgl                       659 ECB             : 
 7655 peter_e                   660 GIC          28 :     appendPQExpBuffer(&buf,
                                661                 :                       "  pg_catalog.obj_description(t.oid, 'pg_type') as \"%s\"\n",
                                662                 :                       gettext_noop("Description"));
                                663                 : 
 3429 heikki.linnakangas        664              28 :     appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_type t\n"
                                665                 :                          "     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
 7547 tgl                       666 ECB             : 
 8397 bruce                     667                 :     /*
                                668                 :      * do not include complex types (typrelid!=0) unless they are standalone
                                669                 :      * composite types
                                670                 :      */
 3429 heikki.linnakangas        671 GIC          28 :     appendPQExpBufferStr(&buf, "WHERE (t.typrelid = 0 ");
 2222 tgl                       672              28 :     appendPQExpBufferStr(&buf, "OR (SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
                                673                 :                          " FROM pg_catalog.pg_class c "
 3260 bruce                     674 ECB             :                          "WHERE c.oid = t.typrelid))\n");
 5050                           675                 : 
                                676                 :     /*
  479 tgl                       677                 :      * do not include array types unless the pattern contains []
 5393                           678                 :      */
  732 tgl                       679 GIC          28 :     if (pattern == NULL || strstr(pattern, "[]") == NULL)
  479                           680              28 :         appendPQExpBufferStr(&buf, "  AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n");
                                681                 : 
 5050 bruce                     682 CBC          28 :     if (!showSystem && !pattern)
 3429 heikki.linnakangas        683 GIC           3 :         appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
                                684                 :                              "      AND n.nspname <> 'information_schema'\n");
                                685                 : 
                                686                 :     /* Match name pattern against either internal or external name */
  354 rhaas                     687              28 :     if (!validateSQLNamePattern(&buf, map_typename_pattern(pattern),
                                688                 :                                 true, false,
  354 rhaas                     689 ECB             :                                 "n.nspname", "t.typname",
                                690                 :                                 "pg_catalog.format_type(t.oid, NULL)",
                                691                 :                                 "pg_catalog.pg_type_is_visible(t.oid)",
                                692                 :                                 NULL, 3))
  262 michael                   693                 :     {
  262 michael                   694 GIC          12 :         termPQExpBuffer(&buf);
  354 rhaas                     695 CBC          12 :         return false;
  262 michael                   696 ECB             :     }
 8557 bruce                     697                 : 
 3429 heikki.linnakangas        698 GBC          16 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
                                699                 : 
 3090 fujii                     700 CBC          16 :     res = PSQLexec(buf.data);
 7655 peter_e                   701              16 :     termPQExpBuffer(&buf);
 8557 bruce                     702              16 :     if (!res)
 8557 bruce                     703 UIC           0 :         return false;
 8557 bruce                     704 ECB             : 
 8557 bruce                     705 GIC          16 :     myopt.nullPrint = NULL;
 7953 peter_e                   706 CBC          16 :     myopt.title = _("List of data types");
 5382 bruce                     707              16 :     myopt.translate_header = true;
                                708                 : 
 2685 tgl                       709 GIC          16 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                                710                 : 
 8557 bruce                     711              16 :     PQclear(res);
                                712              16 :     return true;
                                713                 : }
                                714                 : 
                                715                 : /*
                                716                 :  * Map some variant type names accepted by the backend grammar into
                                717                 :  * canonical type names.
                                718                 :  *
                                719                 :  * Helper for \dT and other functions that take typename patterns.
  732 tgl                       720 ECB             :  * This doesn't completely mask the fact that these names are special;
                                721                 :  * for example, a pattern of "dec*" won't magically match "numeric".
                                722                 :  * But it goes a long way to reduce the surprise factor.
                                723                 :  */
                                724                 : static const char *
  732 tgl                       725 GIC          67 : map_typename_pattern(const char *pattern)
                                726                 : {
                                727                 :     static const char *const typename_map[] = {
                                728                 :         /*
                                729                 :          * These names are accepted by gram.y, although they are neither the
                                730                 :          * "real" name seen in pg_type nor the canonical name printed by
                                731                 :          * format_type().
                                732                 :          */
                                733                 :         "decimal", "numeric",
                                734                 :         "float", "double precision",
                                735                 :         "int", "integer",
                                736                 : 
                                737                 :         /*
                                738                 :          * We also have to map the array names for cases where the canonical
                                739                 :          * name is different from what pg_type says.
                                740                 :          */
                                741                 :         "bool[]", "boolean[]",
                                742                 :         "decimal[]", "numeric[]",
                                743                 :         "float[]", "double precision[]",
                                744                 :         "float4[]", "real[]",
                                745                 :         "float8[]", "double precision[]",
                                746                 :         "int[]", "integer[]",
                                747                 :         "int2[]", "smallint[]",
                                748                 :         "int4[]", "integer[]",
                                749                 :         "int8[]", "bigint[]",
                                750                 :         "time[]", "time without time zone[]",
                                751                 :         "timetz[]", "time with time zone[]",
                                752                 :         "timestamp[]", "timestamp without time zone[]",
                                753                 :         "timestamptz[]", "timestamp with time zone[]",
  732 tgl                       754 ECB             :         "varbit[]", "bit varying[]",
                                755                 :         "varchar[]", "character varying[]",
                                756                 :         NULL
                                757                 :     };
                                758                 : 
  732 tgl                       759 GBC          67 :     if (pattern == NULL)
  732 tgl                       760 GIC           3 :         return NULL;
  732 tgl                       761 CBC        1216 :     for (int i = 0; typename_map[i] != NULL; i += 2)
                                762                 :     {
  732 tgl                       763 GIC        1152 :         if (pg_strcasecmp(pattern, typename_map[i]) == 0)
  732 tgl                       764 UIC           0 :             return typename_map[i + 1];
                                765                 :     }
  732 tgl                       766 GIC          64 :     return pattern;
                                767                 : }
                                768                 : 
                                769                 : 
 2082 tgl                       770 ECB             : /*
                                771                 :  * \do
                                772                 :  * Describe operators
                                773                 :  */
                                774                 : bool
  732 tgl                       775 GIC          31 : describeOperators(const char *oper_pattern,
  732 tgl                       776 ECB             :                   char **arg_patterns, int num_arg_patterns,
                                777                 :                   bool verbose, bool showSystem)
 8557 bruce                     778                 : {
                                779                 :     PQExpBufferData buf;
                                780                 :     PGresult   *res;
 8486 peter_e                   781 GIC          31 :     printQueryOpt myopt = pset.popt;
                                782                 : 
 7655                           783              31 :     initPQExpBuffer(&buf);
                                784                 : 
                                785                 :     /*
                                786                 :      * Note: before Postgres 9.1, we did not assign comments to any built-in
                                787                 :      * operators, preferring to let the comment on the underlying function
                                788                 :      * suffice.  The coalesce() on the obj_description() calls below supports
                                789                 :      * this convention by providing a fallback lookup of a comment on the
                                790                 :      * operator's function.  Since 9.1 there is a policy that every built-in
                                791                 :      * operator should have a comment; so the coalesce() is no longer
                                792                 :      * necessary so far as built-in operators are concerned.  We keep it
                                793                 :      * anyway, for now, because third-party modules may still be following the
                                794                 :      * old convention.
                                795                 :      *
  934 tgl                       796 ECB             :      * The support for postfix operators in this query is dead code as of
                                797                 :      * Postgres 14, but we need to keep it for as long as we support talking
                                798                 :      * to pre-v14 servers.
                                799                 :      */
                                800                 : 
 7655 peter_e                   801 GIC          31 :     printfPQExpBuffer(&buf,
                                802                 :                       "SELECT n.nspname as \"%s\",\n"
                                803                 :                       "  o.oprname AS \"%s\",\n"
                                804                 :                       "  CASE WHEN o.oprkind='l' THEN NULL ELSE pg_catalog.format_type(o.oprleft, NULL) END AS \"%s\",\n"
                                805                 :                       "  CASE WHEN o.oprkind='r' THEN NULL ELSE pg_catalog.format_type(o.oprright, NULL) END AS \"%s\",\n"
                                806                 :                       "  pg_catalog.format_type(o.oprresult, NULL) AS \"%s\",\n",
                                807                 :                       gettext_noop("Schema"),
 5597 tgl                       808 ECB             :                       gettext_noop("Name"),
 5597 tgl                       809 EUB             :                       gettext_noop("Left arg type"),
                                810                 :                       gettext_noop("Right arg type"),
                                811                 :                       gettext_noop("Result type"));
                                812                 : 
 3370 tgl                       813 CBC          31 :     if (verbose)
 3370 tgl                       814 UIC           0 :         appendPQExpBuffer(&buf,
                                815                 :                           "  o.oprcode AS \"%s\",\n",
                                816                 :                           gettext_noop("Function"));
                                817                 : 
 3370 tgl                       818 GIC          31 :     appendPQExpBuffer(&buf,
                                819                 :                       "  coalesce(pg_catalog.obj_description(o.oid, 'pg_operator'),\n"
 2118 tgl                       820 ECB             :                       "           pg_catalog.obj_description(o.oprcode, 'pg_proc')) AS \"%s\"\n"
                                821                 :                       "FROM pg_catalog.pg_operator o\n"
                                822                 :                       "     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace\n",
 5597                           823                 :                       gettext_noop("Description"));
                                824                 : 
  732 tgl                       825 GIC          31 :     if (num_arg_patterns >= 2)
                                826                 :     {
                                827               3 :         num_arg_patterns = 2;   /* ignore any additional arguments */
                                828               3 :         appendPQExpBufferStr(&buf,
  732 tgl                       829 ECB             :                              "     LEFT JOIN pg_catalog.pg_type t0 ON t0.oid = o.oprleft\n"
                                830                 :                              "     LEFT JOIN pg_catalog.pg_namespace nt0 ON nt0.oid = t0.typnamespace\n"
                                831                 :                              "     LEFT JOIN pg_catalog.pg_type t1 ON t1.oid = o.oprright\n"
                                832                 :                              "     LEFT JOIN pg_catalog.pg_namespace nt1 ON nt1.oid = t1.typnamespace\n");
                                833                 :     }
  732 tgl                       834 GIC          28 :     else if (num_arg_patterns == 1)
                                835                 :     {
  732 tgl                       836 CBC           3 :         appendPQExpBufferStr(&buf,
  732 tgl                       837 ECB             :                              "     LEFT JOIN pg_catalog.pg_type t0 ON t0.oid = o.oprright\n"
                                838                 :                              "     LEFT JOIN pg_catalog.pg_namespace nt0 ON nt0.oid = t0.typnamespace\n");
                                839                 :     }
                                840                 : 
  732 tgl                       841 CBC          31 :     if (!showSystem && !oper_pattern)
 3429 heikki.linnakangas        842 GIC           1 :         appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
                                843                 :                              "      AND n.nspname <> 'information_schema'\n");
                                844                 : 
  354 rhaas                     845 CBC          31 :     if (!validateSQLNamePattern(&buf, oper_pattern,
  354 rhaas                     846 GIC          31 :                                 !showSystem && !oper_pattern, true,
  354 rhaas                     847 ECB             :                                 "n.nspname", "o.oprname", NULL,
                                848                 :                                 "pg_catalog.pg_operator_is_visible(o.oid)",
                                849                 :                                 NULL, 3))
  262 michael                   850 CBC          12 :         goto error_return;
                                851                 : 
  732 tgl                       852              19 :     if (num_arg_patterns == 1)
  732 tgl                       853 GIC           3 :         appendPQExpBufferStr(&buf, "  AND o.oprleft = 0\n");
                                854                 : 
                                855              28 :     for (int i = 0; i < num_arg_patterns; i++)
                                856                 :     {
                                857               9 :         if (strcmp(arg_patterns[i], "-") != 0)
                                858                 :         {
                                859                 :             /*
                                860                 :              * Match type-name patterns against either internal or external
                                861                 :              * name, like \dT.  Unlike \dT, there seems no reason to
                                862                 :              * discriminate against arrays or composite types.
                                863                 :              */
  732 tgl                       864 ECB             :             char        nspname[64];
                                865                 :             char        typname[64];
                                866                 :             char        ft[64];
                                867                 :             char        tiv[64];
                                868                 : 
  732 tgl                       869 GIC           9 :             snprintf(nspname, sizeof(nspname), "nt%d.nspname", i);
  732 tgl                       870 CBC           9 :             snprintf(typname, sizeof(typname), "t%d.typname", i);
                                871               9 :             snprintf(ft, sizeof(ft),
                                872                 :                      "pg_catalog.format_type(t%d.oid, NULL)", i);
  732 tgl                       873 GIC           9 :             snprintf(tiv, sizeof(tiv),
                                874                 :                      "pg_catalog.pg_type_is_visible(t%d.oid)", i);
  354 rhaas                     875 GBC           9 :             if (!validateSQLNamePattern(&buf,
  354 rhaas                     876 GIC           9 :                                         map_typename_pattern(arg_patterns[i]),
                                877                 :                                         true, false,
                                878                 :                                         nspname, typname, ft, tiv,
                                879                 :                                         NULL, 3))
  262 michael                   880 UBC           0 :                 goto error_return;
                                881                 :         }
                                882                 :         else
                                883                 :         {
  732 tgl                       884 ECB             :             /* "-" pattern specifies no such parameter */
  732 tgl                       885 UIC           0 :             appendPQExpBuffer(&buf, "  AND t%d.typname IS NULL\n", i);
  732 tgl                       886 ECB             :         }
                                887                 :     }
                                888                 : 
 3429 heikki.linnakangas        889 GBC          19 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3, 4;");
                                890                 : 
 3090 fujii                     891 CBC          19 :     res = PSQLexec(buf.data);
 7655 peter_e                   892              19 :     termPQExpBuffer(&buf);
 8557 bruce                     893              19 :     if (!res)
 8557 bruce                     894 UIC           0 :         return false;
 8557 bruce                     895 ECB             : 
 8557 bruce                     896 GIC          19 :     myopt.nullPrint = NULL;
 7953 peter_e                   897 CBC          19 :     myopt.title = _("List of operators");
 5382 bruce                     898              19 :     myopt.translate_header = true;
                                899                 : 
 2685 tgl                       900              19 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 8557 bruce                     901 ECB             : 
 8557 bruce                     902 CBC          19 :     PQclear(res);
 8557 bruce                     903 GIC          19 :     return true;
                                904                 : 
  262 michael                   905              12 : error_return:
                                906              12 :     termPQExpBuffer(&buf);
                                907              12 :     return false;
                                908                 : }
                                909                 : 
                                910                 : 
                                911                 : /*
 8557 bruce                     912 EUB             :  * listAllDbs
                                913                 :  *
                                914                 :  * for \l, \list, and -l switch
                                915                 :  */
                                916                 : bool
 3689 peter_e                   917 UIC           0 : listAllDbs(const char *pattern, bool verbose)
 8557 bruce                     918 EUB             : {
                                919                 :     PGresult   *res;
 7655 peter_e                   920                 :     PQExpBufferData buf;
 8486 peter_e                   921 UIC           0 :     printQueryOpt myopt = pset.popt;
                                922                 : 
 7655                           923               0 :     initPQExpBuffer(&buf);
                                924                 : 
                                925               0 :     printfPQExpBuffer(&buf,
                                926                 :                       "SELECT\n"
                                927                 :                       "  d.datname as \"%s\",\n"
                                928                 :                       "  pg_catalog.pg_get_userbyid(d.datdba) as \"%s\",\n"
                                929                 :                       "  pg_catalog.pg_encoding_to_char(d.encoding) as \"%s\",\n",
                                930                 :                       gettext_noop("Name"),
                                931                 :                       gettext_noop("Owner"),
                                932                 :                       gettext_noop("Encoding"));
  388 peter                     933 UNC           0 :     if (pset.sversion >= 150000)
                                934               0 :         appendPQExpBuffer(&buf,
                                935                 :                           "  CASE d.datlocprovider WHEN 'c' THEN 'libc' WHEN 'i' THEN 'icu' END AS \"%s\",\n",
                                936                 :                           gettext_noop("Locale Provider"));
                                937                 :     else
                                938               0 :         appendPQExpBuffer(&buf,
                                939                 :                           "  'libc' AS \"%s\",\n",
                                940                 :                           gettext_noop("Locale Provider"));
   32                           941               0 :     appendPQExpBuffer(&buf,
                                942                 :                       "  d.datcollate as \"%s\",\n"
                                943                 :                       "  d.datctype as \"%s\",\n",
                                944                 :                       gettext_noop("Collate"),
                                945                 :                       gettext_noop("Ctype"));
   32 peter                     946 UBC           0 :     if (pset.sversion >= 150000)
   32 peter                     947 UIC           0 :         appendPQExpBuffer(&buf,
                                948                 :                           "  d.daticulocale as \"%s\",\n",
                                949                 :                           gettext_noop("ICU Locale"));
   32 peter                     950 EUB             :     else
   32 peter                     951 UIC           0 :         appendPQExpBuffer(&buf,
                                952                 :                           "  NULL as \"%s\",\n",
                                953                 :                           gettext_noop("ICU Locale"));
   32 peter                     954 UNC           0 :     if (pset.sversion >= 160000)
                                955               0 :         appendPQExpBuffer(&buf,
                                956                 :                           "  d.daticurules as \"%s\",\n",
                                957                 :                           gettext_noop("ICU Rules"));
                                958                 :     else
                                959               0 :         appendPQExpBuffer(&buf,
                                960                 :                           "  NULL as \"%s\",\n",
                                961                 :                           gettext_noop("ICU Rules"));
                                962               0 :     appendPQExpBufferStr(&buf, "  ");
 5212 tgl                       963 UBC           0 :     printACLColumn(&buf, "d.datacl");
  479                           964               0 :     if (verbose)
 5488 tgl                       965 UIC           0 :         appendPQExpBuffer(&buf,
                                966                 :                           ",\n  CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n"
                                967                 :                           "       THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n"
                                968                 :                           "       ELSE 'No Access'\n"
                                969                 :                           "  END as \"%s\""
                                970                 :                           ",\n  t.spcname as \"%s\""
                                971                 :                           ",\n  pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"",
  479 tgl                       972 EUB             :                           gettext_noop("Size"),
                                973                 :                           gettext_noop("Tablespace"),
 5597                           974                 :                           gettext_noop("Description"));
 3429 heikki.linnakangas        975 UIC           0 :     appendPQExpBufferStr(&buf,
                                976                 :                          "\nFROM pg_catalog.pg_database d\n");
  479 tgl                       977               0 :     if (verbose)
 3429 heikki.linnakangas        978               0 :         appendPQExpBufferStr(&buf,
                                979                 :                              "  JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
                                980                 : 
 3689 peter_e                   981               0 :     if (pattern)
                                982                 :     {
  354 rhaas                     983               0 :         if (!validateSQLNamePattern(&buf, pattern, false, false,
  354 rhaas                     984 EUB             :                                     NULL, "d.datname", NULL, NULL,
                                985                 :                                     NULL, 1))
  262 michael                   986                 :         {
  262 michael                   987 UBC           0 :             termPQExpBuffer(&buf);
  354 rhaas                     988 UIC           0 :             return false;
                                989                 :         }
  262 michael                   990 EUB             :     }
                                991                 : 
 3429 heikki.linnakangas        992 UBC           0 :     appendPQExpBufferStr(&buf, "ORDER BY 1;");
 3090 fujii                     993 UIC           0 :     res = PSQLexec(buf.data);
 7655 peter_e                   994               0 :     termPQExpBuffer(&buf);
 8557 bruce                     995               0 :     if (!res)
 8557 bruce                     996 UBC           0 :         return false;
 8557 bruce                     997 EUB             : 
 8557 bruce                     998 UIC           0 :     myopt.nullPrint = NULL;
 7953 peter_e                   999               0 :     myopt.title = _("List of databases");
 5382 bruce                    1000               0 :     myopt.translate_header = true;
 8557 bruce                    1001 EUB             : 
 2685 tgl                      1002 UBC           0 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 8557 bruce                    1003 EUB             : 
 8557 bruce                    1004 UBC           0 :     PQclear(res);
                               1005               0 :     return true;
                               1006                 : }
 8557 bruce                    1007 EUB             : 
                               1008                 : 
 7953 peter_e                  1009                 : /*
                               1010                 :  * List Tables' Grant/Revoke Permissions
 8557 bruce                    1011                 :  * \z (now also \dp -- perhaps more mnemonic)
                               1012                 :  */
                               1013                 : bool
   92 dean.a.rasheed           1014 GNC          39 : permissionsList(const char *pattern, bool showSystem)
                               1015                 : {
                               1016                 :     PQExpBufferData buf;
                               1017                 :     PGresult   *res;
 8486 peter_e                  1018 GIC          39 :     printQueryOpt myopt = pset.popt;
                               1019                 :     static const bool translate_columns[] = {false, false, true, false, false, false};
                               1020                 : 
 7655                          1021              39 :     initPQExpBuffer(&buf);
                               1022                 : 
 7547 tgl                      1023 ECB             :     /*
                               1024                 :      * we ignore indexes and toast tables since they have no meaningful rights
                               1025                 :      */
 7655 peter_e                  1026 GIC          39 :     printfPQExpBuffer(&buf,
 7522 bruce                    1027 ECB             :                       "SELECT n.nspname as \"%s\",\n"
                               1028                 :                       "  c.relname as \"%s\",\n"
                               1029                 :                       "  CASE c.relkind"
 2222 tgl                      1030                 :                       " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'"
                               1031                 :                       " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'"
                               1032                 :                       " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'"
                               1033                 :                       " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'"
                               1034                 :                       " WHEN " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN '%s'"
 2118                          1035                 :                       " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
                               1036                 :                       " END as \"%s\",\n"
                               1037                 :                       "  ",
                               1038                 :                       gettext_noop("Schema"),
                               1039                 :                       gettext_noop("Name"),
                               1040                 :                       gettext_noop("table"),
                               1041                 :                       gettext_noop("view"),
                               1042                 :                       gettext_noop("materialized view"),
                               1043                 :                       gettext_noop("sequence"),
                               1044                 :                       gettext_noop("foreign table"),
                               1045                 :                       gettext_noop("partitioned table"),
                               1046                 :                       gettext_noop("Type"));
                               1047                 : 
 5212 tgl                      1048 GIC          39 :     printACLColumn(&buf, "c.relacl");
                               1049                 : 
  479                          1050              39 :     appendPQExpBuffer(&buf,
                               1051                 :                       ",\n  pg_catalog.array_to_string(ARRAY(\n"
                               1052                 :                       "    SELECT attname || E':\\n  ' || pg_catalog.array_to_string(attacl, E'\\n  ')\n"
                               1053                 :                       "    FROM pg_catalog.pg_attribute a\n"
                               1054                 :                       "    WHERE attrelid = c.oid AND NOT attisdropped AND attacl IS NOT NULL\n"
                               1055                 :                       "  ), E'\\n') AS \"%s\"",
                               1056                 :                       gettext_noop("Column privileges"));
 3124 sfrost                   1057 ECB             : 
 2316 sfrost                   1058 GIC          39 :     if (pset.sversion >= 90500 && pset.sversion < 100000)
 2316 sfrost                   1059 LBC           0 :         appendPQExpBuffer(&buf,
                               1060                 :                           ",\n  pg_catalog.array_to_string(ARRAY(\n"
                               1061                 :                           "    SELECT polname\n"
                               1062                 :                           "    || CASE WHEN polcmd != '*' THEN\n"
                               1063                 :                           "           E' (' || polcmd::pg_catalog.text || E'):'\n"
                               1064                 :                           "       ELSE E':'\n"
                               1065                 :                           "       END\n"
                               1066                 :                           "    || CASE WHEN polqual IS NOT NULL THEN\n"
 2316 sfrost                   1067 ECB             :                           "           E'\\n  (u): ' || pg_catalog.pg_get_expr(polqual, polrelid)\n"
 2316 sfrost                   1068 EUB             :                           "       ELSE E''\n"
                               1069                 :                           "       END\n"
                               1070                 :                           "    || CASE WHEN polwithcheck IS NOT NULL THEN\n"
                               1071                 :                           "           E'\\n  (c): ' || pg_catalog.pg_get_expr(polwithcheck, polrelid)\n"
                               1072                 :                           "       ELSE E''\n"
                               1073                 :                           "       END"
                               1074                 :                           "    || CASE WHEN polroles <> '{0}' THEN\n"
                               1075                 :                           "           E'\\n  to: ' || pg_catalog.array_to_string(\n"
                               1076                 :                           "               ARRAY(\n"
                               1077                 :                           "                   SELECT rolname\n"
                               1078                 :                           "                   FROM pg_catalog.pg_roles\n"
                               1079                 :                           "                   WHERE oid = ANY (polroles)\n"
                               1080                 :                           "                   ORDER BY 1\n"
                               1081                 :                           "               ), E', ')\n"
                               1082                 :                           "       ELSE E''\n"
                               1083                 :                           "       END\n"
                               1084                 :                           "    FROM pg_catalog.pg_policy pol\n"
                               1085                 :                           "    WHERE polrelid = c.oid), E'\\n')\n"
                               1086                 :                           "    AS \"%s\"",
                               1087                 :                           gettext_noop("Policies"));
                               1088                 : 
 2316 sfrost                   1089 GIC          39 :     if (pset.sversion >= 100000)
 3124                          1090              39 :         appendPQExpBuffer(&buf,
                               1091                 :                           ",\n  pg_catalog.array_to_string(ARRAY(\n"
                               1092                 :                           "    SELECT polname\n"
                               1093                 :                           "    || CASE WHEN NOT polpermissive THEN\n"
                               1094                 :                           "       E' (RESTRICTIVE)'\n"
                               1095                 :                           "       ELSE '' END\n"
                               1096                 :                           "    || CASE WHEN polcmd != '*' THEN\n"
                               1097                 :                           "           E' (' || polcmd::pg_catalog.text || E'):'\n"
 2187 peter_e                  1098 ECB             :                           "       ELSE E':'\n"
 3124 sfrost                   1099                 :                           "       END\n"
                               1100                 :                           "    || CASE WHEN polqual IS NOT NULL THEN\n"
                               1101                 :                           "           E'\\n  (u): ' || pg_catalog.pg_get_expr(polqual, polrelid)\n"
                               1102                 :                           "       ELSE E''\n"
                               1103                 :                           "       END\n"
                               1104                 :                           "    || CASE WHEN polwithcheck IS NOT NULL THEN\n"
                               1105                 :                           "           E'\\n  (c): ' || pg_catalog.pg_get_expr(polwithcheck, polrelid)\n"
                               1106                 :                           "       ELSE E''\n"
                               1107                 :                           "       END"
                               1108                 :                           "    || CASE WHEN polroles <> '{0}' THEN\n"
                               1109                 :                           "           E'\\n  to: ' || pg_catalog.array_to_string(\n"
                               1110                 :                           "               ARRAY(\n"
                               1111                 :                           "                   SELECT rolname\n"
                               1112                 :                           "                   FROM pg_catalog.pg_roles\n"
                               1113                 :                           "                   WHERE oid = ANY (polroles)\n"
                               1114                 :                           "                   ORDER BY 1\n"
                               1115                 :                           "               ), E', ')\n"
                               1116                 :                           "       ELSE E''\n"
                               1117                 :                           "       END\n"
                               1118                 :                           "    FROM pg_catalog.pg_policy pol\n"
                               1119                 :                           "    WHERE polrelid = c.oid), E'\\n')\n"
                               1120                 :                           "    AS \"%s\"",
                               1121                 :                           gettext_noop("Policies"));
                               1122                 : 
 3429 heikki.linnakangas       1123 GIC          39 :     appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_class c\n"
                               1124                 :                          "     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
                               1125                 :                          "WHERE c.relkind IN ("
                               1126                 :                          CppAsString2(RELKIND_RELATION) ","
                               1127                 :                          CppAsString2(RELKIND_VIEW) ","
                               1128                 :                          CppAsString2(RELKIND_MATVIEW) ","
                               1129                 :                          CppAsString2(RELKIND_SEQUENCE) ","
                               1130                 :                          CppAsString2(RELKIND_FOREIGN_TABLE) ","
                               1131                 :                          CppAsString2(RELKIND_PARTITIONED_TABLE) ")\n");
 5393 tgl                      1132 ECB             : 
   92 dean.a.rasheed           1133 GNC          39 :     if (!showSystem && !pattern)
                               1134               3 :         appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
                               1135                 :                              "      AND n.nspname <> 'information_schema'\n");
                               1136                 : 
  354 rhaas                    1137 GIC          39 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
                               1138                 :                                 "n.nspname", "c.relname", NULL,
                               1139                 :                                 "pg_catalog.pg_table_is_visible(c.oid)",
  354 rhaas                    1140 ECB             :                                 NULL, 3))
  262 michael                  1141 CBC          12 :         goto error_return;
                               1142                 : 
 3429 heikki.linnakangas       1143 GIC          27 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 8557 bruce                    1144 ECB             : 
 3090 fujii                    1145 GIC          27 :     res = PSQLexec(buf.data);
 8557 bruce                    1146              27 :     if (!res)
  262 michael                  1147 UIC           0 :         goto error_return;
 8557 bruce                    1148 ECB             : 
 8397 bruce                    1149 GIC          27 :     myopt.nullPrint = NULL;
 5393 peter_e                  1150 CBC          27 :     printfPQExpBuffer(&buf, _("Access privileges"));
 7655 peter_e                  1151 GIC          27 :     myopt.title = buf.data;
 5382 bruce                    1152 CBC          27 :     myopt.translate_header = true;
                               1153              27 :     myopt.translate_columns = translate_columns;
 3382 tgl                      1154 GBC          27 :     myopt.n_translate_columns = lengthof(translate_columns);
                               1155                 : 
 2685 tgl                      1156 CBC          27 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 8557 bruce                    1157 ECB             : 
 7655 peter_e                  1158 CBC          27 :     termPQExpBuffer(&buf);
 8557 bruce                    1159              27 :     PQclear(res);
                               1160              27 :     return true;
  262 michael                  1161 ECB             : 
  262 michael                  1162 GIC          12 : error_return:
  262 michael                  1163 CBC          12 :         termPQExpBuffer(&buf);
  262 michael                  1164 GIC          12 :         return false;
 8557 bruce                    1165 ECB             : }
                               1166                 : 
                               1167                 : 
                               1168                 : /*
 4934 tgl                      1169                 :  * \ddp
                               1170                 :  *
 3773                          1171                 :  * List Default ACLs.  The pattern can match either schema or role name.
                               1172                 :  */
                               1173                 : bool
 4934 tgl                      1174 GIC          18 : listDefaultACLs(const char *pattern)
                               1175                 : {
                               1176                 :     PQExpBufferData buf;
                               1177                 :     PGresult   *res;
                               1178              18 :     printQueryOpt myopt = pset.popt;
                               1179                 :     static const bool translate_columns[] = {false, false, true, false};
                               1180                 : 
 4934 tgl                      1181 CBC          18 :     initPQExpBuffer(&buf);
                               1182                 : 
 4934 tgl                      1183 GIC          18 :     printfPQExpBuffer(&buf,
                               1184                 :                       "SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS \"%s\",\n"
 4934 tgl                      1185 ECB             :                       "  n.nspname AS \"%s\",\n"
                               1186                 :                       "  CASE d.defaclobjtype WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' END AS \"%s\",\n"
                               1187                 :                       "  ",
                               1188                 :                       gettext_noop("Owner"),
                               1189                 :                       gettext_noop("Schema"),
 3773                          1190                 :                       DEFACLOBJ_RELATION,
                               1191                 :                       gettext_noop("table"),
                               1192                 :                       DEFACLOBJ_SEQUENCE,
                               1193                 :                       gettext_noop("sequence"),
                               1194                 :                       DEFACLOBJ_FUNCTION,
                               1195                 :                       gettext_noop("function"),
                               1196                 :                       DEFACLOBJ_TYPE,
                               1197                 :                       gettext_noop("type"),
                               1198                 :                       DEFACLOBJ_NAMESPACE,
                               1199                 :                       gettext_noop("schema"),
                               1200                 :                       gettext_noop("Type"));
                               1201                 : 
 4934 tgl                      1202 GIC          18 :     printACLColumn(&buf, "d.defaclacl");
                               1203                 : 
 3429 heikki.linnakangas       1204              18 :     appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_default_acl d\n"
                               1205                 :                          "     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.defaclnamespace\n");
                               1206                 : 
  354 rhaas                    1207              18 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                               1208                 :                                 NULL,
  354 rhaas                    1209 ECB             :                                 "n.nspname",
                               1210                 :                                 "pg_catalog.pg_get_userbyid(d.defaclrole)",
                               1211                 :                                 NULL,
                               1212                 :                                 NULL, 3))
  262 michael                  1213 GIC          12 :         goto error_return;
 4934 tgl                      1214 ECB             : 
 3429 heikki.linnakangas       1215 GIC           6 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
                               1216                 : 
 3090 fujii                    1217               6 :     res = PSQLexec(buf.data);
 4934 tgl                      1218               6 :     if (!res)
  262 michael                  1219 UIC           0 :         goto error_return;
 4934 tgl                      1220 ECB             : 
 4934 tgl                      1221 GIC           6 :     myopt.nullPrint = NULL;
 4934 tgl                      1222 CBC           6 :     printfPQExpBuffer(&buf, _("Default access privileges"));
 4934 tgl                      1223 GIC           6 :     myopt.title = buf.data;
 4934 tgl                      1224 CBC           6 :     myopt.translate_header = true;
                               1225               6 :     myopt.translate_columns = translate_columns;
 3382 tgl                      1226 GBC           6 :     myopt.n_translate_columns = lengthof(translate_columns);
                               1227                 : 
 2685 tgl                      1228 CBC           6 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 4934 tgl                      1229 ECB             : 
 4934 tgl                      1230 CBC           6 :     termPQExpBuffer(&buf);
                               1231               6 :     PQclear(res);
                               1232               6 :     return true;
  262 michael                  1233 ECB             : 
  262 michael                  1234 GIC          12 : error_return:
  262 michael                  1235 CBC          12 :     termPQExpBuffer(&buf);
  262 michael                  1236 GIC          12 :     return false;
 4934 tgl                      1237 ECB             : }
                               1238                 : 
 8557 bruce                    1239                 : 
                               1240                 : /*
                               1241                 :  * Get object comments
                               1242                 :  *
                               1243                 :  * \dd [foo]
                               1244                 :  *
                               1245                 :  * Note: This command only lists comments for object types which do not have
                               1246                 :  * their comments displayed by their own backslash commands. The following
                               1247                 :  * types of objects will be displayed: constraint, operator class,
                               1248                 :  * operator family, rule, and trigger.
                               1249                 :  *
                               1250                 :  */
                               1251                 : bool
 5206 bruce                    1252 GIC          21 : objectDescription(const char *pattern, bool showSystem)
                               1253                 : {
                               1254                 :     PQExpBufferData buf;
                               1255                 :     PGresult   *res;
 8486 peter_e                  1256              21 :     printQueryOpt myopt = pset.popt;
                               1257                 :     static const bool translate_columns[] = {false, false, true, false};
                               1258                 : 
 7655 peter_e                  1259 CBC          21 :     initPQExpBuffer(&buf);
                               1260                 : 
 7547 tgl                      1261 GIC          21 :     appendPQExpBuffer(&buf,
                               1262                 :                       "SELECT DISTINCT tt.nspname AS \"%s\", tt.name AS \"%s\", tt.object AS \"%s\", d.description AS \"%s\"\n"
 7522 bruce                    1263 ECB             :                       "FROM (\n",
                               1264                 :                       gettext_noop("Schema"),
                               1265                 :                       gettext_noop("Name"),
 5597 tgl                      1266                 :                       gettext_noop("Object"),
                               1267                 :                       gettext_noop("Description"));
 7953 peter_e                  1268                 : 
                               1269                 :     /* Table constraint descriptions */
 7547 tgl                      1270 GIC          21 :     appendPQExpBuffer(&buf,
                               1271                 :                       "  SELECT pgc.oid as oid, pgc.tableoid AS tableoid,\n"
                               1272                 :                       "  n.nspname as nspname,\n"
                               1273                 :                       "  CAST(pgc.conname AS pg_catalog.text) as name,"
                               1274                 :                       "  CAST('%s' AS pg_catalog.text) as object\n"
                               1275                 :                       "  FROM pg_catalog.pg_constraint pgc\n"
                               1276                 :                       "    JOIN pg_catalog.pg_class c "
 4259 rhaas                    1277 ECB             :                       "ON c.oid = pgc.conrelid\n"
                               1278                 :                       "    LEFT JOIN pg_catalog.pg_namespace n "
                               1279                 :                       "    ON n.oid = c.relnamespace\n",
                               1280                 :                       gettext_noop("table constraint"));
                               1281                 : 
 5050 bruce                    1282 GIC          21 :     if (!showSystem && !pattern)
 3429 heikki.linnakangas       1283 UIC           0 :         appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
                               1284                 :                              "      AND n.nspname <> 'information_schema'\n");
                               1285                 : 
  354 rhaas                    1286 GIC          21 :     if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern,
                               1287                 :                                 false, "n.nspname", "pgc.conname", NULL,
                               1288                 :                                 "pg_catalog.pg_table_is_visible(c.oid)",
  354 rhaas                    1289 ECB             :                                 NULL, 3))
  262 michael                  1290 GBC          12 :         goto error_return;
                               1291                 : 
                               1292                 :     /* Domain constraint descriptions */
 3029 alvherre                 1293 CBC           9 :     appendPQExpBuffer(&buf,
                               1294                 :                       "UNION ALL\n"
                               1295                 :                       "  SELECT pgc.oid as oid, pgc.tableoid AS tableoid,\n"
                               1296                 :                       "  n.nspname as nspname,\n"
 3029 alvherre                 1297 ECB             :                       "  CAST(pgc.conname AS pg_catalog.text) as name,"
                               1298                 :                       "  CAST('%s' AS pg_catalog.text) as object\n"
                               1299                 :                       "  FROM pg_catalog.pg_constraint pgc\n"
                               1300                 :                       "    JOIN pg_catalog.pg_type t "
                               1301                 :                       "ON t.oid = pgc.contypid\n"
                               1302                 :                       "    LEFT JOIN pg_catalog.pg_namespace n "
                               1303                 :                       "    ON n.oid = t.typnamespace\n",
                               1304                 :                       gettext_noop("domain constraint"));
                               1305                 : 
 3029 alvherre                 1306 GIC           9 :     if (!showSystem && !pattern)
 3029 alvherre                 1307 UIC           0 :         appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
                               1308                 :                              "      AND n.nspname <> 'information_schema'\n");
                               1309                 : 
  354 rhaas                    1310 GIC           9 :     if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern,
                               1311                 :                                 false, "n.nspname", "pgc.conname", NULL,
                               1312                 :                                 "pg_catalog.pg_type_is_visible(t.oid)",
  354 rhaas                    1313 ECB             :                                 NULL, 3))
  262 michael                  1314 UBC           0 :         goto error_return;
                               1315                 : 
                               1316                 :     /* Operator class descriptions */
  479 tgl                      1317 CBC           9 :     appendPQExpBuffer(&buf,
                               1318                 :                       "UNION ALL\n"
                               1319                 :                       "  SELECT o.oid as oid, o.tableoid as tableoid,\n"
                               1320                 :                       "  n.nspname as nspname,\n"
  479 tgl                      1321 EUB             :                       "  CAST(o.opcname AS pg_catalog.text) as name,\n"
                               1322                 :                       "  CAST('%s' AS pg_catalog.text) as object\n"
                               1323                 :                       "  FROM pg_catalog.pg_opclass o\n"
  479 tgl                      1324 ECB             :                       "    JOIN pg_catalog.pg_am am ON "
                               1325                 :                       "o.opcmethod = am.oid\n"
                               1326                 :                       "    JOIN pg_catalog.pg_namespace n ON "
                               1327                 :                       "n.oid = o.opcnamespace\n",
                               1328                 :                       gettext_noop("operator class"));
                               1329                 : 
  479 tgl                      1330 GIC           9 :     if (!showSystem && !pattern)
  479 tgl                      1331 UIC           0 :         appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
                               1332                 :                              "      AND n.nspname <> 'information_schema'\n");
                               1333                 : 
  354 rhaas                    1334 GIC           9 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
                               1335                 :                                 "n.nspname", "o.opcname", NULL,
                               1336                 :                                 "pg_catalog.pg_opclass_is_visible(o.oid)",
  354 rhaas                    1337 ECB             :                                 NULL, 3))
  262 michael                  1338 UBC           0 :         goto error_return;
                               1339                 : 
                               1340                 :     /* Operator family descriptions */
  479 tgl                      1341 CBC           9 :     appendPQExpBuffer(&buf,
                               1342                 :                       "UNION ALL\n"
                               1343                 :                       "  SELECT opf.oid as oid, opf.tableoid as tableoid,\n"
                               1344                 :                       "  n.nspname as nspname,\n"
  479 tgl                      1345 EUB             :                       "  CAST(opf.opfname AS pg_catalog.text) AS name,\n"
                               1346                 :                       "  CAST('%s' AS pg_catalog.text) as object\n"
                               1347                 :                       "  FROM pg_catalog.pg_opfamily opf\n"
  479 tgl                      1348 ECB             :                       "    JOIN pg_catalog.pg_am am "
                               1349                 :                       "ON opf.opfmethod = am.oid\n"
                               1350                 :                       "    JOIN pg_catalog.pg_namespace n "
                               1351                 :                       "ON opf.opfnamespace = n.oid\n",
                               1352                 :                       gettext_noop("operator family"));
                               1353                 : 
  479 tgl                      1354 GIC           9 :     if (!showSystem && !pattern)
  479 tgl                      1355 UIC           0 :         appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
                               1356                 :                              "      AND n.nspname <> 'information_schema'\n");
                               1357                 : 
  354 rhaas                    1358 GIC           9 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
                               1359                 :                                 "n.nspname", "opf.opfname", NULL,
                               1360                 :                                 "pg_catalog.pg_opfamily_is_visible(opf.oid)",
  354 rhaas                    1361 ECB             :                                 NULL, 3))
  262 michael                  1362 UBC           0 :         goto error_return;
                               1363                 : 
                               1364                 :     /* Rule descriptions (ignore rules for views) */
 7547 tgl                      1365 CBC           9 :     appendPQExpBuffer(&buf,
                               1366                 :                       "UNION ALL\n"
                               1367                 :                       "  SELECT r.oid as oid, r.tableoid as tableoid,\n"
                               1368                 :                       "  n.nspname as nspname,\n"
 7522 bruce                    1369 EUB             :                       "  CAST(r.rulename AS pg_catalog.text) as name,"
                               1370                 :                       "  CAST('%s' AS pg_catalog.text) as object\n"
                               1371                 :                       "  FROM pg_catalog.pg_rewrite r\n"
 2118 tgl                      1372 ECB             :                       "       JOIN pg_catalog.pg_class c ON c.oid = r.ev_class\n"
                               1373                 :                       "       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
                               1374                 :                       "  WHERE r.rulename != '_RETURN'\n",
                               1375                 :                       gettext_noop("rule"));
                               1376                 : 
 5050 bruce                    1377 GIC           9 :     if (!showSystem && !pattern)
 3429 heikki.linnakangas       1378 UIC           0 :         appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
                               1379                 :                              "      AND n.nspname <> 'information_schema'\n");
                               1380                 : 
  354 rhaas                    1381 GIC           9 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
                               1382                 :                                 "n.nspname", "r.rulename", NULL,
                               1383                 :                                 "pg_catalog.pg_table_is_visible(c.oid)",
  354 rhaas                    1384 ECB             :                                 NULL, 3))
  262 michael                  1385 UBC           0 :         goto error_return;
                               1386                 : 
                               1387                 :     /* Trigger descriptions */
 7547 tgl                      1388 CBC           9 :     appendPQExpBuffer(&buf,
                               1389                 :                       "UNION ALL\n"
                               1390                 :                       "  SELECT t.oid as oid, t.tableoid as tableoid,\n"
                               1391                 :                       "  n.nspname as nspname,\n"
 7522 bruce                    1392 EUB             :                       "  CAST(t.tgname AS pg_catalog.text) as name,"
                               1393                 :                       "  CAST('%s' AS pg_catalog.text) as object\n"
                               1394                 :                       "  FROM pg_catalog.pg_trigger t\n"
 2118 tgl                      1395 ECB             :                       "       JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid\n"
                               1396                 :                       "       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n",
                               1397                 :                       gettext_noop("trigger"));
                               1398                 : 
 5050 bruce                    1399 GIC           9 :     if (!showSystem && !pattern)
 3429 heikki.linnakangas       1400 UIC           0 :         appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
                               1401                 :                              "      AND n.nspname <> 'information_schema'\n");
                               1402                 : 
  354 rhaas                    1403 GIC           9 :     if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern, false,
                               1404                 :                                 "n.nspname", "t.tgname", NULL,
                               1405                 :                                 "pg_catalog.pg_table_is_visible(c.oid)",
  354 rhaas                    1406 ECB             :                                 NULL, 3))
  262 michael                  1407 UBC           0 :         goto error_return;
                               1408                 : 
 3429 heikki.linnakangas       1409 GIC           9 :     appendPQExpBufferStr(&buf,
 3429 heikki.linnakangas       1410 ECB             :                          ") AS tt\n"
                               1411                 :                          "  JOIN pg_catalog.pg_description d ON (tt.oid = d.objoid AND tt.tableoid = d.classoid AND d.objsubid = 0)\n");
                               1412                 : 
 3429 heikki.linnakangas       1413 GIC           9 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
 8557 bruce                    1414 EUB             : 
 3090 fujii                    1415 GIC           9 :     res = PSQLexec(buf.data);
 7655 peter_e                  1416 CBC           9 :     termPQExpBuffer(&buf);
 8557 bruce                    1417 GIC           9 :     if (!res)
 8557 bruce                    1418 UIC           0 :         return false;
                               1419                 : 
 8557 bruce                    1420 CBC           9 :     myopt.nullPrint = NULL;
 7953 peter_e                  1421 GIC           9 :     myopt.title = _("Object descriptions");
 5382 bruce                    1422 CBC           9 :     myopt.translate_header = true;
                               1423               9 :     myopt.translate_columns = translate_columns;
 3382 tgl                      1424               9 :     myopt.n_translate_columns = lengthof(translate_columns);
 8557 bruce                    1425 EUB             : 
 2685 tgl                      1426 GIC           9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 8557 bruce                    1427 ECB             : 
 8557 bruce                    1428 CBC           9 :     PQclear(res);
                               1429               9 :     return true;
  262 michael                  1430 ECB             : 
  262 michael                  1431 CBC          12 : error_return:
  262 michael                  1432 GIC          12 :     termPQExpBuffer(&buf);
  262 michael                  1433 CBC          12 :     return false;
                               1434                 : }
 8557 bruce                    1435 ECB             : 
                               1436                 : 
                               1437                 : /*
                               1438                 :  * describeTableDetails (for \d)
                               1439                 :  *
 7547 tgl                      1440                 :  * This routine finds the tables to be displayed, and calls
                               1441                 :  * describeOneTableDetails for each one.
                               1442                 :  *
                               1443                 :  * verbose: if true, this is \d+
                               1444                 :  */
                               1445                 : bool
 5192 bruce                    1446 GIC        1612 : describeTableDetails(const char *pattern, bool verbose, bool showSystem)
                               1447                 : {
                               1448                 :     PQExpBufferData buf;
                               1449                 :     PGresult   *res;
                               1450                 :     int         i;
                               1451                 : 
 7547 tgl                      1452            1612 :     initPQExpBuffer(&buf);
 7547 tgl                      1453 ECB             : 
 7547 tgl                      1454 GIC        1612 :     printfPQExpBuffer(&buf,
                               1455                 :                       "SELECT c.oid,\n"
                               1456                 :                       "  n.nspname,\n"
                               1457                 :                       "  c.relname\n"
                               1458                 :                       "FROM pg_catalog.pg_class c\n"
 2118 tgl                      1459 ECB             :                       "     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n");
                               1460                 : 
 5050 bruce                    1461 CBC        1612 :     if (!showSystem && !pattern)
 3429 heikki.linnakangas       1462 UIC           0 :         appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
                               1463                 :                              "      AND n.nspname <> 'information_schema'\n");
                               1464                 : 
  354 rhaas                    1465 GIC        1612 :     if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern, false,
                               1466                 :                                 "n.nspname", "c.relname", NULL,
                               1467                 :                                 "pg_catalog.pg_table_is_visible(c.oid)",
  354 rhaas                    1468 ECB             :                                 NULL, 3))
  262 michael                  1469 EUB             :     {
  262 michael                  1470 UIC           0 :         termPQExpBuffer(&buf);
  354 rhaas                    1471               0 :         return false;
  262 michael                  1472 ECB             :     }
                               1473                 : 
 3429 heikki.linnakangas       1474 GIC        1612 :     appendPQExpBufferStr(&buf, "ORDER BY 2, 3;");
                               1475                 : 
 3090 fujii                    1476            1612 :     res = PSQLexec(buf.data);
 7547 tgl                      1477 GBC        1612 :     termPQExpBuffer(&buf);
                               1478            1612 :     if (!res)
 7547 tgl                      1479 UIC           0 :         return false;
                               1480                 : 
 7547 tgl                      1481 CBC        1612 :     if (PQntuples(res) == 0)
                               1482                 :     {
 6067                          1483              19 :         if (!pset.quiet)
 2082 tgl                      1484 ECB             :         {
 2082 tgl                      1485 LBC           0 :             if (pattern)
 1469 peter                    1486 UBC           0 :                 pg_log_error("Did not find any relation named \"%s\".",
                               1487                 :                              pattern);
 2082 tgl                      1488 ECB             :             else
 1469 peter                    1489 UIC           0 :                 pg_log_error("Did not find any relations.");
 2082 tgl                      1490 ECB             :         }
 7547 tgl                      1491 GIC          19 :         PQclear(res);
 7547 tgl                      1492 GBC          19 :         return false;
 8557 bruce                    1493 EUB             :     }
                               1494                 : 
 7547 tgl                      1495 GIC        3213 :     for (i = 0; i < PQntuples(res); i++)
 7547 tgl                      1496 EUB             :     {
                               1497                 :         const char *oid;
 7547 tgl                      1498 ECB             :         const char *nspname;
                               1499                 :         const char *relname;
                               1500                 : 
 7547 tgl                      1501 GIC        1620 :         oid = PQgetvalue(res, i, 0);
 7547 tgl                      1502 CBC        1620 :         nspname = PQgetvalue(res, i, 1);
 7547 tgl                      1503 GIC        1620 :         relname = PQgetvalue(res, i, 2);
                               1504                 : 
                               1505            1620 :         if (!describeOneTableDetails(nspname, relname, oid, verbose))
                               1506                 :         {
 7547 tgl                      1507 UIC           0 :             PQclear(res);
 7547 tgl                      1508 LBC           0 :             return false;
 7547 tgl                      1509 ECB             :         }
 6143 tgl                      1510 CBC        1620 :         if (cancel_pressed)
                               1511                 :         {
 6143 tgl                      1512 LBC           0 :             PQclear(res);
 6143 tgl                      1513 UIC           0 :             return false;
 6143 tgl                      1514 EUB             :         }
 7547                          1515                 :     }
                               1516                 : 
 7547 tgl                      1517 CBC        1593 :     PQclear(res);
 7547 tgl                      1518 GIC        1593 :     return true;
 7547 tgl                      1519 EUB             : }
                               1520                 : 
                               1521                 : /*
                               1522                 :  * describeOneTableDetails (for \d)
                               1523                 :  *
 7547 tgl                      1524 ECB             :  * Unfortunately, the information presented here is so complicated that it
                               1525                 :  * cannot be done in a single query. So we have to assemble the printed table
                               1526                 :  * by hand and pass it to the underlying printTable() function.
                               1527                 :  */
                               1528                 : static bool
 7547 tgl                      1529 GIC        1620 : describeOneTableDetails(const char *schemaname,
                               1530                 :                         const char *relationname,
                               1531                 :                         const char *oid,
                               1532                 :                         bool verbose)
                               1533                 : {
 1725                          1534            1620 :     bool        retval = false;
                               1535                 :     PQExpBufferData buf;
 8535 bruce                    1536 CBC        1620 :     PGresult   *res = NULL;
 8486 peter_e                  1537 GIC        1620 :     printTableOpt myopt = pset.popt.topt;
                               1538                 :     printTableContent cont;
 5050 bruce                    1539            1620 :     bool        printTableInitialized = false;
                               1540                 :     int         i;
 7522 bruce                    1541 CBC        1620 :     char       *view_def = NULL;
                               1542                 :     char       *headers[12];
 7655 peter_e                  1543 ECB             :     PQExpBufferData title;
 7414 tgl                      1544                 :     PQExpBufferData tmpbuf;
                               1545                 :     int         cols;
 1725 tgl                      1546 CBC        1620 :     int         attname_col = -1,   /* column indexes in "res" */
 1725 tgl                      1547 GIC        1620 :                 atttype_col = -1,
 1725 tgl                      1548 CBC        1620 :                 attrdef_col = -1,
 1725 tgl                      1549 GIC        1620 :                 attnotnull_col = -1,
                               1550            1620 :                 attcoll_col = -1,
                               1551            1620 :                 attidentity_col = -1,
 1471 peter                    1552            1620 :                 attgenerated_col = -1,
 1725 tgl                      1553 CBC        1620 :                 isindexkey_col = -1,
                               1554            1620 :                 indexdef_col = -1,
                               1555            1620 :                 fdwopts_col = -1,
                               1556            1620 :                 attstorage_col = -1,
  682                          1557            1620 :                 attcompression_col = -1,
 1725                          1558            1620 :                 attstattarget_col = -1,
  682                          1559            1620 :                 attdescr_col = -1;
 1725 tgl                      1560 ECB             :     int         numrows;
 8397 bruce                    1561                 :     struct
                               1562                 :     {
                               1563                 :         int16       checks;
 6926 neilc                    1564                 :         char        relkind;
                               1565                 :         bool        hasindex;
 8397 bruce                    1566                 :         bool        hasrules;
                               1567                 :         bool        hastriggers;
                               1568                 :         bool        rowsecurity;
                               1569                 :         bool        forcerowsecurity;
                               1570                 :         bool        hasoids;
                               1571                 :         bool        ispartition;
                               1572                 :         Oid         tablespace;
                               1573                 :         char       *reloptions;
                               1574                 :         char       *reloftype;
                               1575                 :         char        relpersistence;
                               1576                 :         char        relreplident;
                               1577                 :         char       *relam;
                               1578                 :     }           tableinfo;
 2348 peter_e                  1579 GIC        1620 :     bool        show_column_details = false;
                               1580                 : 
 3995 rhaas                    1581            1620 :     myopt.default_footer = false;
                               1582                 :     /* This output looks confusing in expanded mode. */
 6373 bruce                    1583            1620 :     myopt.expanded = false;
                               1584                 : 
 7655 peter_e                  1585            1620 :     initPQExpBuffer(&buf);
 7655 peter_e                  1586 CBC        1620 :     initPQExpBuffer(&title);
 7414 tgl                      1587 GIC        1620 :     initPQExpBuffer(&tmpbuf);
 8557 bruce                    1588 ECB             : 
                               1589                 :     /* Get general table info */
 1601 andres                   1590 CBC        1620 :     if (pset.sversion >= 120000)
                               1591                 :     {
                               1592            1620 :         printfPQExpBuffer(&buf,
 1601 andres                   1593 ECB             :                           "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
                               1594                 :                           "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
                               1595                 :                           "false AS relhasoids, c.relispartition, %s, c.reltablespace, "
                               1596                 :                           "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
 1495                          1597                 :                           "c.relpersistence, c.relreplident, am.amname\n"
                               1598                 :                           "FROM pg_catalog.pg_class c\n "
 1601                          1599                 :                           "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
                               1600                 :                           "LEFT JOIN pg_catalog.pg_am am ON (c.relam = am.oid)\n"
                               1601                 :                           "WHERE c.oid = '%s';",
                               1602                 :                           (verbose ?
                               1603                 :                            "pg_catalog.array_to_string(c.reloptions || "
                               1604                 :                            "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
                               1605                 :                            : "''"),
                               1606                 :                           oid);
                               1607                 :     }
 1475 alvherre                 1608 UIC           0 :     else if (pset.sversion >= 100000)
                               1609                 :     {
                               1610               0 :         printfPQExpBuffer(&buf,
                               1611                 :                           "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
                               1612                 :                           "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
                               1613                 :                           "c.relhasoids, c.relispartition, %s, c.reltablespace, "
                               1614                 :                           "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
 1475 alvherre                 1615 EUB             :                           "c.relpersistence, c.relreplident\n"
                               1616                 :                           "FROM pg_catalog.pg_class c\n "
                               1617                 :                           "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
                               1618                 :                           "WHERE c.oid = '%s';",
                               1619                 :                           (verbose ?
                               1620                 :                            "pg_catalog.array_to_string(c.reloptions || "
                               1621                 :                            "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
                               1622                 :                            : "''"),
                               1623                 :                           oid);
                               1624                 :     }
 1601 andres                   1625 UIC           0 :     else if (pset.sversion >= 90500)
                               1626                 :     {
 3439 rhaas                    1627               0 :         printfPQExpBuffer(&buf,
                               1628                 :                           "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
                               1629                 :                           "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
                               1630                 :                           "c.relhasoids, false as relispartition, %s, c.reltablespace, "
                               1631                 :                           "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
 3124 sfrost                   1632 EUB             :                           "c.relpersistence, c.relreplident\n"
                               1633                 :                           "FROM pg_catalog.pg_class c\n "
 2118 tgl                      1634                 :                           "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
                               1635                 :                           "WHERE c.oid = '%s';",
                               1636                 :                           (verbose ?
                               1637                 :                            "pg_catalog.array_to_string(c.reloptions || "
                               1638                 :                            "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
                               1639                 :                            : "''"),
                               1640                 :                           oid);
                               1641                 :     }
 3124 sfrost                   1642 UIC           0 :     else if (pset.sversion >= 90400)
                               1643                 :     {
                               1644               0 :         printfPQExpBuffer(&buf,
                               1645                 :                           "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
                               1646                 :                           "c.relhastriggers, false, false, c.relhasoids, "
                               1647                 :                           "false as relispartition, %s, c.reltablespace, "
                               1648                 :                           "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
 3439 rhaas                    1649 EUB             :                           "c.relpersistence, c.relreplident\n"
                               1650                 :                           "FROM pg_catalog.pg_class c\n "
 2118 tgl                      1651                 :                           "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
                               1652                 :                           "WHERE c.oid = '%s';",
                               1653                 :                           (verbose ?
                               1654                 :                            "pg_catalog.array_to_string(c.reloptions || "
                               1655                 :                            "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
                               1656                 :                            : "''"),
                               1657                 :                           oid);
                               1658                 :     }
                               1659                 :     else
                               1660                 :     {
 4484 rhaas                    1661 UIC           0 :         printfPQExpBuffer(&buf,
                               1662                 :                           "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
                               1663                 :                           "c.relhastriggers, false, false, c.relhasoids, "
                               1664                 :                           "false as relispartition, %s, c.reltablespace, "
                               1665                 :                           "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
                               1666                 :                           "c.relpersistence\n"
                               1667                 :                           "FROM pg_catalog.pg_class c\n "
 2118 tgl                      1668 EUB             :                           "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
                               1669                 :                           "WHERE c.oid = '%s';",
                               1670                 :                           (verbose ?
                               1671                 :                            "pg_catalog.array_to_string(c.reloptions || "
                               1672                 :                            "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
                               1673                 :                            : "''"),
                               1674                 :                           oid);
                               1675                 :     }
                               1676                 : 
 3090 fujii                    1677 GIC        1620 :     res = PSQLexec(buf.data);
 8397 bruce                    1678            1620 :     if (!res)
 7655 peter_e                  1679 UIC           0 :         goto error_return;
                               1680                 : 
                               1681                 :     /* Did we get anything? */
 8557 bruce                    1682 GIC        1620 :     if (PQntuples(res) == 0)
                               1683                 :     {
 6067 tgl                      1684 LBC           0 :         if (!pset.quiet)
 1469 peter                    1685               0 :             pg_log_error("Did not find any relation with OID %s.", oid);
 7655 peter_e                  1686 UBC           0 :         goto error_return;
                               1687                 :     }
                               1688                 : 
 5264 tgl                      1689 CBC        1620 :     tableinfo.checks = atoi(PQgetvalue(res, 0, 0));
 6926 neilc                    1690 GIC        1620 :     tableinfo.relkind = *(PQgetvalue(res, 0, 1));
 5264 tgl                      1691 GBC        1620 :     tableinfo.hasindex = strcmp(PQgetvalue(res, 0, 2), "t") == 0;
                               1692            1620 :     tableinfo.hasrules = strcmp(PQgetvalue(res, 0, 3), "t") == 0;
                               1693            1620 :     tableinfo.hastriggers = strcmp(PQgetvalue(res, 0, 4), "t") == 0;
 3119 sfrost                   1694 GIC        1620 :     tableinfo.rowsecurity = strcmp(PQgetvalue(res, 0, 5), "t") == 0;
 2744                          1695            1620 :     tableinfo.forcerowsecurity = strcmp(PQgetvalue(res, 0, 6), "t") == 0;
 2744 sfrost                   1696 CBC        1620 :     tableinfo.hasoids = strcmp(PQgetvalue(res, 0, 7), "t") == 0;
 1475 alvherre                 1697            1620 :     tableinfo.ispartition = strcmp(PQgetvalue(res, 0, 8), "t") == 0;
  479 tgl                      1698            1620 :     tableinfo.reloptions = pg_strdup(PQgetvalue(res, 0, 9));
                               1699            1620 :     tableinfo.tablespace = atooid(PQgetvalue(res, 0, 10));
                               1700            1620 :     tableinfo.reloftype = (strcmp(PQgetvalue(res, 0, 11), "") != 0) ?
 1475 alvherre                 1701            1620 :         pg_strdup(PQgetvalue(res, 0, 11)) : NULL;
  479 tgl                      1702            1620 :     tableinfo.relpersistence = *(PQgetvalue(res, 0, 12));
 3439 rhaas                    1703            3240 :     tableinfo.relreplident = (pset.sversion >= 90400) ?
 1475 alvherre                 1704            1620 :         *(PQgetvalue(res, 0, 13)) : 'd';
 1495 andres                   1705            1620 :     if (pset.sversion >= 120000)
 1475 alvherre                 1706            3240 :         tableinfo.relam = PQgetisnull(res, 0, 14) ?
                               1707            1620 :             (char *) NULL : pg_strdup(PQgetvalue(res, 0, 14));
 1495 andres                   1708 ECB             :     else
 1495 andres                   1709 LBC           0 :         tableinfo.relam = NULL;
 8397 bruce                    1710 CBC        1620 :     PQclear(res);
 5270 tgl                      1711            1620 :     res = NULL;
 5050 bruce                    1712 ECB             : 
 5381                          1713                 :     /*
 2022 peter_e                  1714                 :      * If it's a sequence, deal with it here separately.
                               1715                 :      */
 2222 tgl                      1716 GBC        1620 :     if (tableinfo.relkind == RELKIND_SEQUENCE)
 5381 bruce                    1717 ECB             :     {
 2022 peter_e                  1718 CBC          81 :         PGresult   *result = NULL;
  367 tomas.vondra             1719 GIC          81 :         printQueryOpt myopt = pset.popt;
                               1720              81 :         char       *footers[2] = {NULL, NULL};
                               1721                 : 
 2022 peter_e                  1722              81 :         if (pset.sversion >= 100000)
 2022 peter_e                  1723 ECB             :         {
 2022 peter_e                  1724 GIC          81 :             printfPQExpBuffer(&buf,
  367 tomas.vondra             1725 ECB             :                               "SELECT pg_catalog.format_type(seqtypid, NULL) AS \"%s\",\n"
                               1726                 :                               "       seqstart AS \"%s\",\n"
                               1727                 :                               "       seqmin AS \"%s\",\n"
                               1728                 :                               "       seqmax AS \"%s\",\n"
                               1729                 :                               "       seqincrement AS \"%s\",\n"
                               1730                 :                               "       CASE WHEN seqcycle THEN '%s' ELSE '%s' END AS \"%s\",\n"
                               1731                 :                               "       seqcache AS \"%s\"\n",
                               1732                 :                               gettext_noop("Type"),
                               1733                 :                               gettext_noop("Start"),
                               1734                 :                               gettext_noop("Minimum"),
                               1735                 :                               gettext_noop("Maximum"),
                               1736                 :                               gettext_noop("Increment"),
                               1737                 :                               gettext_noop("yes"),
                               1738                 :                               gettext_noop("no"),
                               1739                 :                               gettext_noop("Cycles?"),
                               1740                 :                               gettext_noop("Cache"));
 2022 peter_e                  1741 GIC          81 :             appendPQExpBuffer(&buf,
                               1742                 :                               "FROM pg_catalog.pg_sequence\n"
                               1743                 :                               "WHERE seqrelid = '%s';",
                               1744                 :                               oid);
                               1745                 :         }
                               1746                 :         else
                               1747                 :         {
 2022 peter_e                  1748 LBC           0 :             printfPQExpBuffer(&buf,
                               1749                 :                               "SELECT 'bigint' AS \"%s\",\n"
                               1750                 :                               "       start_value AS \"%s\",\n"
                               1751                 :                               "       min_value AS \"%s\",\n"
                               1752                 :                               "       max_value AS \"%s\",\n"
                               1753                 :                               "       increment_by AS \"%s\",\n"
                               1754                 :                               "       CASE WHEN is_cycled THEN '%s' ELSE '%s' END AS \"%s\",\n"
  367 tomas.vondra             1755 EUB             :                               "       cache_value AS \"%s\"\n",
                               1756                 :                               gettext_noop("Type"),
                               1757                 :                               gettext_noop("Start"),
                               1758                 :                               gettext_noop("Minimum"),
                               1759                 :                               gettext_noop("Maximum"),
                               1760                 :                               gettext_noop("Increment"),
                               1761                 :                               gettext_noop("yes"),
                               1762                 :                               gettext_noop("no"),
                               1763                 :                               gettext_noop("Cycles?"),
                               1764                 :                               gettext_noop("Cache"));
 2022 peter_e                  1765 UIC           0 :             appendPQExpBuffer(&buf, "FROM %s", fmtId(schemaname));
                               1766                 :             /* must be separate because fmtId isn't reentrant */
                               1767               0 :             appendPQExpBuffer(&buf, ".%s;", fmtId(relationname));
                               1768                 :         }
                               1769                 : 
 3090 fujii                    1770 GIC          81 :         res = PSQLexec(buf.data);
 5011 tgl                      1771              81 :         if (!res)
 5381 bruce                    1772 UBC           0 :             goto error_return;
                               1773                 : 
 2022 peter_e                  1774 EUB             :         /* Get the column that owns this sequence */
 2022 peter_e                  1775 GIC          81 :         printfPQExpBuffer(&buf, "SELECT pg_catalog.quote_ident(nspname) || '.' ||"
                               1776                 :                           "\n   pg_catalog.quote_ident(relname) || '.' ||"
 2022 peter_e                  1777 ECB             :                           "\n   pg_catalog.quote_ident(attname),"
                               1778                 :                           "\n   d.deptype"
 2022 peter_e                  1779 EUB             :                           "\nFROM pg_catalog.pg_class c"
                               1780                 :                           "\nINNER JOIN pg_catalog.pg_depend d ON c.oid=d.refobjid"
                               1781                 :                           "\nINNER JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace"
 2022 peter_e                  1782 ECB             :                           "\nINNER JOIN pg_catalog.pg_attribute a ON ("
                               1783                 :                           "\n a.attrelid=c.oid AND"
                               1784                 :                           "\n a.attnum=d.refobjsubid)"
                               1785                 :                           "\nWHERE d.classid='pg_catalog.pg_class'::pg_catalog.regclass"
                               1786                 :                           "\n AND d.refclassid='pg_catalog.pg_class'::pg_catalog.regclass"
                               1787                 :                           "\n AND d.objid='%s'"
                               1788                 :                           "\n AND d.deptype IN ('a', 'i')",
                               1789                 :                           oid);
                               1790                 : 
 2022 peter_e                  1791 GIC          81 :         result = PSQLexec(buf.data);
                               1792                 : 
                               1793                 :         /*
                               1794                 :          * If we get no rows back, don't show anything (obviously). We should
                               1795                 :          * never get more than one row back, but if we do, just ignore it and
                               1796                 :          * don't print anything.
                               1797                 :          */
 2022 peter_e                  1798 CBC          81 :         if (!result)
 2022 peter_e                  1799 UIC           0 :             goto error_return;
 2022 peter_e                  1800 GIC          81 :         else if (PQntuples(result) == 1)
                               1801                 :         {
                               1802              72 :             switch (PQgetvalue(result, 0, 1)[0])
                               1803                 :             {
                               1804              60 :                 case 'a':
  367 tomas.vondra             1805 CBC          60 :                     footers[0] = psprintf(_("Owned by: %s"),
  367 tomas.vondra             1806 EUB             :                                           PQgetvalue(result, 0, 0));
 2022 peter_e                  1807 CBC          60 :                     break;
 2022 peter_e                  1808 GIC          12 :                 case 'i':
  367 tomas.vondra             1809 CBC          12 :                     footers[0] = psprintf(_("Sequence for identity column: %s"),
                               1810                 :                                           PQgetvalue(result, 0, 0));
 2022 peter_e                  1811              12 :                     break;
 2022 peter_e                  1812 ECB             :             }
                               1813                 :         }
 2022 peter_e                  1814 CBC          81 :         PQclear(result);
 2022 peter_e                  1815 ECB             : 
  367 tomas.vondra             1816 CBC          81 :         if (tableinfo.relpersistence == 'u')
  367 tomas.vondra             1817 GIC           3 :             printfPQExpBuffer(&title, _("Unlogged sequence \"%s.%s\""),
  367 tomas.vondra             1818 ECB             :                               schemaname, relationname);
                               1819                 :         else
  367 tomas.vondra             1820 GIC          78 :             printfPQExpBuffer(&title, _("Sequence \"%s.%s\""),
  367 tomas.vondra             1821 ECB             :                               schemaname, relationname);
                               1822                 : 
  367 tomas.vondra             1823 CBC          81 :         myopt.footers = footers;
                               1824              81 :         myopt.topt.default_footer = false;
  367 tomas.vondra             1825 GIC          81 :         myopt.title = title.data;
                               1826              81 :         myopt.translate_header = true;
  381 tomas.vondra             1827 ECB             : 
  367 tomas.vondra             1828 GIC          81 :         printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               1829                 : 
  297 peter                    1830 GNC          81 :         free(footers[0]);
 2022 peter_e                  1831 ECB             : 
 2022 peter_e                  1832 CBC          81 :         retval = true;
 2022 peter_e                  1833 GIC          81 :         goto error_return;      /* not an error, just return early */
 5381 bruce                    1834 ECB             :     }
                               1835                 : 
 1725 tgl                      1836                 :     /* Identify whether we should print collation, nullable, default vals */
 1725 tgl                      1837 GIC        1539 :     if (tableinfo.relkind == RELKIND_RELATION ||
 1725 tgl                      1838 CBC         653 :         tableinfo.relkind == RELKIND_VIEW ||
                               1839             479 :         tableinfo.relkind == RELKIND_MATVIEW ||
 1725 tgl                      1840 GIC         449 :         tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
                               1841             356 :         tableinfo.relkind == RELKIND_COMPOSITE_TYPE ||
                               1842             314 :         tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
 1725 tgl                      1843 CBC        1342 :         show_column_details = true;
 1725 tgl                      1844 ECB             : 
 4265 rhaas                    1845                 :     /*
 1725 tgl                      1846                 :      * Get per-column info
 4265 rhaas                    1847                 :      *
 1725 tgl                      1848                 :      * Since the set of query columns we need varies depending on relkind and
                               1849                 :      * server version, we compute all the column numbers on-the-fly.  Column
                               1850                 :      * number variables for columns not fetched are left as -1; this avoids
                               1851                 :      * duplicative test logic below.
                               1852                 :      */
 1725 tgl                      1853 GIC        1539 :     cols = 0;
                               1854            1539 :     printfPQExpBuffer(&buf, "SELECT a.attname");
                               1855            1539 :     attname_col = cols++;
                               1856            1539 :     appendPQExpBufferStr(&buf, ",\n  pg_catalog.format_type(a.atttypid, a.atttypmod)");
                               1857            1539 :     atttype_col = cols++;
                               1858                 : 
 1725 tgl                      1859 CBC        1539 :     if (show_column_details)
 1725 tgl                      1860 ECB             :     {
 1471 peter                    1861                 :         /* use "pretty" mode for expression to avoid excessive parentheses */
 1725 tgl                      1862 CBC        1342 :         appendPQExpBufferStr(&buf,
  865 tgl                      1863 ECB             :                              ",\n  (SELECT pg_catalog.pg_get_expr(d.adbin, d.adrelid, true)"
                               1864                 :                              "\n   FROM pg_catalog.pg_attrdef d"
 1725                          1865                 :                              "\n   WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef)"
                               1866                 :                              ",\n  a.attnotnull");
 1725 tgl                      1867 GIC        1342 :         attrdef_col = cols++;
 1725 tgl                      1868 CBC        1342 :         attnotnull_col = cols++;
  479 tgl                      1869 GIC        1342 :         appendPQExpBufferStr(&buf, ",\n  (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type t\n"
                               1870                 :                              "   WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation) AS attcollation");
 1725                          1871            1342 :         attcoll_col = cols++;
                               1872            1342 :         if (pset.sversion >= 100000)
 1725 tgl                      1873 CBC        1342 :             appendPQExpBufferStr(&buf, ",\n  a.attidentity");
 1725 tgl                      1874 ECB             :         else
 1725 tgl                      1875 LBC           0 :             appendPQExpBufferStr(&buf, ",\n  ''::pg_catalog.char AS attidentity");
 1725 tgl                      1876 GIC        1342 :         attidentity_col = cols++;
 1471 peter                    1877 CBC        1342 :         if (pset.sversion >= 120000)
                               1878            1342 :             appendPQExpBufferStr(&buf, ",\n  a.attgenerated");
 1471 peter                    1879 ECB             :         else
 1471 peter                    1880 UIC           0 :             appendPQExpBufferStr(&buf, ",\n  ''::pg_catalog.char AS attgenerated");
 1471 peter                    1881 GBC        1342 :         attgenerated_col = cols++;
 1725 tgl                      1882 ECB             :     }
 1906 alvherre                 1883 CBC        1539 :     if (tableinfo.relkind == RELKIND_INDEX ||
                               1884            1411 :         tableinfo.relkind == RELKIND_PARTITIONED_INDEX)
                               1885                 :     {
 1725 tgl                      1886 GBC         194 :         if (pset.sversion >= 110000)
 1725 tgl                      1887 ECB             :         {
 1725 tgl                      1888 GIC         194 :             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",
 1725 tgl                      1889 ECB             :                               oid,
                               1890                 :                               gettext_noop("yes"),
                               1891                 :                               gettext_noop("no"));
 1725 tgl                      1892 CBC         194 :             isindexkey_col = cols++;
                               1893                 :         }
 3429 heikki.linnakangas       1894             194 :         appendPQExpBufferStr(&buf, ",\n  pg_catalog.pg_get_indexdef(a.attrelid, a.attnum, TRUE) AS indexdef");
 1725 tgl                      1895 GIC         194 :         indexdef_col = cols++;
                               1896                 :     }
                               1897                 :     /* FDW options for foreign table column */
  479 tgl                      1898 CBC        1539 :     if (tableinfo.relkind == RELKIND_FOREIGN_TABLE)
                               1899                 :     {
 3429 heikki.linnakangas       1900              93 :         appendPQExpBufferStr(&buf, ",\n  CASE WHEN attfdwoptions IS NULL THEN '' ELSE "
 2083 tgl                      1901 ECB             :                              "  '(' || pg_catalog.array_to_string(ARRAY(SELECT pg_catalog.quote_ident(option_name) || ' ' || pg_catalog.quote_literal(option_value)  FROM "
                               1902                 :                              "  pg_catalog.pg_options_to_table(attfdwoptions)), ', ') || ')' END AS attfdwoptions");
 1725 tgl                      1903 GIC          93 :         fdwopts_col = cols++;
 1725 tgl                      1904 ECB             :     }
 7547 tgl                      1905 GIC        1539 :     if (verbose)
 4275 rhaas                    1906 ECB             :     {
 3429 heikki.linnakangas       1907 GIC         614 :         appendPQExpBufferStr(&buf, ",\n  a.attstorage");
 1725 tgl                      1908             614 :         attstorage_col = cols++;
 1725 tgl                      1909 ECB             : 
                               1910                 :         /* compression info, if relevant to relkind */
  751 rhaas                    1911 CBC         614 :         if (pset.sversion >= 140000 &&
  751 rhaas                    1912 GIC         614 :             !pset.hide_compression &&
  751 rhaas                    1913 CBC          39 :             (tableinfo.relkind == RELKIND_RELATION ||
                               1914               6 :              tableinfo.relkind == RELKIND_PARTITIONED_TABLE ||
  751 rhaas                    1915 GIC           6 :              tableinfo.relkind == RELKIND_MATVIEW))
                               1916                 :         {
  751 rhaas                    1917 CBC          39 :             appendPQExpBufferStr(&buf, ",\n  a.attcompression AS attcompression");
                               1918              39 :             attcompression_col = cols++;
  751 rhaas                    1919 ECB             :         }
                               1920                 : 
 1725 tgl                      1921                 :         /* stats target, if relevant to relkind */
 1725 tgl                      1922 GIC         614 :         if (tableinfo.relkind == RELKIND_RELATION ||
 1725 tgl                      1923 CBC         340 :             tableinfo.relkind == RELKIND_INDEX ||
                               1924             323 :             tableinfo.relkind == RELKIND_PARTITIONED_INDEX ||
 1725 tgl                      1925 GIC         320 :             tableinfo.relkind == RELKIND_MATVIEW ||
                               1926             290 :             tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
                               1927             221 :             tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
 1725 tgl                      1928 ECB             :         {
 1725 tgl                      1929 CBC         447 :             appendPQExpBufferStr(&buf, ",\n  CASE WHEN a.attstattarget=-1 THEN NULL ELSE a.attstattarget END AS attstattarget");
                               1930             447 :             attstattarget_col = cols++;
 1725 tgl                      1931 ECB             :         }
 3955 bruce                    1932                 : 
 4275 rhaas                    1933                 :         /*
                               1934                 :          * In 9.0+, we have column comments for: relations, views, composite
 1914 peter_e                  1935                 :          * types, and foreign tables (cf. CommentObject() in comment.c).
 4275 rhaas                    1936                 :          */
 2222 tgl                      1937 GIC         614 :         if (tableinfo.relkind == RELKIND_RELATION ||
                               1938             340 :             tableinfo.relkind == RELKIND_VIEW ||
                               1939             173 :             tableinfo.relkind == RELKIND_MATVIEW ||
                               1940             143 :             tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
                               1941              74 :             tableinfo.relkind == RELKIND_COMPOSITE_TYPE ||
                               1942              74 :             tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
 1725 tgl                      1943 ECB             :         {
 1725 tgl                      1944 CBC         594 :             appendPQExpBufferStr(&buf, ",\n  pg_catalog.col_description(a.attrelid, a.attnum)");
                               1945             594 :             attdescr_col = cols++;
 1725 tgl                      1946 ECB             :         }
 4275 rhaas                    1947                 :     }
                               1948                 : 
 3429 heikki.linnakangas       1949 GIC        1539 :     appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_attribute a");
 7547 tgl                      1950 CBC        1539 :     appendPQExpBuffer(&buf, "\nWHERE a.attrelid = '%s' AND a.attnum > 0 AND NOT a.attisdropped", oid);
 3429 heikki.linnakangas       1951            1539 :     appendPQExpBufferStr(&buf, "\nORDER BY a.attnum;");
                               1952                 : 
 3090 fujii                    1953 GIC        1539 :     res = PSQLexec(buf.data);
 8535 bruce                    1954            1539 :     if (!res)
 7655 peter_e                  1955 LBC           0 :         goto error_return;
 7414 tgl                      1956 CBC        1539 :     numrows = PQntuples(res);
 8535 bruce                    1957 ECB             : 
                               1958                 :     /* Make title */
 5444 alvherre                 1959 CBC        1539 :     switch (tableinfo.relkind)
 5444 alvherre                 1960 ECB             :     {
 2222 tgl                      1961 GBC         886 :         case RELKIND_RELATION:
 4484 rhaas                    1962 CBC         886 :             if (tableinfo.relpersistence == 'u')
 4428 itagaki.takahiro         1963 UIC           0 :                 printfPQExpBuffer(&title, _("Unlogged table \"%s.%s\""),
                               1964                 :                                   schemaname, relationname);
 4484 rhaas                    1965 ECB             :             else
 4484 rhaas                    1966 GIC         886 :                 printfPQExpBuffer(&title, _("Table \"%s.%s\""),
 4484 rhaas                    1967 ECB             :                                   schemaname, relationname);
 5444 alvherre                 1968 CBC         886 :             break;
 2222 tgl                      1969 GBC         174 :         case RELKIND_VIEW:
 5444 alvherre                 1970 GIC         174 :             printfPQExpBuffer(&title, _("View \"%s.%s\""),
                               1971                 :                               schemaname, relationname);
 5444 alvherre                 1972 CBC         174 :             break;
 2222 tgl                      1973 GIC          30 :         case RELKIND_MATVIEW:
 3689 kgrittn                  1974 CBC          30 :             if (tableinfo.relpersistence == 'u')
 3689 kgrittn                  1975 LBC           0 :                 printfPQExpBuffer(&title, _("Unlogged materialized view \"%s.%s\""),
 3689 kgrittn                  1976 ECB             :                                   schemaname, relationname);
                               1977                 :             else
 3689 kgrittn                  1978 CBC          30 :                 printfPQExpBuffer(&title, _("Materialized view \"%s.%s\""),
 3689 kgrittn                  1979 ECB             :                                   schemaname, relationname);
 3689 kgrittn                  1980 CBC          30 :             break;
 2222 tgl                      1981 GBC         128 :         case RELKIND_INDEX:
 4484 rhaas                    1982 GIC         128 :             if (tableinfo.relpersistence == 'u')
 4428 itagaki.takahiro         1983 UIC           0 :                 printfPQExpBuffer(&title, _("Unlogged index \"%s.%s\""),
 4484 rhaas                    1984 ECB             :                                   schemaname, relationname);
                               1985                 :             else
 4484 rhaas                    1986 CBC         128 :                 printfPQExpBuffer(&title, _("Index \"%s.%s\""),
 4484 rhaas                    1987 ECB             :                                   schemaname, relationname);
 5444 alvherre                 1988 CBC         128 :             break;
 1602 alvherre                 1989 GBC          66 :         case RELKIND_PARTITIONED_INDEX:
 1602 alvherre                 1990 GIC          66 :             if (tableinfo.relpersistence == 'u')
 1602 alvherre                 1991 UIC           0 :                 printfPQExpBuffer(&title, _("Unlogged partitioned index \"%s.%s\""),
 1602 alvherre                 1992 ECB             :                                   schemaname, relationname);
                               1993                 :             else
 1602 alvherre                 1994 CBC          66 :                 printfPQExpBuffer(&title, _("Partitioned index \"%s.%s\""),
 1602 alvherre                 1995 ECB             :                                   schemaname, relationname);
 1602 alvherre                 1996 CBC          66 :             break;
 2222 tgl                      1997 GBC           3 :         case RELKIND_TOASTVALUE:
 5444 alvherre                 1998 GIC           3 :             printfPQExpBuffer(&title, _("TOAST table \"%s.%s\""),
                               1999                 :                               schemaname, relationname);
 5444 alvherre                 2000 CBC           3 :             break;
 2222 tgl                      2001 GIC          42 :         case RELKIND_COMPOSITE_TYPE:
 5444 alvherre                 2002 CBC          42 :             printfPQExpBuffer(&title, _("Composite type \"%s.%s\""),
 5444 alvherre                 2003 ECB             :                               schemaname, relationname);
 5444 alvherre                 2004 CBC          42 :             break;
 2222 tgl                      2005 GIC          93 :         case RELKIND_FOREIGN_TABLE:
 4481 rhaas                    2006 CBC          93 :             printfPQExpBuffer(&title, _("Foreign table \"%s.%s\""),
 4481 rhaas                    2007 ECB             :                               schemaname, relationname);
 4481 rhaas                    2008 CBC          93 :             break;
 2222 tgl                      2009 GIC         117 :         case RELKIND_PARTITIONED_TABLE:
 2314 rhaas                    2010 CBC         117 :             if (tableinfo.relpersistence == 'u')
 1602 alvherre                 2011 LBC           0 :                 printfPQExpBuffer(&title, _("Unlogged partitioned table \"%s.%s\""),
 2314 rhaas                    2012 ECB             :                                   schemaname, relationname);
                               2013                 :             else
 1602 alvherre                 2014 CBC         117 :                 printfPQExpBuffer(&title, _("Partitioned table \"%s.%s\""),
 2314 rhaas                    2015 ECB             :                                   schemaname, relationname);
 2314 rhaas                    2016 CBC         117 :             break;
 5444 alvherre                 2017 UBC           0 :         default:
                               2018                 :             /* untranslated unknown relkind */
 5444 alvherre                 2019 UIC           0 :             printfPQExpBuffer(&title, "?%c? \"%s.%s\"",
 5444 alvherre                 2020 LBC           0 :                               tableinfo.relkind, schemaname, relationname);
 5444 alvherre                 2021 UIC           0 :             break;
 5444 alvherre                 2022 ECB             :     }
 5444 alvherre                 2023 EUB             : 
                               2024                 :     /* Fill headers[] with the names of the columns we will output */
 1725 tgl                      2025 GBC        1539 :     cols = 0;
                               2026            1539 :     headers[cols++] = gettext_noop("Column");
                               2027            1539 :     headers[cols++] = gettext_noop("Type");
 1725 tgl                      2028 GIC        1539 :     if (show_column_details)
                               2029                 :     {
 2348 peter_e                  2030            1342 :         headers[cols++] = gettext_noop("Collation");
 2348 peter_e                  2031 CBC        1342 :         headers[cols++] = gettext_noop("Nullable");
                               2032            1342 :         headers[cols++] = gettext_noop("Default");
 5445 alvherre                 2033 ECB             :     }
 1725 tgl                      2034 CBC        1539 :     if (isindexkey_col >= 0)
 1725 tgl                      2035 GIC         194 :         headers[cols++] = gettext_noop("Key?");
 1725 tgl                      2036 CBC        1539 :     if (indexdef_col >= 0)
 5025 peter_e                  2037             194 :         headers[cols++] = gettext_noop("Definition");
 1725 tgl                      2038            1539 :     if (fdwopts_col >= 0)
 2126 peter_e                  2039 GIC          93 :         headers[cols++] = gettext_noop("FDW options");
 1725 tgl                      2040 CBC        1539 :     if (attstorage_col >= 0)
 5382 bruce                    2041             614 :         headers[cols++] = gettext_noop("Storage");
  751 rhaas                    2042            1539 :     if (attcompression_col >= 0)
                               2043              39 :         headers[cols++] = gettext_noop("Compression");
 1725 tgl                      2044            1539 :     if (attstattarget_col >= 0)
                               2045             447 :         headers[cols++] = gettext_noop("Stats target");
                               2046            1539 :     if (attdescr_col >= 0)
                               2047             594 :         headers[cols++] = gettext_noop("Description");
 1725 tgl                      2048 ECB             : 
 1725 tgl                      2049 CBC        1539 :     Assert(cols <= lengthof(headers));
 5050 bruce                    2050 ECB             : 
 5445 alvherre                 2051 CBC        1539 :     printTableInit(&cont, &myopt, title.data, cols, numrows);
 5270 tgl                      2052            1539 :     printTableInitialized = true;
 5445 alvherre                 2053 ECB             : 
 5445 alvherre                 2054 GIC       10818 :     for (i = 0; i < cols; i++)
 5445 alvherre                 2055 CBC        9279 :         printTableAddHeader(&cont, headers[i], true, 'l');
                               2056                 : 
 8535 bruce                    2057 ECB             :     /* Generate table cells to be printed */
 7414 tgl                      2058 CBC        5107 :     for (i = 0; i < numrows; i++)
                               2059                 :     {
 5445 alvherre                 2060 ECB             :         /* Column */
 1725 tgl                      2061 CBC        3568 :         printTableAddCell(&cont, PQgetvalue(res, i, attname_col), false, false);
                               2062                 : 
                               2063                 :         /* Type */
                               2064            3568 :         printTableAddCell(&cont, PQgetvalue(res, i, atttype_col), false, false);
                               2065                 : 
                               2066                 :         /* Collation, Nullable, Default */
 2348 peter_e                  2067            3568 :         if (show_column_details)
                               2068                 :         {
                               2069                 :             char       *identity;
 1471 peter                    2070 ECB             :             char       *generated;
                               2071                 :             char       *default_str;
  865 tgl                      2072 GIC        3334 :             bool        mustfree = false;
 2194 peter_e                  2073 ECB             : 
 1725 tgl                      2074 GIC        3334 :             printTableAddCell(&cont, PQgetvalue(res, i, attcoll_col), false, false);
                               2075                 : 
                               2076            3334 :             printTableAddCell(&cont,
                               2077            3334 :                               strcmp(PQgetvalue(res, i, attnotnull_col), "t") == 0 ? "not null" : "",
 1725 tgl                      2078 ECB             :                               false, false);
                               2079                 : 
 1725 tgl                      2080 CBC        3334 :             identity = PQgetvalue(res, i, attidentity_col);
 1471 peter                    2081 GIC        3334 :             generated = PQgetvalue(res, i, attgenerated_col);
 2194 peter_e                  2082 ECB             : 
 1471 peter                    2083 CBC        3334 :             if (identity[0] == ATTRIBUTE_IDENTITY_ALWAYS)
 2194 peter_e                  2084 GIC          15 :                 default_str = "generated always as identity";
                               2085            3319 :             else if (identity[0] == ATTRIBUTE_IDENTITY_BY_DEFAULT)
 2194 peter_e                  2086 CBC           9 :                 default_str = "generated by default as identity";
 1471 peter                    2087            3310 :             else if (generated[0] == ATTRIBUTE_GENERATED_STORED)
                               2088                 :             {
  865 tgl                      2089              80 :                 default_str = psprintf("generated always as (%s) stored",
  865 tgl                      2090 ECB             :                                        PQgetvalue(res, i, attrdef_col));
  865 tgl                      2091 CBC          80 :                 mustfree = true;
  865 tgl                      2092 ECB             :             }
 1471 peter                    2093                 :             else
 1471 peter                    2094 GIC        3230 :                 default_str = PQgetvalue(res, i, attrdef_col);
 2194 peter_e                  2095 ECB             : 
  865 tgl                      2096 GIC        3334 :             printTableAddCell(&cont, default_str, false, mustfree);
 8397 bruce                    2097 ECB             :         }
                               2098                 : 
                               2099                 :         /* Info for index columns */
 1725 tgl                      2100 CBC        3568 :         if (isindexkey_col >= 0)
 1725 tgl                      2101 GIC         225 :             printTableAddCell(&cont, PQgetvalue(res, i, isindexkey_col), true, false);
 1725 tgl                      2102 CBC        3568 :         if (indexdef_col >= 0)
 1725 tgl                      2103 GIC         225 :             printTableAddCell(&cont, PQgetvalue(res, i, indexdef_col), false, false);
                               2104                 : 
                               2105                 :         /* FDW options for foreign table columns */
 1725 tgl                      2106 CBC        3568 :         if (fdwopts_col >= 0)
                               2107             342 :             printTableAddCell(&cont, PQgetvalue(res, i, fdwopts_col), false, false);
 4265 rhaas                    2108 ECB             : 
  682 tgl                      2109                 :         /* Storage mode, if relevant */
 1725 tgl                      2110 GIC        3568 :         if (attstorage_col >= 0)
                               2111                 :         {
 1725 tgl                      2112 CBC        1580 :             char       *storage = PQgetvalue(res, i, attstorage_col);
 5270 tgl                      2113 ECB             : 
                               2114                 :             /* these strings are literal in our syntax, so not translated. */
 5050 bruce                    2115 GIC        2139 :             printTableAddCell(&cont, (storage[0] == 'p' ? "plain" :
 5050 bruce                    2116 CBC        1049 :                                       (storage[0] == 'm' ? "main" :
 5050 bruce                    2117 GIC         511 :                                        (storage[0] == 'x' ? "extended" :
 5050 bruce                    2118 CBC          21 :                                         (storage[0] == 'e' ? "external" :
                               2119                 :                                          "???")))),
                               2120                 :                               false, false);
 1725 tgl                      2121 ECB             :         }
 4173 magnus                   2122                 : 
  682 tgl                      2123                 :         /* Column compression, if relevant */
  751 rhaas                    2124 CBC        3568 :         if (attcompression_col >= 0)
                               2125                 :         {
  751 rhaas                    2126 GIC          39 :             char       *compression = PQgetvalue(res, i, attcompression_col);
                               2127                 : 
                               2128                 :             /* these strings are literal in our syntax, so not translated. */
                               2129              69 :             printTableAddCell(&cont, (compression[0] == 'p' ? "pglz" :
  751 rhaas                    2130 CBC          48 :                                       (compression[0] == 'l' ? "lz4" :
  751 rhaas                    2131 GIC          18 :                                        (compression[0] == '\0' ? "" :
  751 rhaas                    2132 ECB             :                                         "???"))),
                               2133                 :                               false, false);
                               2134                 :         }
                               2135                 : 
 1725 tgl                      2136                 :         /* Statistics target, if the relkind supports this feature */
 1725 tgl                      2137 CBC        3568 :         if (attstattarget_col >= 0)
 1725 tgl                      2138 GIC        1141 :             printTableAddCell(&cont, PQgetvalue(res, i, attstattarget_col),
                               2139                 :                               false, false);
                               2140                 : 
                               2141                 :         /* Column comments, if the relkind supports this feature */
                               2142            3568 :         if (attdescr_col >= 0)
 1725 tgl                      2143 CBC        1544 :             printTableAddCell(&cont, PQgetvalue(res, i, attdescr_col),
 1725 tgl                      2144 ECB             :                               false, false);
                               2145                 :     }
                               2146                 : 
                               2147                 :     /* Make footers */
 1355                          2148                 : 
 1355 tgl                      2149 CBC        1539 :     if (tableinfo.ispartition)
                               2150                 :     {
                               2151                 :         /* Footer information for a partition child table */
                               2152                 :         PGresult   *result;
                               2153                 : 
 2083 tgl                      2154 GIC         204 :         printfPQExpBuffer(&buf,
 2083 tgl                      2155 ECB             :                           "SELECT inhparent::pg_catalog.regclass,\n"
                               2156                 :                           "  pg_catalog.pg_get_expr(c.relpartbound, c.oid),\n  ");
                               2157                 : 
  215 drowley                  2158 GNC         204 :         appendPQExpBufferStr(&buf,
                               2159             204 :                              pset.sversion >= 140000 ? "inhdetachpending" :
                               2160                 :                              "false as inhdetachpending");
                               2161                 : 
                               2162                 :         /* If verbose, also request the partition constraint definition */
 2157 rhaas                    2163 GIC         204 :         if (verbose)
 1375 drowley                  2164 CBC          78 :             appendPQExpBufferStr(&buf,
 1355 tgl                      2165 ECB             :                                  ",\n  pg_catalog.pg_get_partition_constraintdef(c.oid)");
 2083 tgl                      2166 GIC         204 :         appendPQExpBuffer(&buf,
                               2167                 :                           "\nFROM pg_catalog.pg_class c"
                               2168                 :                           " JOIN pg_catalog.pg_inherits i"
 2083 tgl                      2169 ECB             :                           " ON c.oid = inhrelid"
 1355                          2170                 :                           "\nWHERE c.oid = '%s';", oid);
 2314 rhaas                    2171 GIC         204 :         result = PSQLexec(buf.data);
 2314 rhaas                    2172 CBC         204 :         if (!result)
 2314 rhaas                    2173 UIC           0 :             goto error_return;
                               2174                 : 
 2314 rhaas                    2175 GIC         204 :         if (PQntuples(result) > 0)
                               2176                 :         {
 1355 tgl                      2177 CBC         204 :             char       *parent_name = PQgetvalue(result, 0, 0);
                               2178             204 :             char       *partdef = PQgetvalue(result, 0, 1);
  745 alvherre                 2179 GBC         204 :             char       *detached = PQgetvalue(result, 0, 2);
                               2180                 : 
  745 alvherre                 2181 CBC         204 :             printfPQExpBuffer(&tmpbuf, _("Partition of: %s %s%s"), parent_name,
                               2182                 :                               partdef,
                               2183             204 :                               strcmp(detached, "t") == 0 ? " DETACH PENDING" : "");
 2314 rhaas                    2184             204 :             printTableAddFooter(&cont, tmpbuf.data);
 2157 rhaas                    2185 ECB             : 
 2018 rhaas                    2186 GIC         204 :             if (verbose)
 2018 rhaas                    2187 ECB             :             {
 1355 tgl                      2188 GIC          78 :                 char       *partconstraintdef = NULL;
 1355 tgl                      2189 ECB             : 
  745 alvherre                 2190 CBC          78 :                 if (!PQgetisnull(result, 0, 3))
  745 alvherre                 2191 GIC          69 :                     partconstraintdef = PQgetvalue(result, 0, 3);
 2018 rhaas                    2192 ECB             :                 /* If there isn't any constraint, show that explicitly */
 2018 rhaas                    2193 GIC          78 :                 if (partconstraintdef == NULL || partconstraintdef[0] == '\0')
 2018 rhaas                    2194 CBC           9 :                     printfPQExpBuffer(&tmpbuf, _("No partition constraint"));
                               2195                 :                 else
                               2196              69 :                     printfPQExpBuffer(&tmpbuf, _("Partition constraint: %s"),
 2018 rhaas                    2197 ECB             :                                       partconstraintdef);
 2018 rhaas                    2198 GIC          78 :                 printTableAddFooter(&cont, tmpbuf.data);
 2018 rhaas                    2199 ECB             :             }
 2314                          2200                 :         }
 1355 tgl                      2201 GIC         204 :         PQclear(result);
 2314 rhaas                    2202 ECB             :     }
                               2203                 : 
 2222 tgl                      2204 CBC        1539 :     if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
                               2205                 :     {
                               2206                 :         /* Footer information for a partitioned table (partitioning parent) */
 2314 rhaas                    2207 ECB             :         PGresult   *result;
                               2208                 : 
 2314 rhaas                    2209 GIC         117 :         printfPQExpBuffer(&buf,
 2118 tgl                      2210 ECB             :                           "SELECT pg_catalog.pg_get_partkeydef('%s'::pg_catalog.oid);",
                               2211                 :                           oid);
 2314 rhaas                    2212 GIC         117 :         result = PSQLexec(buf.data);
 1355 tgl                      2213             117 :         if (!result)
 2314 rhaas                    2214 UIC           0 :             goto error_return;
 2314 rhaas                    2215 ECB             : 
 1355 tgl                      2216 GIC         117 :         if (PQntuples(result) == 1)
                               2217                 :         {
 1355 tgl                      2218 CBC         117 :             char       *partkeydef = PQgetvalue(result, 0, 0);
 1355 tgl                      2219 ECB             : 
 1355 tgl                      2220 GBC         117 :             printfPQExpBuffer(&tmpbuf, _("Partition key: %s"), partkeydef);
 1355 tgl                      2221 GIC         117 :             printTableAddFooter(&cont, tmpbuf.data);
 1355 tgl                      2222 ECB             :         }
 2314 rhaas                    2223 GIC         117 :         PQclear(result);
 2314 rhaas                    2224 ECB             :     }
                               2225                 : 
 1356 tgl                      2226 CBC        1539 :     if (tableinfo.relkind == RELKIND_TOASTVALUE)
 1356 tgl                      2227 ECB             :     {
                               2228                 :         /* For a TOAST table, print name of owning table */
                               2229                 :         PGresult   *result;
                               2230                 : 
 1356 tgl                      2231 GIC           3 :         printfPQExpBuffer(&buf,
 1356 tgl                      2232 ECB             :                           "SELECT n.nspname, c.relname\n"
                               2233                 :                           "FROM pg_catalog.pg_class c"
                               2234                 :                           " JOIN pg_catalog.pg_namespace n"
                               2235                 :                           " ON n.oid = c.relnamespace\n"
                               2236                 :                           "WHERE reltoastrelid = '%s';", oid);
 1356 tgl                      2237 CBC           3 :         result = PSQLexec(buf.data);
 1356 tgl                      2238 GIC           3 :         if (!result)
 1356 tgl                      2239 UIC           0 :             goto error_return;
                               2240                 : 
 1356 tgl                      2241 GIC           3 :         if (PQntuples(result) == 1)
                               2242                 :         {
 1356 tgl                      2243 CBC           3 :             char       *schemaname = PQgetvalue(result, 0, 0);
                               2244               3 :             char       *relname = PQgetvalue(result, 0, 1);
 1356 tgl                      2245 EUB             : 
 1356 tgl                      2246 GIC           3 :             printfPQExpBuffer(&tmpbuf, _("Owning table: \"%s.%s\""),
 1356 tgl                      2247 ECB             :                               schemaname, relname);
 1356 tgl                      2248 GIC           3 :             printTableAddFooter(&cont, tmpbuf.data);
 1356 tgl                      2249 ECB             :         }
 1356 tgl                      2250 CBC           3 :         PQclear(result);
                               2251                 :     }
 1356 tgl                      2252 ECB             : 
 1906 alvherre                 2253 GIC        1539 :     if (tableinfo.relkind == RELKIND_INDEX ||
 1906 alvherre                 2254 CBC        1411 :         tableinfo.relkind == RELKIND_PARTITIONED_INDEX)
 8397 bruce                    2255 GIC         194 :     {
 7917 tgl                      2256 ECB             :         /* Footer information about an index */
                               2257                 :         PGresult   *result;
                               2258                 : 
 7655 peter_e                  2259 CBC         194 :         printfPQExpBuffer(&buf,
  479 tgl                      2260 ECB             :                           "SELECT i.indisunique, i.indisprimary, i.indisclustered, "
                               2261                 :                           "i.indisvalid,\n"
                               2262                 :                           "  (NOT i.indimmediate) AND "
                               2263                 :                           "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
                               2264                 :                           "WHERE conrelid = i.indrelid AND "
                               2265                 :                           "conindid = i.indexrelid AND "
                               2266                 :                           "contype IN ('p','u','x') AND "
                               2267                 :                           "condeferrable) AS condeferrable,\n"
                               2268                 :                           "  (NOT i.indimmediate) AND "
                               2269                 :                           "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint "
                               2270                 :                           "WHERE conrelid = i.indrelid AND "
                               2271                 :                           "conindid = i.indexrelid AND "
                               2272                 :                           "contype IN ('p','u','x') AND "
                               2273                 :                           "condeferred) AS condeferred,\n");
                               2274                 : 
 3439 rhaas                    2275 GIC         194 :         if (pset.sversion >= 90400)
 1375 drowley                  2276             194 :             appendPQExpBufferStr(&buf, "i.indisreplident,\n");
                               2277                 :         else
 1375 drowley                  2278 UIC           0 :             appendPQExpBufferStr(&buf, "false AS indisreplident,\n");
                               2279                 : 
  430 peter                    2280 GIC         194 :         if (pset.sversion >= 150000)
  430 peter                    2281 CBC         194 :             appendPQExpBufferStr(&buf, "i.indnullsnotdistinct,\n");
  430 peter                    2282 ECB             :         else
  430 peter                    2283 UIC           0 :             appendPQExpBufferStr(&buf, "false AS indnullsnotdistinct,\n");
  430 peter                    2284 EUB             : 
 5002 tgl                      2285 GIC         194 :         appendPQExpBuffer(&buf, "  a.amname, c2.relname, "
 2118 tgl                      2286 ECB             :                           "pg_catalog.pg_get_expr(i.indpred, i.indrelid, true)\n"
 7547                          2287                 :                           "FROM pg_catalog.pg_index i, pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_am a\n"
                               2288                 :                           "WHERE i.indexrelid = c.oid AND c.oid = '%s' AND c.relam = a.oid\n"
 4295 rhaas                    2289 EUB             :                           "AND i.indrelid = c2.oid;",
                               2290                 :                           oid);
 7655 peter_e                  2291 ECB             : 
 3090 fujii                    2292 GIC         194 :         result = PSQLexec(buf.data);
 7655 peter_e                  2293             194 :         if (!result)
 7655 peter_e                  2294 UIC           0 :             goto error_return;
 7655 peter_e                  2295 GIC         194 :         else if (PQntuples(result) != 1)
                               2296                 :         {
 7655 peter_e                  2297 UIC           0 :             PQclear(result);
 7655 peter_e                  2298 LBC           0 :             goto error_return;
 7655 peter_e                  2299 ECB             :         }
 8397 bruce                    2300 EUB             :         else
 8397 bruce                    2301 ECB             :         {
 7836 bruce                    2302 GIC         194 :             char       *indisunique = PQgetvalue(result, 0, 0);
 7836 bruce                    2303 GBC         194 :             char       *indisprimary = PQgetvalue(result, 0, 1);
 6942                          2304             194 :             char       *indisclustered = PQgetvalue(result, 0, 2);
 6071 tgl                      2305 GIC         194 :             char       *indisvalid = PQgetvalue(result, 0, 3);
 5002                          2306             194 :             char       *deferrable = PQgetvalue(result, 0, 4);
                               2307             194 :             char       *deferred = PQgetvalue(result, 0, 5);
 3433 tgl                      2308 CBC         194 :             char       *indisreplident = PQgetvalue(result, 0, 6);
  430 peter                    2309             194 :             char       *indnullsnotdistinct = PQgetvalue(result, 0, 7);
                               2310             194 :             char       *indamname = PQgetvalue(result, 0, 8);
                               2311             194 :             char       *indtable = PQgetvalue(result, 0, 9);
                               2312             194 :             char       *indpred = PQgetvalue(result, 0, 10);
 7917 tgl                      2313 ECB             : 
 7655 peter_e                  2314 CBC         194 :             if (strcmp(indisprimary, "t") == 0)
 6753                          2315              42 :                 printfPQExpBuffer(&tmpbuf, _("primary key, "));
 7655                          2316             152 :             else if (strcmp(indisunique, "t") == 0)
  430 peter                    2317 ECB             :             {
  430 peter                    2318 CBC          51 :                 printfPQExpBuffer(&tmpbuf, _("unique"));
  430 peter                    2319 GIC          51 :                 if (strcmp(indnullsnotdistinct, "t") == 0)
  430 peter                    2320 CBC           3 :                     appendPQExpBufferStr(&tmpbuf, _(" nulls not distinct"));
  215 drowley                  2321 GNC          51 :                 appendPQExpBufferStr(&tmpbuf, _(", "));
  430 peter                    2322 ECB             :             }
                               2323                 :             else
 7655 peter_e                  2324 CBC         101 :                 resetPQExpBuffer(&tmpbuf);
                               2325             194 :             appendPQExpBuffer(&tmpbuf, "%s, ", indamname);
 7655 peter_e                  2326 ECB             : 
 7547 tgl                      2327                 :             /* we assume here that index and table are in same schema */
 7547 tgl                      2328 GIC         194 :             appendPQExpBuffer(&tmpbuf, _("for table \"%s.%s\""),
                               2329                 :                               schemaname, indtable);
 7547 tgl                      2330 ECB             : 
 7655 peter_e                  2331 CBC         194 :             if (strlen(indpred))
 7028 db                       2332 UIC           0 :                 appendPQExpBuffer(&tmpbuf, _(", predicate (%s)"), indpred);
                               2333                 : 
 6942 bruce                    2334 CBC         194 :             if (strcmp(indisclustered, "t") == 0)
 3429 heikki.linnakangas       2335 UIC           0 :                 appendPQExpBufferStr(&tmpbuf, _(", clustered"));
                               2336                 : 
 6071 tgl                      2337 CBC         194 :             if (strcmp(indisvalid, "t") != 0)
 3429 heikki.linnakangas       2338 UBC           0 :                 appendPQExpBufferStr(&tmpbuf, _(", invalid"));
                               2339                 : 
 5002 tgl                      2340 CBC         194 :             if (strcmp(deferrable, "t") == 0)
 3429 heikki.linnakangas       2341 UBC           0 :                 appendPQExpBufferStr(&tmpbuf, _(", deferrable"));
                               2342                 : 
 5002 tgl                      2343 CBC         194 :             if (strcmp(deferred, "t") == 0)
 3429 heikki.linnakangas       2344 UBC           0 :                 appendPQExpBufferStr(&tmpbuf, _(", initially deferred"));
                               2345                 : 
 3433 tgl                      2346 CBC         194 :             if (strcmp(indisreplident, "t") == 0)
 1375 drowley                  2347 UBC           0 :                 appendPQExpBufferStr(&tmpbuf, _(", replica identity"));
                               2348                 : 
 5445 alvherre                 2349 CBC         194 :             printTableAddFooter(&cont, tmpbuf.data);
 1356 tgl                      2350 EUB             : 
                               2351                 :             /*
 1356 tgl                      2352 ECB             :              * If it's a partitioned index, we'll print the tablespace below
 1356 tgl                      2353 EUB             :              */
 1356 tgl                      2354 GIC         194 :             if (tableinfo.relkind == RELKIND_INDEX)
 1356 tgl                      2355 CBC         128 :                 add_tablespace_footer(&cont, tableinfo.relkind,
                               2356                 :                                       tableinfo.tablespace, true);
                               2357                 :         }
                               2358                 : 
 7901 tgl                      2359 GIC         194 :         PQclear(result);
 8397 bruce                    2360 ECB             :     }
 1356 tgl                      2361                 :     /* If you add relkinds here, see also "Finish printing..." stanza below */
 2222 tgl                      2362 GIC        1345 :     else if (tableinfo.relkind == RELKIND_RELATION ||
                               2363             459 :              tableinfo.relkind == RELKIND_MATVIEW ||
                               2364             429 :              tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
 1356 tgl                      2365 CBC         336 :              tableinfo.relkind == RELKIND_PARTITIONED_TABLE ||
 1356 tgl                      2366 GIC         219 :              tableinfo.relkind == RELKIND_PARTITIONED_INDEX ||
                               2367             219 :              tableinfo.relkind == RELKIND_TOASTVALUE)
 8557 bruce                    2368 ECB             :     {
 7917 tgl                      2369                 :         /* Footer information about a table */
 5445 alvherre                 2370 CBC        1129 :         PGresult   *result = NULL;
                               2371            1129 :         int         tuples = 0;
 5445 alvherre                 2372 ECB             : 
                               2373                 :         /* print indexes */
 7655 peter_e                  2374 GIC        1129 :         if (tableinfo.hasindex)
                               2375                 :         {
 7655 peter_e                  2376 CBC         367 :             printfPQExpBuffer(&buf,
  479 tgl                      2377 ECB             :                               "SELECT c2.relname, i.indisprimary, i.indisunique, "
                               2378                 :                               "i.indisclustered, i.indisvalid, "
                               2379                 :                               "pg_catalog.pg_get_indexdef(i.indexrelid, 0, true),\n  "
                               2380                 :                               "pg_catalog.pg_get_constraintdef(con.oid, true), "
                               2381                 :                               "contype, condeferrable, condeferred");
 3439 rhaas                    2382 CBC         367 :             if (pset.sversion >= 90400)
 3429 heikki.linnakangas       2383 GIC         367 :                 appendPQExpBufferStr(&buf, ", i.indisreplident");
                               2384                 :             else
 3429 heikki.linnakangas       2385 UIC           0 :                 appendPQExpBufferStr(&buf, ", false AS indisreplident");
  479 tgl                      2386 GIC         367 :             appendPQExpBufferStr(&buf, ", c2.reltablespace");
 4777                          2387             367 :             appendPQExpBuffer(&buf,
  479 tgl                      2388 ECB             :                               "\nFROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i\n"
                               2389                 :                               "  LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN ('p','u','x'))\n"
                               2390                 :                               "WHERE c.oid = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
 1377 tgl                      2391 EUB             :                               "ORDER BY i.indisprimary DESC, c2.relname;",
 7522 bruce                    2392 ECB             :                               oid);
 3090 fujii                    2393 CBC         367 :             result = PSQLexec(buf.data);
 5445 alvherre                 2394 GIC         367 :             if (!result)
 7655 peter_e                  2395 UIC           0 :                 goto error_return;
                               2396                 :             else
 5445 alvherre                 2397 GIC         367 :                 tuples = PQntuples(result);
                               2398                 : 
 5445 alvherre                 2399 CBC         367 :             if (tuples > 0)
 5445 alvherre                 2400 ECB             :             {
 5445 alvherre                 2401 GBC         352 :                 printTableAddFooter(&cont, _("Indexes:"));
 5445 alvherre                 2402 GIC         977 :                 for (i = 0; i < tuples; i++)
 5445 alvherre                 2403 ECB             :                 {
                               2404                 :                     /* untranslated index name */
 5445 alvherre                 2405 CBC         625 :                     printfPQExpBuffer(&buf, "    \"%s\"",
                               2406                 :                                       PQgetvalue(result, i, 0));
 5445 alvherre                 2407 ECB             : 
 4777 tgl                      2408                 :                     /* If exclusion constraint, print the constraintdef */
 4777 tgl                      2409 GIC         625 :                     if (strcmp(PQgetvalue(result, i, 7), "x") == 0)
                               2410                 :                     {
 4777 tgl                      2411 CBC          27 :                         appendPQExpBuffer(&buf, " %s",
                               2412                 :                                           PQgetvalue(result, i, 6));
                               2413                 :                     }
                               2414                 :                     else
 4777 tgl                      2415 ECB             :                     {
                               2416                 :                         const char *indexdef;
                               2417                 :                         const char *usingpos;
                               2418                 : 
                               2419                 :                         /* Label as primary key or unique (but not both) */
 4777 tgl                      2420 GIC         598 :                         if (strcmp(PQgetvalue(result, i, 1), "t") == 0)
 3429 heikki.linnakangas       2421             151 :                             appendPQExpBufferStr(&buf, " PRIMARY KEY,");
 4777 tgl                      2422             447 :                         else if (strcmp(PQgetvalue(result, i, 2), "t") == 0)
                               2423                 :                         {
 4634 rhaas                    2424             165 :                             if (strcmp(PQgetvalue(result, i, 7), "u") == 0)
 3429 heikki.linnakangas       2425              72 :                                 appendPQExpBufferStr(&buf, " UNIQUE CONSTRAINT,");
 4634 rhaas                    2426 ECB             :                             else
 3429 heikki.linnakangas       2427 CBC          93 :                                 appendPQExpBufferStr(&buf, " UNIQUE,");
 4634 rhaas                    2428 ECB             :                         }
                               2429                 : 
 4777 tgl                      2430                 :                         /* Everything after "USING" is echoed verbatim */
 4777 tgl                      2431 CBC         598 :                         indexdef = PQgetvalue(result, i, 5);
 4777 tgl                      2432 GIC         598 :                         usingpos = strstr(indexdef, " USING ");
 4777 tgl                      2433 CBC         598 :                         if (usingpos)
 4777 tgl                      2434 GIC         598 :                             indexdef = usingpos + 7;
                               2435             598 :                         appendPQExpBuffer(&buf, " %s", indexdef);
                               2436                 : 
 4777 tgl                      2437 ECB             :                         /* Need these for deferrable PK/UNIQUE indexes */
 4777 tgl                      2438 CBC         598 :                         if (strcmp(PQgetvalue(result, i, 8), "t") == 0)
 3429 heikki.linnakangas       2439               9 :                             appendPQExpBufferStr(&buf, " DEFERRABLE");
 4777 tgl                      2440 ECB             : 
 4777 tgl                      2441 CBC         598 :                         if (strcmp(PQgetvalue(result, i, 9), "t") == 0)
 3429 heikki.linnakangas       2442 UIC           0 :                             appendPQExpBufferStr(&buf, " INITIALLY DEFERRED");
                               2443                 :                     }
 4777 tgl                      2444 ECB             : 
                               2445                 :                     /* Add these for all cases */
 5445 alvherre                 2446 GIC         625 :                     if (strcmp(PQgetvalue(result, i, 3), "t") == 0)
 3429 heikki.linnakangas       2447 LBC           0 :                         appendPQExpBufferStr(&buf, " CLUSTER");
 5445 alvherre                 2448 EUB             : 
 5445 alvherre                 2449 GIC         625 :                     if (strcmp(PQgetvalue(result, i, 4), "t") != 0)
 3429 heikki.linnakangas       2450              21 :                         appendPQExpBufferStr(&buf, " INVALID");
                               2451                 : 
 3439 rhaas                    2452 CBC         625 :                     if (strcmp(PQgetvalue(result, i, 10), "t") == 0)
 1375 drowley                  2453 GBC          27 :                         appendPQExpBufferStr(&buf, " REPLICA IDENTITY");
                               2454                 : 
 5445 alvherre                 2455 CBC         625 :                     printTableAddFooter(&cont, buf.data);
 5445 alvherre                 2456 ECB             : 
                               2457                 :                     /* Print tablespace of the index on the same line */
  479 tgl                      2458 CBC         625 :                     add_tablespace_footer(&cont, RELKIND_INDEX,
                               2459             625 :                                           atooid(PQgetvalue(result, i, 11)),
                               2460                 :                                           false);
 5445 alvherre                 2461 ECB             :                 }
                               2462                 :             }
 5445 alvherre                 2463 GIC         367 :             PQclear(result);
 8397 bruce                    2464 ECB             :         }
                               2465                 : 
                               2466                 :         /* print table (and column) check constraints */
 7655 peter_e                  2467 GIC        1129 :         if (tableinfo.checks)
                               2468                 :         {
 7655 peter_e                  2469 CBC         183 :             printfPQExpBuffer(&buf,
                               2470                 :                               "SELECT r.conname, "
                               2471                 :                               "pg_catalog.pg_get_constraintdef(r.oid, true)\n"
                               2472                 :                               "FROM pg_catalog.pg_constraint r\n"
 4006 alvherre                 2473 ECB             :                               "WHERE r.conrelid = '%s' AND r.contype = 'c'\n"
                               2474                 :                               "ORDER BY 1;",
                               2475                 :                               oid);
 3090 fujii                    2476 GIC         183 :             result = PSQLexec(buf.data);
 5445 alvherre                 2477             183 :             if (!result)
 7655 peter_e                  2478 UIC           0 :                 goto error_return;
                               2479                 :             else
 5445 alvherre                 2480 GIC         183 :                 tuples = PQntuples(result);
                               2481                 : 
 5445 alvherre                 2482 CBC         183 :             if (tuples > 0)
 5865 JanWieck                 2483 ECB             :             {
 5445 alvherre                 2484 GBC         183 :                 printTableAddFooter(&cont, _("Check constraints:"));
 5445 alvherre                 2485 GIC         453 :                 for (i = 0; i < tuples; i++)
 5445 alvherre                 2486 ECB             :                 {
                               2487                 :                     /* untranslated constraint name and def */
 4006 alvherre                 2488 CBC         270 :                     printfPQExpBuffer(&buf, "    \"%s\" %s",
                               2489                 :                                       PQgetvalue(result, i, 0),
 4006 alvherre                 2490 ECB             :                                       PQgetvalue(result, i, 1));
 8397 bruce                    2491                 : 
 5445 alvherre                 2492 GIC         270 :                     printTableAddFooter(&cont, buf.data);
                               2493                 :                 }
 7226 tgl                      2494 ECB             :             }
 5445 alvherre                 2495 GIC         183 :             PQclear(result);
                               2496                 :         }
                               2497                 : 
 1791 alvherre                 2498 ECB             :         /*
                               2499                 :          * Print foreign-key constraints (there are none if no triggers,
                               2500                 :          * except if the table is partitioned, in which case the triggers
                               2501                 :          * appear in the partitions)
                               2502                 :          */
 1791 alvherre                 2503 GIC        1129 :         if (tableinfo.hastriggers ||
                               2504            1027 :             tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
                               2505                 :         {
 1475                          2506             207 :             if (pset.sversion >= 120000 &&
                               2507             207 :                 (tableinfo.ispartition || tableinfo.relkind == RELKIND_PARTITIONED_TABLE))
                               2508                 :             {
 1475 alvherre                 2509 ECB             :                 /*
                               2510                 :                  * Put the constraints defined in this table first, followed
                               2511                 :                  * by the constraints defined in ancestor partitioned tables.
                               2512                 :                  */
 1475 alvherre                 2513 CBC         144 :                 printfPQExpBuffer(&buf,
                               2514                 :                                   "SELECT conrelid = '%s'::pg_catalog.regclass AS sametable,\n"
                               2515                 :                                   "       conname,\n"
                               2516                 :                                   "       pg_catalog.pg_get_constraintdef(oid, true) AS condef,\n"
                               2517                 :                                   "       conrelid::pg_catalog.regclass AS ontable\n"
                               2518                 :                                   "  FROM pg_catalog.pg_constraint,\n"
 1475 alvherre                 2519 ECB             :                                   "       pg_catalog.pg_partition_ancestors('%s')\n"
                               2520                 :                                   " WHERE conrelid = relid AND contype = 'f' AND conparentid = 0\n"
                               2521                 :                                   "ORDER BY sametable DESC, conname;",
                               2522                 :                                   oid, oid);
                               2523                 :             }
                               2524                 :             else
                               2525                 :             {
 1475 alvherre                 2526 GIC          63 :                 printfPQExpBuffer(&buf,
                               2527                 :                                   "SELECT true as sametable, conname,\n"
                               2528                 :                                   "  pg_catalog.pg_get_constraintdef(r.oid, true) as condef,\n"
                               2529                 :                                   "  conrelid::pg_catalog.regclass AS ontable\n"
                               2530                 :                                   "FROM pg_catalog.pg_constraint r\n"
                               2531                 :                                   "WHERE r.conrelid = '%s' AND r.contype = 'f'\n",
 1475 alvherre                 2532 ECB             :                                   oid);
                               2533                 : 
 1467 alvherre                 2534 GIC          63 :                 if (pset.sversion >= 120000)
 1375 drowley                  2535              63 :                     appendPQExpBufferStr(&buf, "     AND conparentid = 0\n");
                               2536              63 :                 appendPQExpBufferStr(&buf, "ORDER BY conname");
                               2537                 :             }
                               2538                 : 
 3090 fujii                    2539             207 :             result = PSQLexec(buf.data);
 5445 alvherre                 2540 CBC         207 :             if (!result)
 7541 tgl                      2541 LBC           0 :                 goto error_return;
 7541 tgl                      2542 ECB             :             else
 5445 alvherre                 2543 GIC         207 :                 tuples = PQntuples(result);
                               2544                 : 
 5445 alvherre                 2545 CBC         207 :             if (tuples > 0)
 5445 alvherre                 2546 ECB             :             {
 1475 alvherre                 2547 GBC          69 :                 int         i_sametable = PQfnumber(result, "sametable"),
 1475 alvherre                 2548 GIC          69 :                             i_conname = PQfnumber(result, "conname"),
 1475 alvherre                 2549 CBC          69 :                             i_condef = PQfnumber(result, "condef"),
 1475 alvherre                 2550 GIC          69 :                             i_ontable = PQfnumber(result, "ontable");
 1475 alvherre                 2551 ECB             : 
 5445 alvherre                 2552 GIC          69 :                 printTableAddFooter(&cont, _("Foreign-key constraints:"));
 5445 alvherre                 2553 CBC         156 :                 for (i = 0; i < tuples; i++)
 5445 alvherre                 2554 ECB             :                 {
 1475                          2555                 :                     /*
                               2556                 :                      * Print untranslated constraint name and definition. Use
                               2557                 :                      * a "TABLE tab" prefix when the constraint is defined in
                               2558                 :                      * a parent partitioned table.
                               2559                 :                      */
 1475 alvherre                 2560 GIC          87 :                     if (strcmp(PQgetvalue(result, i, i_sametable), "f") == 0)
                               2561              39 :                         printfPQExpBuffer(&buf, "    TABLE \"%s\" CONSTRAINT \"%s\" %s",
                               2562                 :                                           PQgetvalue(result, i, i_ontable),
                               2563                 :                                           PQgetvalue(result, i, i_conname),
                               2564                 :                                           PQgetvalue(result, i, i_condef));
                               2565                 :                     else
 1475 alvherre                 2566 CBC          48 :                         printfPQExpBuffer(&buf, "    \"%s\" %s",
 1475 alvherre                 2567 ECB             :                                           PQgetvalue(result, i, i_conname),
                               2568                 :                                           PQgetvalue(result, i, i_condef));
                               2569                 : 
 5445 alvherre                 2570 GIC          87 :                     printTableAddFooter(&cont, buf.data);
                               2571                 :                 }
 5445 alvherre                 2572 ECB             :             }
 5445 alvherre                 2573 GIC         207 :             PQclear(result);
                               2574                 :         }
                               2575                 : 
 1475 alvherre                 2576 ECB             :         /* print incoming foreign-key references */
 1475 alvherre                 2577 GIC        1129 :         if (tableinfo.hastriggers ||
                               2578            1027 :             tableinfo.relkind == RELKIND_PARTITIONED_TABLE)
 5488 tgl                      2579 ECB             :         {
 1475 alvherre                 2580 GIC         207 :             if (pset.sversion >= 120000)
                               2581                 :             {
                               2582             207 :                 printfPQExpBuffer(&buf,
 1475 alvherre                 2583 ECB             :                                   "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n"
                               2584                 :                                   "       pg_catalog.pg_get_constraintdef(oid, true) AS condef\n"
                               2585                 :                                   "  FROM pg_catalog.pg_constraint c\n"
                               2586                 :                                   " WHERE confrelid IN (SELECT pg_catalog.pg_partition_ancestors('%s')\n"
                               2587                 :                                   "                     UNION ALL VALUES ('%s'::pg_catalog.regclass))\n"
                               2588                 :                                   "       AND contype = 'f' AND conparentid = 0\n"
                               2589                 :                                   "ORDER BY conname;",
                               2590                 :                                   oid, oid);
                               2591                 :             }
                               2592                 :             else
                               2593                 :             {
 1475 alvherre                 2594 UIC           0 :                 printfPQExpBuffer(&buf,
                               2595                 :                                   "SELECT conname, conrelid::pg_catalog.regclass AS ontable,\n"
                               2596                 :                                   "       pg_catalog.pg_get_constraintdef(oid, true) AS condef\n"
                               2597                 :                                   "  FROM pg_catalog.pg_constraint\n"
                               2598                 :                                   " WHERE confrelid = %s AND contype = 'f'\n"
                               2599                 :                                   "ORDER BY conname;",
 1475 alvherre                 2600 EUB             :                                   oid);
                               2601                 :             }
                               2602                 : 
 3090 fujii                    2603 GIC         207 :             result = PSQLexec(buf.data);
 5445 alvherre                 2604             207 :             if (!result)
 5488 tgl                      2605 UIC           0 :                 goto error_return;
                               2606                 :             else
 5445 alvherre                 2607 GIC         207 :                 tuples = PQntuples(result);
                               2608                 : 
 5445 alvherre                 2609 CBC         207 :             if (tuples > 0)
 7318 bruce                    2610 ECB             :             {
 1475 alvherre                 2611 GBC          30 :                 int         i_conname = PQfnumber(result, "conname"),
 1475 alvherre                 2612 GIC          30 :                             i_ontable = PQfnumber(result, "ontable"),
 1475 alvherre                 2613 CBC          30 :                             i_condef = PQfnumber(result, "condef");
                               2614                 : 
 5445                          2615              30 :                 printTableAddFooter(&cont, _("Referenced by:"));
 5445 alvherre                 2616 GIC          60 :                 for (i = 0; i < tuples; i++)
 6508 bruce                    2617 ECB             :                 {
 5048 peter_e                  2618 CBC          30 :                     printfPQExpBuffer(&buf, "    TABLE \"%s\" CONSTRAINT \"%s\" %s",
 1475 alvherre                 2619 ECB             :                                       PQgetvalue(result, i, i_ontable),
                               2620                 :                                       PQgetvalue(result, i, i_conname),
                               2621                 :                                       PQgetvalue(result, i, i_condef));
 5445                          2622                 : 
 5445 alvherre                 2623 GIC          30 :                     printTableAddFooter(&cont, buf.data);
 6508 bruce                    2624 ECB             :                 }
                               2625                 :             }
 5445 alvherre                 2626 GIC         207 :             PQclear(result);
                               2627                 :         }
                               2628                 : 
 3119 sfrost                   2629 ECB             :         /* print any row-level policies */
 3124 sfrost                   2630 GIC        1129 :         if (pset.sversion >= 90500)
                               2631                 :         {
 2083 tgl                      2632 CBC        1129 :             printfPQExpBuffer(&buf, "SELECT pol.polname,");
 2316 sfrost                   2633 GIC        1129 :             if (pset.sversion >= 100000)
 1375 drowley                  2634            1129 :                 appendPQExpBufferStr(&buf,
                               2635                 :                                      " pol.polpermissive,\n");
 2316 sfrost                   2636 ECB             :             else
 1375 drowley                  2637 UIC           0 :                 appendPQExpBufferStr(&buf,
 1375 drowley                  2638 ECB             :                                      " 't' as polpermissive,\n");
 2083 tgl                      2639 CBC        1129 :             appendPQExpBuffer(&buf,
 2083 tgl                      2640 ECB             :                               "  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"
                               2641                 :                               "  pg_catalog.pg_get_expr(pol.polqual, pol.polrelid),\n"
                               2642                 :                               "  pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid),\n"
 2083 tgl                      2643 EUB             :                               "  CASE pol.polcmd\n"
                               2644                 :                               "    WHEN 'r' THEN 'SELECT'\n"
 2083 tgl                      2645 ECB             :                               "    WHEN 'a' THEN 'INSERT'\n"
                               2646                 :                               "    WHEN 'w' THEN 'UPDATE'\n"
                               2647                 :                               "    WHEN 'd' THEN 'DELETE'\n"
                               2648                 :                               "    END AS cmd\n"
                               2649                 :                               "FROM pg_catalog.pg_policy pol\n"
                               2650                 :                               "WHERE pol.polrelid = '%s' ORDER BY 1;",
                               2651                 :                               oid);
                               2652                 : 
 3090 fujii                    2653 GIC        1129 :             result = PSQLexec(buf.data);
 3124 sfrost                   2654            1129 :             if (!result)
 3124 sfrost                   2655 UIC           0 :                 goto error_return;
                               2656                 :             else
 3124 sfrost                   2657 GIC        1129 :                 tuples = PQntuples(result);
                               2658                 : 
 3119 sfrost                   2659 ECB             :             /*
 2878 bruce                    2660                 :              * Handle cases where RLS is enabled and there are policies, or
 2878 bruce                    2661 EUB             :              * there aren't policies, or RLS isn't enabled but there are
                               2662                 :              * policies
 3119 sfrost                   2663 ECB             :              */
 2744 sfrost                   2664 GIC        1129 :             if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples > 0)
 3124                          2665               6 :                 printTableAddFooter(&cont, _("Policies:"));
                               2666                 : 
 2744                          2667            1129 :             if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples > 0)
 2667 peter_e                  2668 UIC           0 :                 printTableAddFooter(&cont, _("Policies (forced row security enabled):"));
                               2669                 : 
 2744 sfrost                   2670 CBC        1129 :             if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples == 0)
 2667 peter_e                  2671 LBC           0 :                 printTableAddFooter(&cont, _("Policies (row security enabled): (none)"));
                               2672                 : 
 2744 sfrost                   2673 CBC        1129 :             if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples == 0)
 2667 peter_e                  2674 UBC           0 :                 printTableAddFooter(&cont, _("Policies (forced row security enabled): (none)"));
                               2675                 : 
 3119 sfrost                   2676 CBC        1129 :             if (!tableinfo.rowsecurity && tuples > 0)
 2667 peter_e                  2677 UBC           0 :                 printTableAddFooter(&cont, _("Policies (row security disabled):"));
                               2678                 : 
 3119 sfrost                   2679 ECB             :             /* Might be an empty set - that's ok */
 3119 sfrost                   2680 GBC        1144 :             for (i = 0; i < tuples; i++)
                               2681                 :             {
 3119 sfrost                   2682 CBC          15 :                 printfPQExpBuffer(&buf, "    POLICY \"%s\"",
 2878 bruce                    2683 EUB             :                                   PQgetvalue(result, i, 0));
                               2684                 : 
 2316 sfrost                   2685 GIC          15 :                 if (*(PQgetvalue(result, i, 1)) == 'f')
 1375 drowley                  2686 CBC           9 :                     appendPQExpBufferStr(&buf, " AS RESTRICTIVE");
                               2687                 : 
 2316 sfrost                   2688              15 :                 if (!PQgetisnull(result, i, 5))
 3110 sfrost                   2689 UIC           0 :                     appendPQExpBuffer(&buf, " FOR %s",
                               2690                 :                                       PQgetvalue(result, i, 5));
 3124 sfrost                   2691 ECB             : 
 2316 sfrost                   2692 CBC          15 :                 if (!PQgetisnull(result, i, 2))
                               2693                 :                 {
 3110                          2694               9 :                     appendPQExpBuffer(&buf, "\n      TO %s",
 2316 sfrost                   2695 EUB             :                                       PQgetvalue(result, i, 2));
                               2696                 :                 }
                               2697                 : 
 2316 sfrost                   2698 CBC          15 :                 if (!PQgetisnull(result, i, 3))
 2806 mail                     2699 GIC          15 :                     appendPQExpBuffer(&buf, "\n      USING (%s)",
 2316 sfrost                   2700 ECB             :                                       PQgetvalue(result, i, 3));
                               2701                 : 
 2316 sfrost                   2702 GIC          15 :                 if (!PQgetisnull(result, i, 4))
 2806 mail                     2703 UIC           0 :                     appendPQExpBuffer(&buf, "\n      WITH CHECK (%s)",
 2316 sfrost                   2704 ECB             :                                       PQgetvalue(result, i, 4));
 3119                          2705                 : 
 3119 sfrost                   2706 GIC          15 :                 printTableAddFooter(&cont, buf.data);
                               2707                 :             }
 3124 sfrost                   2708 CBC        1129 :             PQclear(result);
 3124 sfrost                   2709 EUB             :         }
                               2710                 : 
                               2711                 :         /* print any extended statistics */
  744 tomas.vondra             2712 CBC        1129 :         if (pset.sversion >= 140000)
                               2713                 :         {
                               2714            1129 :             printfPQExpBuffer(&buf,
                               2715                 :                               "SELECT oid, "
                               2716                 :                               "stxrelid::pg_catalog.regclass, "
                               2717                 :                               "stxnamespace::pg_catalog.regnamespace::pg_catalog.text AS nsp, "
  744 tomas.vondra             2718 ECB             :                               "stxname,\n"
                               2719                 :                               "pg_catalog.pg_get_statisticsobjdef_columns(oid) AS columns,\n"
                               2720                 :                               "  'd' = any(stxkind) AS ndist_enabled,\n"
                               2721                 :                               "  'f' = any(stxkind) AS deps_enabled,\n"
                               2722                 :                               "  'm' = any(stxkind) AS mcv_enabled,\n"
                               2723                 :                               "stxstattarget\n"
                               2724                 :                               "FROM pg_catalog.pg_statistic_ext\n"
                               2725                 :                               "WHERE stxrelid = '%s'\n"
                               2726                 :                               "ORDER BY nsp, stxname;",
                               2727                 :                               oid);
                               2728                 : 
  744 tomas.vondra             2729 GIC        1129 :             result = PSQLexec(buf.data);
                               2730            1129 :             if (!result)
  744 tomas.vondra             2731 UIC           0 :                 goto error_return;
                               2732                 :             else
  744 tomas.vondra             2733 GIC        1129 :                 tuples = PQntuples(result);
                               2734                 : 
  744 tomas.vondra             2735 CBC        1129 :             if (tuples > 0)
  744 tomas.vondra             2736 ECB             :             {
  744 tomas.vondra             2737 GBC          18 :                 printTableAddFooter(&cont, _("Statistics objects:"));
                               2738                 : 
  744 tomas.vondra             2739 CBC          45 :                 for (i = 0; i < tuples; i++)
                               2740                 :                 {
                               2741              27 :                     bool        gotone = false;
                               2742                 :                     bool        has_ndistinct;
  744 tomas.vondra             2743 ECB             :                     bool        has_dependencies;
                               2744                 :                     bool        has_mcv;
                               2745                 :                     bool        has_all;
                               2746                 :                     bool        has_some;
                               2747                 : 
  744 tomas.vondra             2748 GIC          27 :                     has_ndistinct = (strcmp(PQgetvalue(result, i, 5), "t") == 0);
                               2749              27 :                     has_dependencies = (strcmp(PQgetvalue(result, i, 6), "t") == 0);
                               2750              27 :                     has_mcv = (strcmp(PQgetvalue(result, i, 7), "t") == 0);
                               2751                 : 
                               2752              27 :                     printfPQExpBuffer(&buf, "    ");
                               2753                 : 
  744 tomas.vondra             2754 ECB             :                     /* statistics object name (qualified with namespace) */
  587 alvherre                 2755 CBC          27 :                     appendPQExpBuffer(&buf, "\"%s.%s\"",
  744 tomas.vondra             2756 ECB             :                                       PQgetvalue(result, i, 2),
                               2757                 :                                       PQgetvalue(result, i, 3));
                               2758                 : 
                               2759                 :                     /*
                               2760                 :                      * When printing kinds we ignore expression statistics,
  439 michael                  2761                 :                      * which are used only internally and can't be specified
                               2762                 :                      * by user. We don't print the kinds when none are
                               2763                 :                      * specified (in which case it has to be statistics on a
                               2764                 :                      * single expr) or when all are specified (in which case
                               2765                 :                      * we assume it's expanded by CREATE STATISTICS).
                               2766                 :                      */
  744 tomas.vondra             2767 GIC          27 :                     has_all = (has_ndistinct && has_dependencies && has_mcv);
                               2768              27 :                     has_some = (has_ndistinct || has_dependencies || has_mcv);
                               2769                 : 
                               2770              27 :                     if (has_some && !has_all)
                               2771                 :                     {
  675 drowley                  2772 UIC           0 :                         appendPQExpBufferStr(&buf, " (");
  744 tomas.vondra             2773 ECB             : 
                               2774                 :                         /* options */
  744 tomas.vondra             2775 UIC           0 :                         if (has_ndistinct)
  744 tomas.vondra             2776 ECB             :                         {
  744 tomas.vondra             2777 UIC           0 :                             appendPQExpBufferStr(&buf, "ndistinct");
  744 tomas.vondra             2778 UBC           0 :                             gotone = true;
                               2779                 :                         }
                               2780                 : 
                               2781               0 :                         if (has_dependencies)
                               2782                 :                         {
                               2783               0 :                             appendPQExpBuffer(&buf, "%sdependencies", gotone ? ", " : "");
                               2784               0 :                             gotone = true;
                               2785                 :                         }
                               2786                 : 
                               2787               0 :                         if (has_mcv)
                               2788                 :                         {
                               2789               0 :                             appendPQExpBuffer(&buf, "%smcv", gotone ? ", " : "");
  744 tomas.vondra             2790 EUB             :                         }
                               2791                 : 
  675 drowley                  2792 UIC           0 :                         appendPQExpBufferChar(&buf, ')');
  744 tomas.vondra             2793 EUB             :                     }
                               2794                 : 
  744 tomas.vondra             2795 GBC          27 :                     appendPQExpBuffer(&buf, " ON %s FROM %s",
                               2796                 :                                       PQgetvalue(result, i, 4),
                               2797                 :                                       PQgetvalue(result, i, 1));
  744 tomas.vondra             2798 EUB             : 
                               2799                 :                     /* Show the stats target if it's not default */
  744 tomas.vondra             2800 GIC          27 :                     if (strcmp(PQgetvalue(result, i, 8), "-1") != 0)
  744 tomas.vondra             2801 CBC           3 :                         appendPQExpBuffer(&buf, "; STATISTICS %s",
                               2802                 :                                           PQgetvalue(result, i, 8));
                               2803                 : 
  744 tomas.vondra             2804 GIC          27 :                     printTableAddFooter(&cont, buf.data);
                               2805                 :                 }
  744 tomas.vondra             2806 ECB             :             }
  744 tomas.vondra             2807 CBC        1129 :             PQclear(result);
                               2808                 :         }
  744 tomas.vondra             2809 UIC           0 :         else if (pset.sversion >= 100000)
 2207 alvherre                 2810 ECB             :         {
 2207 alvherre                 2811 UIC           0 :             printfPQExpBuffer(&buf,
                               2812                 :                               "SELECT oid, "
 2158 alvherre                 2813 ECB             :                               "stxrelid::pg_catalog.regclass, "
                               2814                 :                               "stxnamespace::pg_catalog.regnamespace AS nsp, "
 2158 alvherre                 2815 EUB             :                               "stxname,\n"
                               2816                 :                               "  (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(attname),', ')\n"
 2183                          2817                 :                               "   FROM pg_catalog.unnest(stxkeys) s(attnum)\n"
                               2818                 :                               "   JOIN pg_catalog.pg_attribute a ON (stxrelid = a.attrelid AND\n"
                               2819                 :                               "        a.attnum = s.attnum AND NOT attisdropped)) AS columns,\n"
                               2820                 :                               "  'd' = any(stxkind) AS ndist_enabled,\n"
                               2821                 :                               "  'f' = any(stxkind) AS deps_enabled,\n"
                               2822                 :                               "  'm' = any(stxkind) AS mcv_enabled,\n");
                               2823                 : 
  940 alvherre                 2824 UIC           0 :             if (pset.sversion >= 130000)
                               2825               0 :                 appendPQExpBufferStr(&buf, "  stxstattarget\n");
                               2826                 :             else
                               2827               0 :                 appendPQExpBufferStr(&buf, "  -1 AS stxstattarget\n");
  456 michael                  2828               0 :             appendPQExpBuffer(&buf, "FROM pg_catalog.pg_statistic_ext\n"
                               2829                 :                               "WHERE stxrelid = '%s'\n"
 2194 tgl                      2830 EUB             :                               "ORDER BY 1;",
 2207 alvherre                 2831                 :                               oid);
                               2832                 : 
 2207 alvherre                 2833 UBC           0 :             result = PSQLexec(buf.data);
                               2834               0 :             if (!result)
 2207 alvherre                 2835 UIC           0 :                 goto error_return;
                               2836                 :             else
                               2837               0 :                 tuples = PQntuples(result);
                               2838                 : 
 2207 alvherre                 2839 UBC           0 :             if (tuples > 0)
 2207 alvherre                 2840 EUB             :             {
 2156 tgl                      2841 UBC           0 :                 printTableAddFooter(&cont, _("Statistics objects:"));
                               2842                 : 
 2207 alvherre                 2843               0 :                 for (i = 0; i < tuples; i++)
                               2844                 :                 {
 2195 simon                    2845               0 :                     bool        gotone = false;
                               2846                 : 
 2207 alvherre                 2847               0 :                     printfPQExpBuffer(&buf, "    ");
                               2848                 : 
 2156 tgl                      2849 EUB             :                     /* statistics object name (qualified with namespace) */
  587 alvherre                 2850 UIC           0 :                     appendPQExpBuffer(&buf, "\"%s.%s\" (",
 2158 alvherre                 2851 EUB             :                                       PQgetvalue(result, i, 2),
                               2852                 :                                       PQgetvalue(result, i, 3));
 2207                          2853                 : 
                               2854                 :                     /* options */
 2207 alvherre                 2855 UIC           0 :                     if (strcmp(PQgetvalue(result, i, 5), "t") == 0)
 2207 alvherre                 2856 EUB             :                     {
 2207 alvherre                 2857 UIC           0 :                         appendPQExpBufferStr(&buf, "ndistinct");
 2195 simon                    2858               0 :                         gotone = true;
                               2859                 :                     }
                               2860                 : 
 2195 simon                    2861 UBC           0 :                     if (strcmp(PQgetvalue(result, i, 6), "t") == 0)
                               2862                 :                     {
                               2863               0 :                         appendPQExpBuffer(&buf, "%sdependencies", gotone ? ", " : "");
 1474 tomas.vondra             2864               0 :                         gotone = true;
                               2865                 :                     }
                               2866                 : 
                               2867               0 :                     if (strcmp(PQgetvalue(result, i, 7), "t") == 0)
                               2868                 :                     {
                               2869               0 :                         appendPQExpBuffer(&buf, "%smcv", gotone ? ", " : "");
 2207 alvherre                 2870 EUB             :                     }
                               2871                 : 
 2158 alvherre                 2872 UIC           0 :                     appendPQExpBuffer(&buf, ") ON %s FROM %s",
 2158 alvherre                 2873 EUB             :                                       PQgetvalue(result, i, 4),
                               2874                 :                                       PQgetvalue(result, i, 1));
 2207                          2875                 : 
                               2876                 :                     /* Show the stats target if it's not default */
  940 alvherre                 2877 UIC           0 :                     if (strcmp(PQgetvalue(result, i, 8), "-1") != 0)
  940 alvherre                 2878 UBC           0 :                         appendPQExpBuffer(&buf, "; STATISTICS %s",
                               2879                 :                                           PQgetvalue(result, i, 8));
                               2880                 : 
 2207 alvherre                 2881 UIC           0 :                     printTableAddFooter(&cont, buf.data);
                               2882                 :                 }
 2207 alvherre                 2883 EUB             :             }
 2207 alvherre                 2884 UBC           0 :             PQclear(result);
                               2885                 :         }
                               2886                 : 
 5445 alvherre                 2887 EUB             :         /* print rules */
 2222 tgl                      2888 GIC        1129 :         if (tableinfo.hasrules && tableinfo.relkind != RELKIND_MATVIEW)
                               2889                 :         {
  479 tgl                      2890 GBC          15 :             printfPQExpBuffer(&buf,
                               2891                 :                               "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
                               2892                 :                               "ev_enabled\n"
                               2893                 :                               "FROM pg_catalog.pg_rewrite r\n"
  479 tgl                      2894 ECB             :                               "WHERE r.ev_class = '%s' ORDER BY 1;",
                               2895                 :                               oid);
 3090 fujii                    2896 CBC          15 :             result = PSQLexec(buf.data);
 5445 alvherre                 2897 GIC          15 :             if (!result)
 5445 alvherre                 2898 UIC           0 :                 goto error_return;
                               2899                 :             else
 5445 alvherre                 2900 GIC          15 :                 tuples = PQntuples(result);
                               2901                 : 
 5445 alvherre                 2902 CBC          15 :             if (tuples > 0)
 5865 JanWieck                 2903 ECB             :             {
 5445 alvherre                 2904 EUB             :                 bool        have_heading;
                               2905                 :                 int         category;
 7318 bruce                    2906 ECB             : 
 5445 alvherre                 2907 GIC          75 :                 for (category = 0; category < 4; category++)
 5865 JanWieck                 2908 ECB             :                 {
 5445 alvherre                 2909 GIC          60 :                     have_heading = false;
                               2910                 : 
                               2911             216 :                     for (i = 0; i < tuples; i++)
                               2912                 :                     {
 5445 alvherre                 2913 ECB             :                         const char *ruledef;
 5445 alvherre                 2914 GIC         156 :                         bool        list_rule = false;
 5865 JanWieck                 2915 ECB             : 
 5865 JanWieck                 2916 GIC         156 :                         switch (category)
 5865 JanWieck                 2917 ECB             :                         {
 5865 JanWieck                 2918 GIC          39 :                             case 0:
 5445 alvherre                 2919              39 :                                 if (*PQgetvalue(result, i, 2) == 'O')
 5445 alvherre                 2920 CBC          39 :                                     list_rule = true;
 5865 JanWieck                 2921 GIC          39 :                                 break;
 5865 JanWieck                 2922 CBC          39 :                             case 1:
 5445 alvherre                 2923 GIC          39 :                                 if (*PQgetvalue(result, i, 2) == 'D')
 5445 alvherre                 2924 LBC           0 :                                     list_rule = true;
 5865 JanWieck                 2925 CBC          39 :                                 break;
                               2926              39 :                             case 2:
 5445 alvherre                 2927              39 :                                 if (*PQgetvalue(result, i, 2) == 'A')
 5445 alvherre                 2928 LBC           0 :                                     list_rule = true;
 5865 JanWieck                 2929 CBC          39 :                                 break;
 5865 JanWieck                 2930 GBC          39 :                             case 3:
 5445 alvherre                 2931 CBC          39 :                                 if (*PQgetvalue(result, i, 2) == 'R')
 5445 alvherre                 2932 LBC           0 :                                     list_rule = true;
 5865 JanWieck                 2933 CBC          39 :                                 break;
 5865 JanWieck                 2934 EUB             :                         }
 5445 alvherre                 2935 CBC         156 :                         if (!list_rule)
                               2936             117 :                             continue;
 5865 JanWieck                 2937 ECB             : 
 5445 alvherre                 2938 GBC          39 :                         if (!have_heading)
 5445 alvherre                 2939 ECB             :                         {
 5445 alvherre                 2940 GIC          15 :                             switch (category)
 5445 alvherre                 2941 ECB             :                             {
 5445 alvherre                 2942 CBC          15 :                                 case 0:
 5445 alvherre                 2943 GIC          15 :                                     printfPQExpBuffer(&buf, _("Rules:"));
 5445 alvherre                 2944 CBC          15 :                                     break;
 5445 alvherre                 2945 UIC           0 :                                 case 1:
 5445 alvherre                 2946 LBC           0 :                                     printfPQExpBuffer(&buf, _("Disabled rules:"));
 5445 alvherre                 2947 UIC           0 :                                     break;
 5445 alvherre                 2948 LBC           0 :                                 case 2:
                               2949               0 :                                     printfPQExpBuffer(&buf, _("Rules firing always:"));
                               2950               0 :                                     break;
 5445 alvherre                 2951 UBC           0 :                                 case 3:
                               2952               0 :                                     printfPQExpBuffer(&buf, _("Rules firing on replica only:"));
                               2953               0 :                                     break;
 5445 alvherre                 2954 EUB             :                             }
 5445 alvherre                 2955 GBC          15 :                             printTableAddFooter(&cont, buf.data);
                               2956              15 :                             have_heading = true;
 5445 alvherre                 2957 EUB             :                         }
                               2958                 : 
                               2959                 :                         /* Everything after "CREATE RULE" is echoed verbatim */
 5445 alvherre                 2960 GIC          39 :                         ruledef = PQgetvalue(result, i, 1);
 5445 alvherre                 2961 CBC          39 :                         ruledef += 12;
                               2962              39 :                         printfPQExpBuffer(&buf, "    %s", ruledef);
 5445 alvherre                 2963 GIC          39 :                         printTableAddFooter(&cont, buf.data);
                               2964                 :                     }
                               2965                 :                 }
 7318 bruce                    2966 ECB             :             }
 5445 alvherre                 2967 CBC          15 :             PQclear(result);
 8397 bruce                    2968 ECB             :         }
 2271 peter_e                  2969                 : 
                               2970                 :         /* print any publications */
 2271 peter_e                  2971 GIC        1129 :         if (pset.sversion >= 100000)
                               2972                 :         {
  529 akapila                  2973 CBC        1129 :             if (pset.sversion >= 150000)
                               2974                 :             {
  529 akapila                  2975 GIC        1129 :                 printfPQExpBuffer(&buf,
                               2976                 :                                   "SELECT pubname\n"
  334 peter                    2977 ECB             :                                   "     , NULL\n"
                               2978                 :                                   "     , NULL\n"
  529 akapila                  2979                 :                                   "FROM pg_catalog.pg_publication p\n"
                               2980                 :                                   "     JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
  334 peter                    2981                 :                                   "     JOIN pg_catalog.pg_class pc ON pc.relnamespace = pn.pnnspid\n"
                               2982                 :                                   "WHERE pc.oid ='%s' and pg_catalog.pg_relation_is_publishable('%s')\n"
                               2983                 :                                   "UNION\n"
                               2984                 :                                   "SELECT pubname\n"
                               2985                 :                                   "     , pg_get_expr(pr.prqual, c.oid)\n"
                               2986                 :                                   "     , (CASE WHEN pr.prattrs IS NOT NULL THEN\n"
                               2987                 :                                   "         (SELECT string_agg(attname, ', ')\n"
                               2988                 :                                   "           FROM pg_catalog.generate_series(0, pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n"
                               2989                 :                                   "                pg_catalog.pg_attribute\n"
                               2990                 :                                   "          WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n"
                               2991                 :                                   "        ELSE NULL END) "
                               2992                 :                                   "FROM pg_catalog.pg_publication p\n"
                               2993                 :                                   "     JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
                               2994                 :                                   "     JOIN pg_catalog.pg_class c ON c.oid = pr.prrelid\n"
                               2995                 :                                   "WHERE pr.prrelid = '%s'\n"
                               2996                 :                                   "UNION\n"
                               2997                 :                                   "SELECT pubname\n"
                               2998                 :                                   "     , NULL\n"
                               2999                 :                                   "     , NULL\n"
                               3000                 :                                   "FROM pg_catalog.pg_publication p\n"
                               3001                 :                                   "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
                               3002                 :                                   "ORDER BY 1;",
                               3003                 :                                   oid, oid, oid, oid);
                               3004                 :             }
                               3005                 :             else
                               3006                 :             {
  529 akapila                  3007 UIC           0 :                 printfPQExpBuffer(&buf,
                               3008                 :                                   "SELECT pubname\n"
                               3009                 :                                   "     , NULL\n"
                               3010                 :                                   "     , NULL\n"
                               3011                 :                                   "FROM pg_catalog.pg_publication p\n"
                               3012                 :                                   "JOIN pg_catalog.pg_publication_rel pr ON p.oid = pr.prpubid\n"
  529 akapila                  3013 EUB             :                                   "WHERE pr.prrelid = '%s'\n"
                               3014                 :                                   "UNION ALL\n"
                               3015                 :                                   "SELECT pubname\n"
                               3016                 :                                   "     , NULL\n"
                               3017                 :                                   "     , NULL\n"
                               3018                 :                                   "FROM pg_catalog.pg_publication p\n"
                               3019                 :                                   "WHERE p.puballtables AND pg_catalog.pg_relation_is_publishable('%s')\n"
                               3020                 :                                   "ORDER BY 1;",
                               3021                 :                                   oid, oid);
                               3022                 :             }
                               3023                 : 
 2271 peter_e                  3024 GIC        1129 :             result = PSQLexec(buf.data);
                               3025            1129 :             if (!result)
 2271 peter_e                  3026 UIC           0 :                 goto error_return;
                               3027                 :             else
 2271 peter_e                  3028 GIC        1129 :                 tuples = PQntuples(result);
                               3029                 : 
 2271 peter_e                  3030 CBC        1129 :             if (tuples > 0)
                               3031              36 :                 printTableAddFooter(&cont, _("Publications:"));
 2271 peter_e                  3032 EUB             : 
                               3033                 :             /* Might be an empty set - that's ok */
 2271 peter_e                  3034 CBC        1183 :             for (i = 0; i < tuples; i++)
                               3035                 :             {
                               3036              54 :                 printfPQExpBuffer(&buf, "    \"%s\"",
 2271 peter_e                  3037 ECB             :                                   PQgetvalue(result, i, 0));
                               3038                 : 
                               3039                 :                 /* column list (if any) */
  379 tomas.vondra             3040 CBC          54 :                 if (!PQgetisnull(result, i, 2))
  379 tomas.vondra             3041 GIC          12 :                     appendPQExpBuffer(&buf, " (%s)",
  379 tomas.vondra             3042 ECB             :                                       PQgetvalue(result, i, 2));
                               3043                 : 
                               3044                 :                 /* row filter (if any) */
  411 akapila                  3045 GIC          54 :                 if (!PQgetisnull(result, i, 1))
  411 akapila                  3046 CBC          12 :                     appendPQExpBuffer(&buf, " WHERE %s",
  411 akapila                  3047 ECB             :                                       PQgetvalue(result, i, 1));
                               3048                 : 
 2271 peter_e                  3049 GIC          54 :                 printTableAddFooter(&cont, buf.data);
                               3050                 :             }
 2271 peter_e                  3051 CBC        1129 :             PQclear(result);
 2271 peter_e                  3052 ECB             :         }
                               3053                 :     }
                               3054                 : 
 1725 tgl                      3055                 :     /* Get view_def if table is a view or materialized view */
 1725 tgl                      3056 GIC        1539 :     if ((tableinfo.relkind == RELKIND_VIEW ||
 1725 tgl                      3057 CBC        1539 :          tableinfo.relkind == RELKIND_MATVIEW) && verbose)
                               3058                 :     {
                               3059                 :         PGresult   *result;
                               3060                 : 
 1725 tgl                      3061 GIC         197 :         printfPQExpBuffer(&buf,
 1725 tgl                      3062 ECB             :                           "SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid, true);",
                               3063                 :                           oid);
 1725 tgl                      3064 GIC         197 :         result = PSQLexec(buf.data);
                               3065             197 :         if (!result)
 1725 tgl                      3066 UIC           0 :             goto error_return;
 1725 tgl                      3067 ECB             : 
 1725 tgl                      3068 GIC         197 :         if (PQntuples(result) > 0)
                               3069             197 :             view_def = pg_strdup(PQgetvalue(result, 0, 0));
 1725 tgl                      3070 ECB             : 
 1725 tgl                      3071 CBC         197 :         PQclear(result);
 1725 tgl                      3072 EUB             :     }
                               3073                 : 
 3689 kgrittn                  3074 CBC        1539 :     if (view_def)
 3689 kgrittn                  3075 ECB             :     {
 3689 kgrittn                  3076 GIC         197 :         PGresult   *result = NULL;
 3689 kgrittn                  3077 ECB             : 
                               3078                 :         /* Footer information about a view */
 3689 kgrittn                  3079 GIC         197 :         printTableAddFooter(&cont, _("View definition:"));
 3689 kgrittn                  3080 CBC         197 :         printTableAddFooter(&cont, view_def);
                               3081                 : 
 3689 kgrittn                  3082 ECB             :         /* print rules */
 3689 kgrittn                  3083 GIC         197 :         if (tableinfo.hasrules)
                               3084                 :         {
 3689 kgrittn                  3085 CBC         197 :             printfPQExpBuffer(&buf,
 3689 kgrittn                  3086 ECB             :                               "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true))\n"
                               3087                 :                               "FROM pg_catalog.pg_rewrite r\n"
                               3088                 :                               "WHERE r.ev_class = '%s' AND r.rulename != '_RETURN' ORDER BY 1;",
                               3089                 :                               oid);
 3090 fujii                    3090 GIC         197 :             result = PSQLexec(buf.data);
 3689 kgrittn                  3091 CBC         197 :             if (!result)
 3689 kgrittn                  3092 UIC           0 :                 goto error_return;
                               3093                 : 
 3689 kgrittn                  3094 GIC         197 :             if (PQntuples(result) > 0)
                               3095                 :             {
 3689 kgrittn                  3096 CBC           6 :                 printTableAddFooter(&cont, _("Rules:"));
                               3097              12 :                 for (i = 0; i < PQntuples(result); i++)
 3689 kgrittn                  3098 EUB             :                 {
                               3099                 :                     const char *ruledef;
 3689 kgrittn                  3100 ECB             : 
                               3101                 :                     /* Everything after "CREATE RULE" is echoed verbatim */
 3689 kgrittn                  3102 CBC           6 :                     ruledef = PQgetvalue(result, i, 1);
                               3103               6 :                     ruledef += 12;
                               3104                 : 
 3689 kgrittn                  3105 GIC           6 :                     printfPQExpBuffer(&buf, " %s", ruledef);
                               3106               6 :                     printTableAddFooter(&cont, buf.data);
                               3107                 :                 }
 3689 kgrittn                  3108 ECB             :             }
 3689 kgrittn                  3109 CBC         197 :             PQclear(result);
                               3110                 :         }
 3689 kgrittn                  3111 ECB             :     }
                               3112                 : 
                               3113                 :     /*
                               3114                 :      * Print triggers next, if any (but only user-defined triggers).  This
 4564 tgl                      3115                 :      * could apply to either a table or a view.
                               3116                 :      */
 4564 tgl                      3117 GIC        1539 :     if (tableinfo.hastriggers)
                               3118                 :     {
                               3119                 :         PGresult   *result;
                               3120                 :         int         tuples;
                               3121                 : 
 4382 bruce                    3122             108 :         printfPQExpBuffer(&buf,
 4382 bruce                    3123 ECB             :                           "SELECT t.tgname, "
                               3124                 :                           "pg_catalog.pg_get_triggerdef(t.oid, true), "
                               3125                 :                           "t.tgenabled, t.tgisinternal,\n");
                               3126                 : 
                               3127                 :         /*
  447 tgl                      3128                 :          * Detect whether each trigger is inherited, and if so, get the name
                               3129                 :          * of the topmost table it's inherited from.  We have no easy way to
                               3130                 :          * do that pre-v13, for lack of the tgparentid column.  Even with
                               3131                 :          * tgparentid, a straightforward search for the topmost parent would
                               3132                 :          * require a recursive CTE, which seems unduly expensive.  We cheat a
                               3133                 :          * bit by assuming parent triggers will match by tgname; then, joining
                               3134                 :          * with pg_partition_ancestors() allows the planner to make use of
                               3135                 :          * pg_trigger_tgrelid_tgname_index if it wishes.  We ensure we find
                               3136                 :          * the correct topmost parent by stopping at the first-in-partition-
                               3137                 :          * ancestry-order trigger that has tgparentid = 0.  (There might be
                               3138                 :          * unrelated, non-inherited triggers with the same name further up the
                               3139                 :          * stack, so this is important.)
                               3140                 :          */
  447 tgl                      3141 GIC         108 :         if (pset.sversion >= 130000)
                               3142             108 :             appendPQExpBufferStr(&buf,
                               3143                 :                                  "  CASE WHEN t.tgparentid != 0 THEN\n"
                               3144                 :                                  "    (SELECT u.tgrelid::pg_catalog.regclass\n"
                               3145                 :                                  "     FROM pg_catalog.pg_trigger AS u,\n"
                               3146                 :                                  "          pg_catalog.pg_partition_ancestors(t.tgrelid) WITH ORDINALITY AS a(relid, depth)\n"
  447 tgl                      3147 ECB             :                                  "     WHERE u.tgname = t.tgname AND u.tgrelid = a.relid\n"
                               3148                 :                                  "           AND u.tgparentid = 0\n"
                               3149                 :                                  "     ORDER BY a.depth LIMIT 1)\n"
                               3150                 :                                  "  END AS parent\n");
                               3151                 :         else
  447 tgl                      3152 UIC           0 :             appendPQExpBufferStr(&buf, "  NULL AS parent\n");
                               3153                 : 
  447 tgl                      3154 GIC         108 :         appendPQExpBuffer(&buf,
                               3155                 :                           "FROM pg_catalog.pg_trigger t\n"
                               3156                 :                           "WHERE t.tgrelid = '%s' AND ",
                               3157                 :                           oid);
  459 alvherre                 3158 EUB             : 
                               3159                 :         /*
  459 alvherre                 3160 ECB             :          * tgisinternal is set true for inherited triggers of partitions in
                               3161                 :          * servers between v11 and v14, though these must still be shown to
                               3162                 :          * the user.  So we use another property that is true for such
                               3163                 :          * inherited triggers to avoid them being hidden, which is their
                               3164                 :          * dependence on another trigger.
                               3165                 :          */
  459 alvherre                 3166 GIC         108 :         if (pset.sversion >= 110000 && pset.sversion < 150000)
 1375 drowley                  3167 UIC           0 :             appendPQExpBufferStr(&buf, "(NOT t.tgisinternal OR (t.tgisinternal AND t.tgenabled = 'D') \n"
                               3168                 :                                  "    OR EXISTS (SELECT 1 FROM pg_catalog.pg_depend WHERE objid = t.oid \n"
                               3169                 :                                  "        AND refclassid = 'pg_catalog.pg_trigger'::pg_catalog.regclass))");
                               3170                 :         else
                               3171                 :             /* display/warn about disabled internal triggers */
 1375 drowley                  3172 CBC         108 :             appendPQExpBufferStr(&buf, "(NOT t.tgisinternal OR (t.tgisinternal AND t.tgenabled = 'D'))");
 3429 heikki.linnakangas       3173 GBC         108 :         appendPQExpBufferStr(&buf, "\nORDER BY 1;");
                               3174                 : 
 3090 fujii                    3175 GIC         108 :         result = PSQLexec(buf.data);
 4382 bruce                    3176             108 :         if (!result)
 4382 bruce                    3177 UIC           0 :             goto error_return;
 4382 bruce                    3178 ECB             :         else
 4382 bruce                    3179 CBC         108 :             tuples = PQntuples(result);
                               3180                 : 
                               3181             108 :         if (tuples > 0)
 4382 bruce                    3182 ECB             :         {
 4382 bruce                    3183 EUB             :             bool        have_heading;
                               3184                 :             int         category;
 4382 bruce                    3185 ECB             : 
                               3186                 :             /*
                               3187                 :              * split the output into 4 different categories. Enabled triggers,
                               3188                 :              * disabled triggers and the two special ALWAYS and REPLICA
                               3189                 :              * configurations.
                               3190                 :              */
 3331 bruce                    3191 GIC         108 :             for (category = 0; category <= 4; category++)
                               3192                 :             {
 4382                          3193              90 :                 have_heading = false;
                               3194             405 :                 for (i = 0; i < tuples; i++)
                               3195                 :                 {
                               3196                 :                     bool        list_trigger;
 4382 bruce                    3197 ECB             :                     const char *tgdef;
                               3198                 :                     const char *usingpos;
                               3199                 :                     const char *tgenabled;
 3331                          3200                 :                     const char *tgisinternal;
                               3201                 : 
                               3202                 :                     /*
                               3203                 :                      * Check if this trigger falls into the current category
                               3204                 :                      */
 4382 bruce                    3205 GIC         315 :                     tgenabled = PQgetvalue(result, i, 2);
 3331                          3206             315 :                     tgisinternal = PQgetvalue(result, i, 3);
 4382                          3207             315 :                     list_trigger = false;
                               3208             315 :                     switch (category)
                               3209                 :                     {
                               3210              63 :                         case 0:
 4382 bruce                    3211 CBC          63 :                             if (*tgenabled == 'O' || *tgenabled == 't')
                               3212              63 :                                 list_trigger = true;
                               3213              63 :                             break;
                               3214              63 :                         case 1:
 3331 bruce                    3215 GIC          63 :                             if ((*tgenabled == 'D' || *tgenabled == 'f') &&
 3331 bruce                    3216 LBC           0 :                                 *tgisinternal == 'f')
 4382                          3217               0 :                                 list_trigger = true;
 4382 bruce                    3218 CBC          63 :                             break;
                               3219              63 :                         case 2:
 3331                          3220              63 :                             if ((*tgenabled == 'D' || *tgenabled == 'f') &&
 3331 bruce                    3221 LBC           0 :                                 *tgisinternal == 't')
 4382 bruce                    3222 UBC           0 :                                 list_trigger = true;
 4382 bruce                    3223 GBC          63 :                             break;
 4382 bruce                    3224 CBC          63 :                         case 3:
 3331                          3225              63 :                             if (*tgenabled == 'A')
 3331 bruce                    3226 LBC           0 :                                 list_trigger = true;
 3331 bruce                    3227 GBC          63 :                             break;
                               3228              63 :                         case 4:
 4382 bruce                    3229 CBC          63 :                             if (*tgenabled == 'R')
 4382 bruce                    3230 LBC           0 :                                 list_trigger = true;
 4382 bruce                    3231 CBC          63 :                             break;
 4382 bruce                    3232 EUB             :                     }
 4382 bruce                    3233 CBC         315 :                     if (list_trigger == false)
                               3234             252 :                         continue;
 4382 bruce                    3235 ECB             : 
 4382 bruce                    3236 EUB             :                     /* Print the category heading once */
 4382 bruce                    3237 CBC          63 :                     if (have_heading == false)
                               3238                 :                     {
 5865 JanWieck                 3239              18 :                         switch (category)
 5865 JanWieck                 3240 ECB             :                         {
 5865 JanWieck                 3241 GIC          18 :                             case 0:
 4382 bruce                    3242              18 :                                 printfPQExpBuffer(&buf, _("Triggers:"));
 5865 JanWieck                 3243 CBC          18 :                                 break;
 5865 JanWieck                 3244 UIC           0 :                             case 1:
  479 tgl                      3245 LBC           0 :                                 printfPQExpBuffer(&buf, _("Disabled user triggers:"));
 5865 JanWieck                 3246 UIC           0 :                                 break;
 5865 JanWieck                 3247 LBC           0 :                             case 2:
 3260 bruce                    3248               0 :                                 printfPQExpBuffer(&buf, _("Disabled internal triggers:"));
 5865 JanWieck                 3249               0 :                                 break;
 5865 JanWieck                 3250 UBC           0 :                             case 3:
 3331 bruce                    3251               0 :                                 printfPQExpBuffer(&buf, _("Triggers firing always:"));
                               3252               0 :                                 break;
                               3253               0 :                             case 4:
 4382                          3254               0 :                                 printfPQExpBuffer(&buf, _("Triggers firing on replica only:"));
 5865 JanWieck                 3255               0 :                                 break;
 5865 JanWieck                 3256 EUB             :                         }
 5445 alvherre                 3257 GBC          18 :                         printTableAddFooter(&cont, buf.data);
 4382 bruce                    3258              18 :                         have_heading = true;
 5445 alvherre                 3259 EUB             :                     }
 4382 bruce                    3260                 : 
                               3261                 :                     /* Everything after "TRIGGER" is echoed verbatim */
 4382 bruce                    3262 GIC          63 :                     tgdef = PQgetvalue(result, i, 1);
 4382 bruce                    3263 CBC          63 :                     usingpos = strstr(tgdef, " TRIGGER ");
                               3264              63 :                     if (usingpos)
 4382 bruce                    3265 GIC          63 :                         tgdef = usingpos + 9;
                               3266                 : 
                               3267              63 :                     printfPQExpBuffer(&buf, "    %s", tgdef);
 1083 alvherre                 3268 ECB             : 
                               3269                 :                     /* Visually distinguish inherited triggers */
 1083 alvherre                 3270 CBC          63 :                     if (!PQgetisnull(result, i, 4))
                               3271               6 :                         appendPQExpBuffer(&buf, ", ON TABLE %s",
                               3272                 :                                           PQgetvalue(result, i, 4));
 1083 alvherre                 3273 ECB             : 
 4382 bruce                    3274 GIC          63 :                     printTableAddFooter(&cont, buf.data);
                               3275                 :                 }
 5923 neilc                    3276 ECB             :             }
 4382 bruce                    3277                 :         }
 4382 bruce                    3278 GIC         108 :         PQclear(result);
                               3279                 :     }
 4564 tgl                      3280 ECB             : 
                               3281                 :     /*
                               3282                 :      * Finish printing the footer information about a table.
                               3283                 :      */
 2222 tgl                      3284 CBC        1539 :     if (tableinfo.relkind == RELKIND_RELATION ||
 2222 tgl                      3285 GIC         653 :         tableinfo.relkind == RELKIND_MATVIEW ||
                               3286             623 :         tableinfo.relkind == RELKIND_FOREIGN_TABLE ||
 1356                          3287             530 :         tableinfo.relkind == RELKIND_PARTITIONED_TABLE ||
                               3288             413 :         tableinfo.relkind == RELKIND_PARTITIONED_INDEX ||
                               3289             347 :         tableinfo.relkind == RELKIND_TOASTVALUE)
 4564 tgl                      3290 ECB             :     {
 1356                          3291                 :         bool        is_partitioned;
 4564                          3292                 :         PGresult   *result;
                               3293                 :         int         tuples;
 5923 neilc                    3294                 : 
 1356 tgl                      3295                 :         /* simplify some repeated tests below */
 1356 tgl                      3296 GIC        2273 :         is_partitioned = (tableinfo.relkind == RELKIND_PARTITIONED_TABLE ||
                               3297            1078 :                           tableinfo.relkind == RELKIND_PARTITIONED_INDEX);
                               3298                 : 
                               3299                 :         /* print foreign server name */
 2222                          3300            1195 :         if (tableinfo.relkind == RELKIND_FOREIGN_TABLE)
                               3301                 :         {
 3955 bruce                    3302 ECB             :             char       *ftoptions;
 4259 rhaas                    3303                 : 
                               3304                 :             /* Footer information about foreign table */
 4481 rhaas                    3305 GIC          93 :             printfPQExpBuffer(&buf,
 4259 rhaas                    3306 ECB             :                               "SELECT s.srvname,\n"
                               3307                 :                               "  pg_catalog.array_to_string(ARRAY(\n"
                               3308                 :                               "    SELECT pg_catalog.quote_ident(option_name)"
                               3309                 :                               " || ' ' || pg_catalog.quote_literal(option_value)\n"
                               3310                 :                               "    FROM pg_catalog.pg_options_to_table(ftoptions)),  ', ')\n"
 4481                          3311                 :                               "FROM pg_catalog.pg_foreign_table f,\n"
                               3312                 :                               "     pg_catalog.pg_foreign_server s\n"
                               3313                 :                               "WHERE f.ftrelid = '%s' AND s.oid = f.ftserver;",
                               3314                 :                               oid);
 3090 fujii                    3315 GIC          93 :             result = PSQLexec(buf.data);
 4481 rhaas                    3316              93 :             if (!result)
 4481 rhaas                    3317 UIC           0 :                 goto error_return;
 4481 rhaas                    3318 GIC          93 :             else if (PQntuples(result) != 1)
                               3319                 :             {
 4481 rhaas                    3320 UIC           0 :                 PQclear(result);
 4481 rhaas                    3321 LBC           0 :                 goto error_return;
 4481 rhaas                    3322 ECB             :             }
 4481 rhaas                    3323 EUB             : 
 4259 rhaas                    3324 ECB             :             /* Print server name */
 2160 peter_e                  3325 GIC          93 :             printfPQExpBuffer(&buf, _("Server: %s"),
 4382 bruce                    3326 EUB             :                               PQgetvalue(result, 0, 0));
 4481 rhaas                    3327 GBC          93 :             printTableAddFooter(&cont, buf.data);
                               3328                 : 
                               3329                 :             /* Print per-table FDW options, if any */
 4259 rhaas                    3330 GIC          93 :             ftoptions = PQgetvalue(result, 0, 1);
 4259 rhaas                    3331 CBC          93 :             if (ftoptions && ftoptions[0] != '\0')
                               3332                 :             {
 2126 peter_e                  3333              87 :                 printfPQExpBuffer(&buf, _("FDW options: (%s)"), ftoptions);
 4259 rhaas                    3334 GIC          87 :                 printTableAddFooter(&cont, buf.data);
                               3335                 :             }
 4481 rhaas                    3336 CBC          93 :             PQclear(result);
 4481 rhaas                    3337 ECB             :         }
                               3338                 : 
 1356 tgl                      3339                 :         /* print tables inherited from (exclude partitioned parents) */
 2314 rhaas                    3340 CBC        1195 :         printfPQExpBuffer(&buf,
                               3341                 :                           "SELECT c.oid::pg_catalog.regclass\n"
 1356 tgl                      3342 ECB             :                           "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
                               3343                 :                           "WHERE c.oid = i.inhparent AND i.inhrelid = '%s'\n"
                               3344                 :                           "  AND c.relkind != " CppAsString2(RELKIND_PARTITIONED_TABLE)
                               3345                 :                           " AND c.relkind != " CppAsString2(RELKIND_PARTITIONED_INDEX)
                               3346                 :                           "\nORDER BY inhseqno;",
                               3347                 :                           oid);
                               3348                 : 
 3090 fujii                    3349 GIC        1195 :         result = PSQLexec(buf.data);
 5445 alvherre                 3350            1195 :         if (!result)
 5445 alvherre                 3351 UIC           0 :             goto error_return;
                               3352                 :         else
                               3353                 :         {
 5624 bruce                    3354 GIC        1195 :             const char *s = _("Inherits");
 4050 tgl                      3355 CBC        1195 :             int         sw = pg_wcswidth(s, strlen(s), pset.encoding);
 7198 bruce                    3356 ECB             : 
 4050 tgl                      3357 GBC        1195 :             tuples = PQntuples(result);
                               3358                 : 
 4050 tgl                      3359 GIC        1414 :             for (i = 0; i < tuples; i++)
 4050 tgl                      3360 ECB             :             {
 4050 tgl                      3361 CBC         219 :                 if (i == 0)
 4050 tgl                      3362 GIC         180 :                     printfPQExpBuffer(&buf, "%s: %s",
 4050 tgl                      3363 ECB             :                                       s, PQgetvalue(result, i, 0));
                               3364                 :                 else
 4050 tgl                      3365 CBC          39 :                     printfPQExpBuffer(&buf, "%*s  %s",
                               3366                 :                                       sw, "", PQgetvalue(result, i, 0));
                               3367             219 :                 if (i < tuples - 1)
 2838 heikki.linnakangas       3368              39 :                     appendPQExpBufferChar(&buf, ',');
                               3369                 : 
 4050 tgl                      3370 GIC         219 :                 printTableAddFooter(&cont, buf.data);
 4050 tgl                      3371 ECB             :             }
                               3372                 : 
 4050 tgl                      3373 CBC        1195 :             PQclear(result);
 7198 bruce                    3374 ECB             :         }
                               3375                 : 
 2314 rhaas                    3376                 :         /* print child tables (with additional info if partitions) */
  745 alvherre                 3377 GIC        1195 :         if (pset.sversion >= 140000)
                               3378            1195 :             printfPQExpBuffer(&buf,
  745 alvherre                 3379 ECB             :                               "SELECT c.oid::pg_catalog.regclass, c.relkind,"
                               3380                 :                               " inhdetachpending,"
                               3381                 :                               " pg_catalog.pg_get_expr(c.relpartbound, c.oid)\n"
                               3382                 :                               "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
                               3383                 :                               "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n"
                               3384                 :                               "ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT',"
                               3385                 :                               " c.oid::pg_catalog.regclass::pg_catalog.text;",
                               3386                 :                               oid);
  745 alvherre                 3387 UIC           0 :         else if (pset.sversion >= 100000)
 2314 rhaas                    3388               0 :             printfPQExpBuffer(&buf,
                               3389                 :                               "SELECT c.oid::pg_catalog.regclass, c.relkind,"
                               3390                 :                               " false AS inhdetachpending,"
                               3391                 :                               " pg_catalog.pg_get_expr(c.relpartbound, c.oid)\n"
                               3392                 :                               "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
 1356 tgl                      3393 EUB             :                               "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n"
                               3394                 :                               "ORDER BY pg_catalog.pg_get_expr(c.relpartbound, c.oid) = 'DEFAULT',"
                               3395                 :                               " c.oid::pg_catalog.regclass::pg_catalog.text;",
                               3396                 :                               oid);
                               3397                 :         else
 2083 tgl                      3398 UIC           0 :             printfPQExpBuffer(&buf,
                               3399                 :                               "SELECT c.oid::pg_catalog.regclass, c.relkind,"
                               3400                 :                               " false AS inhdetachpending, NULL\n"
                               3401                 :                               "FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i\n"
                               3402                 :                               "WHERE c.oid = i.inhrelid AND i.inhparent = '%s'\n"
                               3403                 :                               "ORDER BY c.oid::pg_catalog.regclass::pg_catalog.text;",
 1356 tgl                      3404 EUB             :                               oid);
                               3405                 : 
 3090 fujii                    3406 GIC        1195 :         result = PSQLexec(buf.data);
 5028 peter_e                  3407            1195 :         if (!result)
 5028 peter_e                  3408 UIC           0 :             goto error_return;
 1356 tgl                      3409 GIC        1195 :         tuples = PQntuples(result);
                               3410                 : 
                               3411                 :         /*
 1963 simon                    3412 ECB             :          * For a partitioned table with no partitions, always print the number
                               3413                 :          * of partitions as zero, even when verbose output is expected.
 1963 simon                    3414 EUB             :          * Otherwise, we will not print "Partitions" section for a partitioned
 1963 simon                    3415 ECB             :          * table without any partitions.
                               3416                 :          */
 1356 tgl                      3417 GIC        1195 :         if (is_partitioned && tuples == 0)
                               3418                 :         {
 1963 simon                    3419              33 :             printfPQExpBuffer(&buf, _("Number of partitions: %d"), tuples);
                               3420              33 :             printTableAddFooter(&cont, buf.data);
                               3421                 :         }
                               3422            1162 :         else if (!verbose)
 5028 peter_e                  3423 ECB             :         {
                               3424                 :             /* print the number of child tables, if any */
 5028 peter_e                  3425 CBC         750 :             if (tuples > 0)
 5028 peter_e                  3426 ECB             :             {
 1356 tgl                      3427 GIC         177 :                 if (is_partitioned)
 2314 rhaas                    3428 CBC         111 :                     printfPQExpBuffer(&buf, _("Number of partitions: %d (Use \\d+ to list them.)"), tuples);
                               3429                 :                 else
 1356 tgl                      3430 GIC          66 :                     printfPQExpBuffer(&buf, _("Number of child tables: %d (Use \\d+ to list them.)"), tuples);
 5028 peter_e                  3431 CBC         177 :                 printTableAddFooter(&cont, buf.data);
                               3432                 :             }
 5028 peter_e                  3433 ECB             :         }
                               3434                 :         else
                               3435                 :         {
 5024 tgl                      3436                 :             /* display the list of child tables */
 1356 tgl                      3437 CBC         412 :             const char *ct = is_partitioned ? _("Partitions") : _("Child tables");
 4050 tgl                      3438 GIC         412 :             int         ctw = pg_wcswidth(ct, strlen(ct), pset.encoding);
                               3439                 : 
 5028 peter_e                  3440             592 :             for (i = 0; i < tuples; i++)
                               3441                 :             {
 1356 tgl                      3442             180 :                 char        child_relkind = *PQgetvalue(result, i, 1);
 1963 simon                    3443 ECB             : 
 1356 tgl                      3444 CBC         180 :                 if (i == 0)
 1356 tgl                      3445 GIC         102 :                     printfPQExpBuffer(&buf, "%s: %s",
 1356 tgl                      3446 ECB             :                                       ct, PQgetvalue(result, i, 0));
                               3447                 :                 else
 1356 tgl                      3448 CBC          78 :                     printfPQExpBuffer(&buf, "%*s  %s",
                               3449                 :                                       ctw, "", PQgetvalue(result, i, 0));
  745 alvherre                 3450             180 :                 if (!PQgetisnull(result, i, 3))
                               3451              96 :                     appendPQExpBuffer(&buf, " %s", PQgetvalue(result, i, 3));
 1356 tgl                      3452 GIC         180 :                 if (child_relkind == RELKIND_PARTITIONED_TABLE ||
                               3453                 :                     child_relkind == RELKIND_PARTITIONED_INDEX)
 1356 tgl                      3454 CBC          12 :                     appendPQExpBufferStr(&buf, ", PARTITIONED");
  152 michael                  3455 GNC         168 :                 else if (child_relkind == RELKIND_FOREIGN_TABLE)
                               3456              54 :                     appendPQExpBufferStr(&buf, ", FOREIGN");
  745 alvherre                 3457 GIC         180 :                 if (strcmp(PQgetvalue(result, i, 2), "t") == 0)
  675 drowley                  3458 LBC           0 :                     appendPQExpBufferStr(&buf, " (DETACH PENDING)");
 5024 tgl                      3459 CBC         180 :                 if (i < tuples - 1)
 3429 heikki.linnakangas       3460              78 :                     appendPQExpBufferChar(&buf, ',');
                               3461                 : 
 5024 tgl                      3462             180 :                 printTableAddFooter(&cont, buf.data);
 5024 tgl                      3463 ECB             :             }
 5028 peter_e                  3464                 :         }
 5028 peter_e                  3465 CBC        1195 :         PQclear(result);
 5028 peter_e                  3466 EUB             : 
 4819 peter_e                  3467 ECB             :         /* Table type */
 4819 peter_e                  3468 CBC        1195 :         if (tableinfo.reloftype)
                               3469                 :         {
                               3470              30 :             printfPQExpBuffer(&buf, _("Typed table of type: %s"), tableinfo.reloftype);
 4819 peter_e                  3471 GIC          30 :             printTableAddFooter(&cont, buf.data);
                               3472                 :         }
 4819 peter_e                  3473 ECB             : 
 2222 tgl                      3474 GIC        1195 :         if (verbose &&
                               3475             430 :             (tableinfo.relkind == RELKIND_RELATION ||
 2222 tgl                      3476 CBC         156 :              tableinfo.relkind == RELKIND_MATVIEW) &&
                               3477                 : 
 3260 bruce                    3478 ECB             :         /*
 2222 tgl                      3479                 :          * No need to display default values; we already display a REPLICA
                               3480                 :          * IDENTITY marker on indexes.
                               3481                 :          */
 3281 bruce                    3482 CBC         304 :             tableinfo.relreplident != 'i' &&
                               3483             301 :             ((strcmp(schemaname, "pg_catalog") != 0 && tableinfo.relreplident != 'd') ||
                               3484             298 :              (strcmp(schemaname, "pg_catalog") == 0 && tableinfo.relreplident != 'n')))
                               3485                 :         {
 3439 rhaas                    3486 GIC           3 :             const char *s = _("Replica Identity");
                               3487                 : 
                               3488               3 :             printfPQExpBuffer(&buf, "%s: %s",
                               3489                 :                               s,
 3301 bruce                    3490 CBC           3 :                               tableinfo.relreplident == 'f' ? "FULL" :
 3301 bruce                    3491 LBC           0 :                               tableinfo.relreplident == 'n' ? "NOTHING" :
 3301 bruce                    3492 ECB             :                               "???");
                               3493                 : 
 3439 rhaas                    3494 CBC           3 :             printTableAddFooter(&cont, buf.data);
                               3495                 :         }
 3439 rhaas                    3496 ECB             : 
                               3497                 :         /* OIDs, if verbose and not a materialized view */
 2222 tgl                      3498 CBC        1195 :         if (verbose && tableinfo.relkind != RELKIND_MATVIEW && tableinfo.hasoids)
 3281 bruce                    3499 UBC           0 :             printTableAddFooter(&cont, _("Has OIDs: yes"));
                               3500                 : 
                               3501                 :         /* Tablespace info */
 5445 alvherre                 3502 CBC        1195 :         add_tablespace_footer(&cont, tableinfo.relkind, tableinfo.tablespace,
                               3503                 :                               true);
                               3504                 : 
                               3505                 :         /* Access method info */
 1495 andres                   3506            1195 :         if (verbose && tableinfo.relam != NULL && !pset.hide_tableam)
 1495 andres                   3507 EUB             :         {
 1495 andres                   3508 GIC           6 :             printfPQExpBuffer(&buf, _("Access method: %s"), tableinfo.relam);
                               3509               6 :             printTableAddFooter(&cont, buf.data);
 1495 andres                   3510 ECB             :         }
                               3511                 :     }
                               3512                 : 
                               3513                 :     /* reloptions, if verbose */
 3870 tgl                      3514 CBC        1539 :     if (verbose &&
 3870 tgl                      3515 GIC         614 :         tableinfo.reloptions && tableinfo.reloptions[0] != '\0')
 3870 tgl                      3516 ECB             :     {
 3870 tgl                      3517 CBC          17 :         const char *t = _("Options");
                               3518                 : 
 3870 tgl                      3519 GIC          17 :         printfPQExpBuffer(&buf, "%s: %s", t, tableinfo.reloptions);
                               3520              17 :         printTableAddFooter(&cont, buf.data);
                               3521                 :     }
 3870 tgl                      3522 ECB             : 
 2685 tgl                      3523 CBC        1539 :     printTable(&cont, pset.queryFout, false, pset.logfile);
                               3524                 : 
 7655 peter_e                  3525            1539 :     retval = true;
                               3526                 : 
                               3527            1620 : error_return:
 8557 bruce                    3528 ECB             : 
                               3529                 :     /* clean up */
 5270 tgl                      3530 GIC        1620 :     if (printTableInitialized)
 5270 tgl                      3531 CBC        1539 :         printTableCleanup(&cont);
 7655 peter_e                  3532 GIC        1620 :     termPQExpBuffer(&buf);
 7655 peter_e                  3533 CBC        1620 :     termPQExpBuffer(&title);
 7414 tgl                      3534 GIC        1620 :     termPQExpBuffer(&tmpbuf);
 5050 bruce                    3535 ECB             : 
  297 peter                    3536 GNC        1620 :     free(view_def);
 7547 tgl                      3537 ECB             : 
  280 peter                    3538 GNC        1620 :     PQclear(res);
 8557 bruce                    3539 ECB             : 
 7655 peter_e                  3540 CBC        1620 :     return retval;
                               3541                 : }
 8557 bruce                    3542 ECB             : 
                               3543                 : /*
 5445 alvherre                 3544                 :  * Add a tablespace description to a footer.  If 'newline' is true, it is added
                               3545                 :  * in a new line; otherwise it's appended to the current value of the last
                               3546                 :  * footer.
                               3547                 :  */
                               3548                 : static void
 5445 alvherre                 3549 GIC        1948 : add_tablespace_footer(printTableContent *const cont, char relkind,
                               3550                 :                       Oid tablespace, const bool newline)
                               3551                 : {
                               3552                 :     /* relkinds for which we support tablespaces */
 2222 tgl                      3553            1948 :     if (relkind == RELKIND_RELATION ||
                               3554            1032 :         relkind == RELKIND_MATVIEW ||
 2222 tgl                      3555 CBC         279 :         relkind == RELKIND_INDEX ||
 1453 alvherre                 3556 GIC         162 :         relkind == RELKIND_PARTITIONED_TABLE ||
 1356 tgl                      3557              96 :         relkind == RELKIND_PARTITIONED_INDEX ||
                               3558                 :         relkind == RELKIND_TOASTVALUE)
 6845 bruce                    3559 ECB             :     {
                               3560                 :         /*
 6385                          3561                 :          * We ignore the database default tablespace so that users not using
  479 tgl                      3562                 :          * tablespaces don't need to know about them.
 6845 bruce                    3563                 :          */
 6797 bruce                    3564 GIC        1855 :         if (tablespace != 0)
                               3565                 :         {
 5445 alvherre                 3566             102 :             PGresult   *result = NULL;
                               3567                 :             PQExpBufferData buf;
                               3568                 : 
                               3569             102 :             initPQExpBuffer(&buf);
 5393 tgl                      3570 CBC         102 :             printfPQExpBuffer(&buf,
                               3571                 :                               "SELECT spcname FROM pg_catalog.pg_tablespace\n"
 4295 rhaas                    3572 ECB             :                               "WHERE oid = '%u';", tablespace);
 3090 fujii                    3573 GIC         102 :             result = PSQLexec(buf.data);
 5445 alvherre                 3574             102 :             if (!result)
 2082 tgl                      3575 ECB             :             {
 2082 tgl                      3576 LBC           0 :                 termPQExpBuffer(&buf);
 5445 alvherre                 3577 UIC           0 :                 return;
                               3578                 :             }
 6845 bruce                    3579 ECB             :             /* Should always be the case, but.... */
 5445 alvherre                 3580 CBC         102 :             if (PQntuples(result) > 0)
                               3581                 :             {
 5445 alvherre                 3582 GBC         102 :                 if (newline)
 5445 alvherre                 3583 EUB             :                 {
                               3584                 :                     /* Add the tablespace as a new footer */
 5445 alvherre                 3585 GIC          87 :                     printfPQExpBuffer(&buf, _("Tablespace: \"%s\""),
 5445 alvherre                 3586 ECB             :                                       PQgetvalue(result, 0, 0));
 5445 alvherre                 3587 GIC          87 :                     printTableAddFooter(cont, buf.data);
 5445 alvherre                 3588 ECB             :                 }
                               3589                 :                 else
                               3590                 :                 {
                               3591                 :                     /* Append the tablespace to the latest footer */
 5445 alvherre                 3592 GIC          15 :                     printfPQExpBuffer(&buf, "%s", cont->footer->data);
 5050 bruce                    3593 ECB             : 
                               3594                 :                     /*-------
                               3595                 :                        translator: before this string there's an index description like
                               3596                 :                        '"foo_pkey" PRIMARY KEY, btree (a)' */
 5445 alvherre                 3597 GIC          15 :                     appendPQExpBuffer(&buf, _(", tablespace \"%s\""),
 5445 alvherre                 3598 ECB             :                                       PQgetvalue(result, 0, 0));
 5445 alvherre                 3599 GIC          15 :                     printTableSetFooter(cont, buf.data);
                               3600                 :                 }
                               3601                 :             }
                               3602             102 :             PQclear(result);
 5445 alvherre                 3603 CBC         102 :             termPQExpBuffer(&buf);
                               3604                 :         }
 6845 bruce                    3605 ECB             :     }
                               3606                 : }
                               3607                 : 
 8005                          3608                 : /*
 6447 tgl                      3609                 :  * \du or \dg
                               3610                 :  *
                               3611                 :  * Describes roles.  Any schema portion of the pattern is ignored.
                               3612                 :  */
                               3613                 : bool
 2557 sfrost                   3614 GIC          12 : describeRoles(const char *pattern, bool verbose, bool showSystem)
                               3615                 : {
                               3616                 :     PQExpBufferData buf;
                               3617                 :     PGresult   *res;
                               3618                 :     printTableContent cont;
 5444 alvherre                 3619              12 :     printTableOpt myopt = pset.popt.topt;
 5444 alvherre                 3620 CBC          12 :     int         ncols = 3;
 5444 alvherre                 3621 GIC          12 :     int         nrows = 0;
                               3622                 :     int         i;
                               3623                 :     int         conns;
                               3624              12 :     const char  align = 'l';
 5444 alvherre                 3625 ECB             :     char      **attr;
 7836 bruce                    3626                 : 
 3995 rhaas                    3627 CBC          12 :     myopt.default_footer = false;
                               3628                 : 
 7655 peter_e                  3629 GIC          12 :     initPQExpBuffer(&buf);
 7655 peter_e                  3630 ECB             : 
  479 tgl                      3631 GIC          12 :     printfPQExpBuffer(&buf,
                               3632                 :                       "SELECT r.rolname, r.rolsuper, r.rolinherit,\n"
  479 tgl                      3633 ECB             :                       "  r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,\n"
                               3634                 :                       "  r.rolconnlimit, r.rolvaliduntil,\n"
                               3635                 :                       "  ARRAY(SELECT b.rolname\n"
                               3636                 :                       "        FROM pg_catalog.pg_auth_members m\n"
                               3637                 :                       "        JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)\n"
                               3638                 :                       "        WHERE m.member = r.oid) as memberof");
                               3639                 : 
  479 tgl                      3640 GIC          12 :     if (verbose)
                               3641                 :     {
  479 tgl                      3642 UIC           0 :         appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description");
                               3643               0 :         ncols++;
                               3644                 :     }
  479 tgl                      3645 GIC          12 :     appendPQExpBufferStr(&buf, "\n, r.rolreplication");
 3124 sfrost                   3646 ECB             : 
  479 tgl                      3647 GIC          12 :     if (pset.sversion >= 90500)
  479 tgl                      3648 EUB             :     {
  479 tgl                      3649 GBC          12 :         appendPQExpBufferStr(&buf, "\n, r.rolbypassrls");
                               3650                 :     }
 5393 tgl                      3651 ECB             : 
  479 tgl                      3652 GIC          12 :     appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_roles r\n");
 2557 sfrost                   3653 ECB             : 
  479 tgl                      3654 GIC          12 :     if (!showSystem && !pattern)
  479 tgl                      3655 LBC           0 :         appendPQExpBufferStr(&buf, "WHERE r.rolname !~ '^pg_'\n");
                               3656                 : 
  354 rhaas                    3657 GIC          12 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
  354 rhaas                    3658 ECB             :                                 NULL, "r.rolname", NULL, NULL,
                               3659                 :                                 NULL, 1))
  262 michael                  3660                 :     {
  262 michael                  3661 GBC           9 :         termPQExpBuffer(&buf);
  354 rhaas                    3662 GIC           9 :         return false;
  262 michael                  3663 ECB             :     }
                               3664                 : 
 3429 heikki.linnakangas       3665 GIC           3 :     appendPQExpBufferStr(&buf, "ORDER BY 1;");
                               3666                 : 
 3090 fujii                    3667 CBC           3 :     res = PSQLexec(buf.data);
 7069 bruce                    3668               3 :     if (!res)
 7069 bruce                    3669 UIC           0 :         return false;
                               3670                 : 
 5444 alvherre                 3671 CBC           3 :     nrows = PQntuples(res);
 3841 tgl                      3672 GIC           3 :     attr = pg_malloc0((nrows + 1) * sizeof(*attr));
 7069 bruce                    3673 ECB             : 
 5444 alvherre                 3674 CBC           3 :     printTableInit(&cont, &myopt, _("List of roles"), ncols, nrows);
 5444 alvherre                 3675 EUB             : 
 5444 alvherre                 3676 GIC           3 :     printTableAddHeader(&cont, gettext_noop("Role name"), true, align);
 5444 alvherre                 3677 CBC           3 :     printTableAddHeader(&cont, gettext_noop("Attributes"), true, align);
  744 noah                     3678 ECB             :     /* ignores implicit memberships from superuser & pg_database_owner */
 5444 alvherre                 3679 GIC           3 :     printTableAddHeader(&cont, gettext_noop("Member of"), true, align);
 5444 alvherre                 3680 ECB             : 
  479 tgl                      3681 GIC           3 :     if (verbose)
 5444 alvherre                 3682 LBC           0 :         printTableAddHeader(&cont, gettext_noop("Description"), true, align);
 5444 alvherre                 3683 ECB             : 
 5444 alvherre                 3684 GIC           3 :     for (i = 0; i < nrows; i++)
 5444 alvherre                 3685 ECB             :     {
 4787 heikki.linnakangas       3686 UIC           0 :         printTableAddCell(&cont, PQgetvalue(res, i, 0), false, false);
 5444 alvherre                 3687 ECB             : 
 5444 alvherre                 3688 UBC           0 :         resetPQExpBuffer(&buf);
 5444 alvherre                 3689 UIC           0 :         if (strcmp(PQgetvalue(res, i, 1), "t") == 0)
 5444 alvherre                 3690 LBC           0 :             add_role_attribute(&buf, _("Superuser"));
                               3691                 : 
 5444 alvherre                 3692 UBC           0 :         if (strcmp(PQgetvalue(res, i, 2), "t") != 0)
 5444 alvherre                 3693 UIC           0 :             add_role_attribute(&buf, _("No inheritance"));
 5444 alvherre                 3694 EUB             : 
 5444 alvherre                 3695 UBC           0 :         if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
                               3696               0 :             add_role_attribute(&buf, _("Create role"));
                               3697                 : 
                               3698               0 :         if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
                               3699               0 :             add_role_attribute(&buf, _("Create DB"));
                               3700                 : 
                               3701               0 :         if (strcmp(PQgetvalue(res, i, 5), "t") != 0)
                               3702               0 :             add_role_attribute(&buf, _("Cannot login"));
                               3703                 : 
  479 tgl                      3704               0 :         if (strcmp(PQgetvalue(res, i, (verbose ? 10 : 9)), "t") == 0)
                               3705               0 :             add_role_attribute(&buf, _("Replication"));
                               3706                 : 
 3119 sfrost                   3707               0 :         if (pset.sversion >= 90500)
                               3708               0 :             if (strcmp(PQgetvalue(res, i, (verbose ? 11 : 10)), "t") == 0)
 3119 sfrost                   3709 UIC           0 :                 add_role_attribute(&buf, _("Bypass RLS"));
 3119 sfrost                   3710 EUB             : 
 5444 alvherre                 3711 UBC           0 :         conns = atoi(PQgetvalue(res, i, 6));
 5444 alvherre                 3712 UIC           0 :         if (conns >= 0)
 5444 alvherre                 3713 EUB             :         {
 5444 alvherre                 3714 UBC           0 :             if (buf.len > 0)
 3429 heikki.linnakangas       3715               0 :                 appendPQExpBufferChar(&buf, '\n');
                               3716                 : 
 5444 alvherre                 3717               0 :             if (conns == 0)
 3429 heikki.linnakangas       3718               0 :                 appendPQExpBufferStr(&buf, _("No connections"));
                               3719                 :             else
 5057 tgl                      3720               0 :                 appendPQExpBuffer(&buf, ngettext("%d connection",
 5057 tgl                      3721 EUB             :                                                  "%d connections",
                               3722                 :                                                  conns),
                               3723                 :                                   conns);
 5444 alvherre                 3724                 :         }
                               3725                 : 
 4035 tgl                      3726 UBC           0 :         if (strcmp(PQgetvalue(res, i, 7), "") != 0)
                               3727                 :         {
 4035 tgl                      3728 UIC           0 :             if (buf.len > 0)
 2063 peter_e                  3729               0 :                 appendPQExpBufferChar(&buf, '\n');
 4035 tgl                      3730               0 :             appendPQExpBufferStr(&buf, _("Password valid until "));
                               3731               0 :             appendPQExpBufferStr(&buf, PQgetvalue(res, i, 7));
 4035 tgl                      3732 EUB             :         }
                               3733                 : 
 5444 alvherre                 3734 UBC           0 :         attr[i] = pg_strdup(buf.data);
 5444 alvherre                 3735 EUB             : 
 4787 heikki.linnakangas       3736 UBC           0 :         printTableAddCell(&cont, attr[i], false, false);
 5444 alvherre                 3737 EUB             : 
 4035 tgl                      3738 UIC           0 :         printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
                               3739                 : 
  479 tgl                      3740 UBC           0 :         if (verbose)
 4035 tgl                      3741 UIC           0 :             printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false);
 5444 alvherre                 3742 EUB             :     }
 5444 alvherre                 3743 GIC           3 :     termPQExpBuffer(&buf);
 5444 alvherre                 3744 EUB             : 
 2685 tgl                      3745 GIC           3 :     printTable(&cont, pset.queryFout, false, pset.logfile);
 5444 alvherre                 3746 GBC           3 :     printTableCleanup(&cont);
 5444 alvherre                 3747 EUB             : 
 5444 alvherre                 3748 GIC           3 :     for (i = 0; i < nrows; i++)
 5444 alvherre                 3749 LBC           0 :         free(attr[i]);
 5444 alvherre                 3750 GIC           3 :     free(attr);
 7069 bruce                    3751 ECB             : 
 7069 bruce                    3752 CBC           3 :     PQclear(res);
 7069 bruce                    3753 GIC           3 :     return true;
 7069 bruce                    3754 ECB             : }
 7069 bruce                    3755 EUB             : 
 5049 tgl                      3756 ECB             : static void
 5444 alvherre                 3757 UIC           0 : add_role_attribute(PQExpBuffer buf, const char *const str)
 5444 alvherre                 3758 ECB             : {
 5444 alvherre                 3759 LBC           0 :     if (buf->len > 0)
 4897 peter_e                  3760 UIC           0 :         appendPQExpBufferStr(buf, ", ");
                               3761                 : 
 5444 alvherre                 3762               0 :     appendPQExpBufferStr(buf, str);
 5444 alvherre                 3763 UBC           0 : }
                               3764                 : 
 4932 alvherre                 3765 EUB             : /*
                               3766                 :  * \drds
                               3767                 :  */
                               3768                 : bool
 4932 alvherre                 3769 GBC          15 : listDbRoleSettings(const char *pattern, const char *pattern2)
                               3770                 : {
                               3771                 :     PQExpBufferData buf;
                               3772                 :     PGresult   *res;
 4932 alvherre                 3773 GIC          15 :     printQueryOpt myopt = pset.popt;
                               3774                 :     bool        havewhere;
 4932 alvherre                 3775 ECB             : 
 2082 tgl                      3776 GIC          15 :     initPQExpBuffer(&buf);
                               3777                 : 
                               3778              15 :     printfPQExpBuffer(&buf, "SELECT rolname AS \"%s\", datname AS \"%s\",\n"
                               3779                 :                       "pg_catalog.array_to_string(setconfig, E'\\n') AS \"%s\"",
                               3780                 :                       gettext_noop("Role"),
 2082 tgl                      3781 ECB             :                       gettext_noop("Database"),
                               3782                 :                       gettext_noop("Settings"));
  121 akorotkov                3783 GNC          15 :     if (pset.sversion >= 160000)
                               3784              15 :         appendPQExpBuffer(&buf, ",\npg_catalog.array_to_string(setuser, E'\\n') AS \"%s\"",
                               3785                 :                           gettext_noop("User set"));
                               3786              15 :     appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_db_role_setting s\n"
                               3787                 :                       "LEFT JOIN pg_catalog.pg_database d ON d.oid = setdatabase\n"
                               3788                 :                       "LEFT JOIN pg_catalog.pg_roles r ON r.oid = setrole\n");
  354 rhaas                    3789 GIC          15 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                               3790                 :                                 NULL, "r.rolname", NULL, NULL, &havewhere, 1))
  262 michael                  3791               9 :         goto error_return;
  354 rhaas                    3792 CBC           6 :     if (!validateSQLNamePattern(&buf, pattern2, havewhere, false,
  354 rhaas                    3793 ECB             :                                 NULL, "d.datname", NULL, NULL,
                               3794                 :                                 NULL, 1))
  262 michael                  3795 LBC           0 :         goto error_return;
 2082 tgl                      3796 GIC           6 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
                               3797                 : 
 3090 fujii                    3798 CBC           6 :     res = PSQLexec(buf.data);
 2082 tgl                      3799 GIC           6 :     termPQExpBuffer(&buf);
 4932 alvherre                 3800 CBC           6 :     if (!res)
 4932 alvherre                 3801 LBC           0 :         return false;
                               3802                 : 
                               3803                 :     /*
 2082 tgl                      3804 EUB             :      * Most functions in this file are content to print an empty table when
 2082 tgl                      3805 ECB             :      * there are no matching objects.  We intentionally deviate from that
                               3806                 :      * here, but only in !quiet mode, because of the possibility that the user
                               3807                 :      * is confused about what the two pattern arguments mean.
                               3808                 :      */
 4932 alvherre                 3809 CBC           6 :     if (PQntuples(res) == 0 && !pset.quiet)
 4932 alvherre                 3810 EUB             :     {
 2082 tgl                      3811 UIC           0 :         if (pattern && pattern2)
 1469 peter                    3812               0 :             pg_log_error("Did not find any settings for role \"%s\" and database \"%s\".",
                               3813                 :                          pattern, pattern2);
 2082 tgl                      3814               0 :         else if (pattern)
 1469 peter                    3815               0 :             pg_log_error("Did not find any settings for role \"%s\".",
                               3816                 :                          pattern);
                               3817                 :         else
 1469 peter                    3818 LBC           0 :             pg_log_error("Did not find any settings.");
                               3819                 :     }
 4932 alvherre                 3820 EUB             :     else
                               3821                 :     {
 4932 alvherre                 3822 GIC           6 :         myopt.nullPrint = NULL;
 4932 alvherre                 3823 GBC           6 :         myopt.title = _("List of settings");
                               3824               6 :         myopt.translate_header = true;
                               3825                 : 
 2685 tgl                      3826 GIC           6 :         printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 4932 alvherre                 3827 EUB             :     }
                               3828                 : 
 4932 alvherre                 3829 GIC           6 :     PQclear(res);
                               3830               6 :     return true;
  262 michael                  3831 ECB             : 
  262 michael                  3832 CBC           9 : error_return:
                               3833               9 :     termPQExpBuffer(&buf);
  262 michael                  3834 GIC           9 :     return false;
 4932 alvherre                 3835 ECB             : }
                               3836                 : 
                               3837                 : 
 8557 bruce                    3838                 : /*
                               3839                 :  * listTables()
                               3840                 :  *
 5118 tgl                      3841                 :  * handler for \dt, \di, etc.
 8557 bruce                    3842                 :  *
 7547 tgl                      3843                 :  * tabtypes is an array of characters, specifying what info is desired:
                               3844                 :  * t - tables
                               3845                 :  * i - indexes
                               3846                 :  * v - views
                               3847                 :  * m - materialized views
                               3848                 :  * s - sequences
                               3849                 :  * E - foreign table (Note: different from 'f', the relkind value)
                               3850                 :  * (any order of the above is fine)
                               3851                 :  */
                               3852                 : bool
 5206 bruce                    3853 GIC         153 : listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem)
                               3854                 : {
 7547 tgl                      3855             153 :     bool        showTables = strchr(tabtypes, 't') != NULL;
                               3856             153 :     bool        showIndexes = strchr(tabtypes, 'i') != NULL;
                               3857             153 :     bool        showViews = strchr(tabtypes, 'v') != NULL;
 3689 kgrittn                  3858             153 :     bool        showMatViews = strchr(tabtypes, 'm') != NULL;
 7547 tgl                      3859             153 :     bool        showSeq = strchr(tabtypes, 's') != NULL;
 4481 rhaas                    3860             153 :     bool        showForeign = strchr(tabtypes, 'E') != NULL;
                               3861                 : 
 7655 peter_e                  3862 ECB             :     PQExpBufferData buf;
                               3863                 :     PGresult   *res;
 8486 peter_e                  3864 CBC         153 :     printQueryOpt myopt = pset.popt;
 1376 tgl                      3865 ECB             :     int         cols_so_far;
  949 michael                  3866 CBC         153 :     bool        translate_columns[] = {false, false, true, false, false, false, false, false, false};
 8557 bruce                    3867 ECB             : 
 2120 tgl                      3868                 :     /* If tabtypes is empty, we default to \dtvmsE (but see also command.c) */
 3689 kgrittn                  3869 CBC         153 :     if (!(showTables || showIndexes || showViews || showMatViews || showSeq || showForeign))
 3689 kgrittn                  3870 UIC           0 :         showTables = showViews = showMatViews = showSeq = showForeign = true;
                               3871                 : 
 7655 peter_e                  3872 GIC         153 :     initPQExpBuffer(&buf);
 8393 peter_e                  3873 ECB             : 
 7655 peter_e                  3874 GIC         153 :     printfPQExpBuffer(&buf,
 7522 bruce                    3875 ECB             :                       "SELECT n.nspname as \"%s\",\n"
                               3876                 :                       "  c.relname as \"%s\",\n"
                               3877                 :                       "  CASE c.relkind"
 2222 tgl                      3878                 :                       " WHEN " CppAsString2(RELKIND_RELATION) " THEN '%s'"
 2222 tgl                      3879 EUB             :                       " WHEN " CppAsString2(RELKIND_VIEW) " THEN '%s'"
                               3880                 :                       " WHEN " CppAsString2(RELKIND_MATVIEW) " THEN '%s'"
 2222 tgl                      3881 ECB             :                       " WHEN " CppAsString2(RELKIND_INDEX) " THEN '%s'"
                               3882                 :                       " WHEN " CppAsString2(RELKIND_SEQUENCE) " THEN '%s'"
  824                          3883                 :                       " WHEN " CppAsString2(RELKIND_TOASTVALUE) " THEN '%s'"
                               3884                 :                       " WHEN " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN '%s'"
                               3885                 :                       " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
                               3886                 :                       " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
                               3887                 :                       " END as \"%s\",\n"
                               3888                 :                       "  pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"",
                               3889                 :                       gettext_noop("Schema"),
                               3890                 :                       gettext_noop("Name"),
                               3891                 :                       gettext_noop("table"),
                               3892                 :                       gettext_noop("view"),
                               3893                 :                       gettext_noop("materialized view"),
                               3894                 :                       gettext_noop("index"),
                               3895                 :                       gettext_noop("sequence"),
                               3896                 :                       gettext_noop("TOAST table"),
                               3897                 :                       gettext_noop("foreign table"),
                               3898                 :                       gettext_noop("partitioned table"),
                               3899                 :                       gettext_noop("partitioned index"),
                               3900                 :                       gettext_noop("Type"),
                               3901                 :                       gettext_noop("Owner"));
 1376 tgl                      3902 GIC         153 :     cols_so_far = 4;
                               3903                 : 
 6785 neilc                    3904             153 :     if (showIndexes)
                               3905                 :     {
                               3906              21 :         appendPQExpBuffer(&buf,
                               3907                 :                           ",\n  c2.relname as \"%s\"",
                               3908                 :                           gettext_noop("Table"));
 1376 tgl                      3909              21 :         cols_so_far++;
                               3910                 :     }
 6785 neilc                    3911 ECB             : 
 5393 tgl                      3912 GIC         153 :     if (verbose)
 4384 rhaas                    3913 ECB             :     {
                               3914                 :         /*
  479 tgl                      3915                 :          * Show whether a relation is permanent, temporary, or unlogged.
                               3916                 :          */
  479 tgl                      3917 GIC          15 :         appendPQExpBuffer(&buf,
  479 tgl                      3918 ECB             :                           ",\n  CASE c.relpersistence WHEN 'p' THEN '%s' WHEN 't' THEN '%s' WHEN 'u' THEN '%s' END as \"%s\"",
                               3919                 :                           gettext_noop("permanent"),
                               3920                 :                           gettext_noop("temporary"),
                               3921                 :                           gettext_noop("unlogged"),
                               3922                 :                           gettext_noop("Persistence"));
  479 tgl                      3923 GIC          15 :         translate_columns[cols_so_far] = true;
                               3924                 : 
                               3925                 :         /*
 1376 tgl                      3926 ECB             :          * We don't bother to count cols_so_far below here, as there's no need
                               3927                 :          * to; this might change with future additions to the output columns.
                               3928                 :          */
                               3929                 : 
                               3930                 :         /*
                               3931                 :          * Access methods exist for tables, materialized views and indexes.
  949 michael                  3932                 :          * This has been introduced in PostgreSQL 12 for tables.
                               3933                 :          */
  949 michael                  3934 GIC          15 :         if (pset.sversion >= 120000 && !pset.hide_tableam &&
                               3935               6 :             (showTables || showMatViews || showIndexes))
                               3936               9 :             appendPQExpBuffer(&buf,
                               3937                 :                               ",\n  am.amname as \"%s\"",
                               3938                 :                               gettext_noop("Access method"));
                               3939                 : 
 7655 peter_e                  3940              15 :         appendPQExpBuffer(&buf,
                               3941                 :                           ",\n  pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\""
                               3942                 :                           ",\n  pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"",
  479 tgl                      3943 ECB             :                           gettext_noop("Size"),
 5597                          3944                 :                           gettext_noop("Description"));
 4384 rhaas                    3945                 :     }
                               3946                 : 
 3429 heikki.linnakangas       3947 GIC         153 :     appendPQExpBufferStr(&buf,
                               3948                 :                          "\nFROM pg_catalog.pg_class c"
 2118 tgl                      3949 ECB             :                          "\n     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace");
                               3950                 : 
  949 michael                  3951 GIC         153 :     if (pset.sversion >= 120000 && !pset.hide_tableam &&
                               3952               6 :         (showTables || showMatViews || showIndexes))
                               3953               9 :         appendPQExpBufferStr(&buf,
                               3954                 :                              "\n     LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam");
                               3955                 : 
 7522 bruce                    3956 CBC         153 :     if (showIndexes)
 3429 heikki.linnakangas       3957 GIC          21 :         appendPQExpBufferStr(&buf,
                               3958                 :                              "\n     LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid"
                               3959                 :                              "\n     LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid");
 7655 peter_e                  3960 ECB             : 
 3429 heikki.linnakangas       3961 CBC         153 :     appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
 7953 peter_e                  3962             153 :     if (showTables)
                               3963                 :     {
 2222 tgl                      3964 GIC          54 :         appendPQExpBufferStr(&buf, CppAsString2(RELKIND_RELATION) ","
 2222 tgl                      3965 ECB             :                              CppAsString2(RELKIND_PARTITIONED_TABLE) ",");
  824                          3966                 :         /* with 'S' or a pattern, allow 't' to match TOAST tables too */
  824 tgl                      3967 GIC          54 :         if (showSystem || pattern)
                               3968              45 :             appendPQExpBufferStr(&buf, CppAsString2(RELKIND_TOASTVALUE) ",");
                               3969                 :     }
 8557 bruce                    3970 CBC         153 :     if (showViews)
 2222 tgl                      3971              30 :         appendPQExpBufferStr(&buf, CppAsString2(RELKIND_VIEW) ",");
 3689 kgrittn                  3972 GIC         153 :     if (showMatViews)
 2222 tgl                      3973 CBC          30 :         appendPQExpBufferStr(&buf, CppAsString2(RELKIND_MATVIEW) ",");
 7953 peter_e                  3974 GIC         153 :     if (showIndexes)
 1906 alvherre                 3975              21 :         appendPQExpBufferStr(&buf, CppAsString2(RELKIND_INDEX) ","
 1906 alvherre                 3976 ECB             :                              CppAsString2(RELKIND_PARTITIONED_INDEX) ",");
 7953 peter_e                  3977 CBC         153 :     if (showSeq)
 2222 tgl                      3978 GIC          27 :         appendPQExpBufferStr(&buf, CppAsString2(RELKIND_SEQUENCE) ",");
 5120 bruce                    3979 CBC         153 :     if (showSystem || pattern)
 2118 tgl                      3980             138 :         appendPQExpBufferStr(&buf, "'s',"); /* was RELKIND_SPECIAL */
 4481 rhaas                    3981             153 :     if (showForeign)
 2222 tgl                      3982              15 :         appendPQExpBufferStr(&buf, CppAsString2(RELKIND_FOREIGN_TABLE) ",");
 4481 rhaas                    3983 ECB             : 
 3260 bruce                    3984 CBC         153 :     appendPQExpBufferStr(&buf, "''"); /* dummy */
 3429 heikki.linnakangas       3985 GIC         153 :     appendPQExpBufferStr(&buf, ")\n");
 8557 bruce                    3986 ECB             : 
 5050 bruce                    3987 CBC         153 :     if (!showSystem && !pattern)
 3429 heikki.linnakangas       3988              15 :         appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
  824 tgl                      3989 ECB             :                              "      AND n.nspname !~ '^pg_toast'\n"
 3429 heikki.linnakangas       3990                 :                              "      AND n.nspname <> 'information_schema'\n");
 5118 tgl                      3991                 : 
  354 rhaas                    3992 GIC         153 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
  354 rhaas                    3993 ECB             :                                 "n.nspname", "c.relname", NULL,
                               3994                 :                                 "pg_catalog.pg_table_is_visible(c.oid)",
                               3995                 :                                 NULL, 3))
  262 michael                  3996                 :     {
  262 michael                  3997 CBC          81 :         termPQExpBuffer(&buf);
  354 rhaas                    3998 GIC          81 :         return false;
                               3999                 :     }
                               4000                 : 
 3429 heikki.linnakangas       4001 CBC          72 :     appendPQExpBufferStr(&buf, "ORDER BY 1,2;");
                               4002                 : 
 3090 fujii                    4003 GIC          72 :     res = PSQLexec(buf.data);
 7655 peter_e                  4004              72 :     termPQExpBuffer(&buf);
 8557 bruce                    4005              72 :     if (!res)
 8557 bruce                    4006 LBC           0 :         return false;
 8557 bruce                    4007 ECB             : 
                               4008                 :     /*
                               4009                 :      * Most functions in this file are content to print an empty table when
 2082 tgl                      4010                 :      * there are no matching objects.  We intentionally deviate from that
                               4011                 :      * here, but only in !quiet mode, for historical reasons.
                               4012                 :      */
 6067 tgl                      4013 CBC          72 :     if (PQntuples(res) == 0 && !pset.quiet)
 8397 bruce                    4014 ECB             :     {
 7547 tgl                      4015 UBC           0 :         if (pattern)
 1469 peter                    4016 UIC           0 :             pg_log_error("Did not find any relation named \"%s\".",
                               4017                 :                          pattern);
                               4018                 :         else
                               4019               0 :             pg_log_error("Did not find any relations.");
                               4020                 :     }
                               4021                 :     else
 8557 bruce                    4022 ECB             :     {
 8557 bruce                    4023 GIC          72 :         myopt.nullPrint = NULL;
 7953 peter_e                  4024 GBC          72 :         myopt.title = _("List of relations");
 5382 bruce                    4025              72 :         myopt.translate_header = true;
 5382 bruce                    4026 GIC          72 :         myopt.translate_columns = translate_columns;
 3382 tgl                      4027              72 :         myopt.n_translate_columns = lengthof(translate_columns);
 8557 bruce                    4028 EUB             : 
 2685 tgl                      4029 GIC          72 :         printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               4030                 :     }
                               4031                 : 
 8557 bruce                    4032 CBC          72 :     PQclear(res);
                               4033              72 :     return true;
 8557 bruce                    4034 ECB             : }
 7691                          4035                 : 
 1463 alvherre                 4036                 : /*
                               4037                 :  * \dP
                               4038                 :  * Takes an optional regexp to select particular relations
                               4039                 :  *
                               4040                 :  * As with \d, you can specify the kinds of relations you want:
                               4041                 :  *
                               4042                 :  * t for tables
                               4043                 :  * i for indexes
                               4044                 :  *
                               4045                 :  * And there's additional flags:
                               4046                 :  *
                               4047                 :  * n to list non-leaf partitioned tables
                               4048                 :  *
                               4049                 :  * and you can mix and match these in any order.
                               4050                 :  */
                               4051                 : bool
 1463 alvherre                 4052 GIC          54 : listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
                               4053                 : {
                               4054              54 :     bool        showTables = strchr(reltypes, 't') != NULL;
                               4055              54 :     bool        showIndexes = strchr(reltypes, 'i') != NULL;
                               4056              54 :     bool        showNested = strchr(reltypes, 'n') != NULL;
                               4057                 :     PQExpBufferData buf;
                               4058                 :     PQExpBufferData title;
                               4059                 :     PGresult   *res;
                               4060              54 :     printQueryOpt myopt = pset.popt;
 1418 tgl                      4061 CBC          54 :     bool        translate_columns[] = {false, false, false, false, false, false, false, false, false};
                               4062                 :     const char *tabletitle;
 1463 alvherre                 4063              54 :     bool        mixed_output = false;
 1463 alvherre                 4064 ECB             : 
                               4065                 :     /*
                               4066                 :      * Note: Declarative table partitioning is only supported as of Pg 10.0.
                               4067                 :      */
 1463 alvherre                 4068 GIC          54 :     if (pset.sversion < 100000)
 1463 alvherre                 4069 ECB             :     {
                               4070                 :         char        sverbuf[32];
                               4071                 : 
 1463 alvherre                 4072 LBC           0 :         pg_log_error("The server (version %s) does not support declarative table partitioning.",
                               4073                 :                      formatPGVersionNumber(pset.sversion, false,
                               4074                 :                                            sverbuf, sizeof(sverbuf)));
 1463 alvherre                 4075 UIC           0 :         return true;
                               4076                 :     }
 1463 alvherre                 4077 ECB             : 
                               4078                 :     /* If no relation kind was selected, show them all */
 1463 alvherre                 4079 GIC          54 :     if (!showTables && !showIndexes)
                               4080              36 :         showTables = showIndexes = true;
 1463 alvherre                 4081 EUB             : 
 1463 alvherre                 4082 GIC          54 :     if (showIndexes && !showTables)
                               4083               9 :         tabletitle = _("List of partitioned indexes");    /* \dPi */
 1463 alvherre                 4084 GBC          45 :     else if (showTables && !showIndexes)
 1463 alvherre                 4085 GIC           9 :         tabletitle = _("List of partitioned tables"); /* \dPt */
                               4086                 :     else
                               4087                 :     {
 1463 alvherre                 4088 ECB             :         /* show all kinds */
 1463 alvherre                 4089 CBC          36 :         tabletitle = _("List of partitioned relations");
 1463 alvherre                 4090 GIC          36 :         mixed_output = true;
 1463 alvherre                 4091 ECB             :     }
                               4092                 : 
 1463 alvherre                 4093 CBC          54 :     initPQExpBuffer(&buf);
 1463 alvherre                 4094 ECB             : 
 1463 alvherre                 4095 GIC          54 :     printfPQExpBuffer(&buf,
                               4096                 :                       "SELECT n.nspname as \"%s\",\n"
                               4097                 :                       "  c.relname as \"%s\",\n"
 1463 alvherre                 4098 ECB             :                       "  pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"",
                               4099                 :                       gettext_noop("Schema"),
                               4100                 :                       gettext_noop("Name"),
                               4101                 :                       gettext_noop("Owner"));
                               4102                 : 
 1463 alvherre                 4103 GIC          54 :     if (mixed_output)
 1463 alvherre                 4104 ECB             :     {
 1463 alvherre                 4105 GIC          36 :         appendPQExpBuffer(&buf,
                               4106                 :                           ",\n  CASE c.relkind"
                               4107                 :                           " WHEN " CppAsString2(RELKIND_PARTITIONED_TABLE) " THEN '%s'"
                               4108                 :                           " WHEN " CppAsString2(RELKIND_PARTITIONED_INDEX) " THEN '%s'"
                               4109                 :                           " END as \"%s\"",
                               4110                 :                           gettext_noop("partitioned table"),
                               4111                 :                           gettext_noop("partitioned index"),
 1463 alvherre                 4112 ECB             :                           gettext_noop("Type"));
                               4113                 : 
 1463 alvherre                 4114 CBC          36 :         translate_columns[3] = true;
                               4115                 :     }
                               4116                 : 
 1463 alvherre                 4117 GIC          54 :     if (showNested || pattern)
                               4118              45 :         appendPQExpBuffer(&buf,
                               4119                 :                           ",\n  inh.inhparent::pg_catalog.regclass as \"%s\"",
                               4120                 :                           gettext_noop("Parent name"));
                               4121                 : 
                               4122              54 :     if (showIndexes)
 1463 alvherre                 4123 CBC          45 :         appendPQExpBuffer(&buf,
                               4124                 :                           ",\n c2.oid::pg_catalog.regclass as \"%s\"",
                               4125                 :                           gettext_noop("Table"));
 1463 alvherre                 4126 ECB             : 
 1463 alvherre                 4127 CBC          54 :     if (verbose)
                               4128                 :     {
 1463 alvherre                 4129 UIC           0 :         if (showNested)
                               4130                 :         {
 1463 alvherre                 4131 LBC           0 :             appendPQExpBuffer(&buf,
 1463 alvherre                 4132 ECB             :                               ",\n  s.dps as \"%s\"",
                               4133                 :                               gettext_noop("Leaf partition size"));
 1463 alvherre                 4134 UIC           0 :             appendPQExpBuffer(&buf,
                               4135                 :                               ",\n  s.tps as \"%s\"",
 1463 alvherre                 4136 ECB             :                               gettext_noop("Total size"));
                               4137                 :         }
 1463 alvherre                 4138 EUB             :         else
                               4139                 :             /* Sizes of all partitions are considered in this case. */
 1463 alvherre                 4140 UBC           0 :             appendPQExpBuffer(&buf,
                               4141                 :                               ",\n  s.tps as \"%s\"",
                               4142                 :                               gettext_noop("Total size"));
 1463 alvherre                 4143 EUB             : 
 1463 alvherre                 4144 UIC           0 :         appendPQExpBuffer(&buf,
                               4145                 :                           ",\n  pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"",
                               4146                 :                           gettext_noop("Description"));
                               4147                 :     }
                               4148                 : 
 1463 alvherre                 4149 GBC          54 :     appendPQExpBufferStr(&buf,
                               4150                 :                          "\nFROM pg_catalog.pg_class c"
                               4151                 :                          "\n     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace");
                               4152                 : 
                               4153              54 :     if (showIndexes)
 1463 alvherre                 4154 GIC          45 :         appendPQExpBufferStr(&buf,
                               4155                 :                              "\n     LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid"
                               4156                 :                              "\n     LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid");
                               4157                 : 
 1463 alvherre                 4158 CBC          54 :     if (showNested || pattern)
 1463 alvherre                 4159 GIC          45 :         appendPQExpBufferStr(&buf,
                               4160                 :                              "\n     LEFT JOIN pg_catalog.pg_inherits inh ON c.oid = inh.inhrelid");
                               4161                 : 
 1463 alvherre                 4162 CBC          54 :     if (verbose)
 1463 alvherre                 4163 ECB             :     {
 1463 alvherre                 4164 UIC           0 :         if (pset.sversion < 120000)
                               4165                 :         {
 1375 drowley                  4166               0 :             appendPQExpBufferStr(&buf,
 1375 drowley                  4167 ECB             :                                  ",\n     LATERAL (WITH RECURSIVE d\n"
                               4168                 :                                  "                AS (SELECT inhrelid AS oid, 1 AS level\n"
                               4169                 :                                  "                      FROM pg_catalog.pg_inherits\n"
                               4170                 :                                  "                     WHERE inhparent = c.oid\n"
                               4171                 :                                  "                    UNION ALL\n"
                               4172                 :                                  "                    SELECT inhrelid, level + 1\n"
 1375 drowley                  4173 EUB             :                                  "                      FROM pg_catalog.pg_inherits i\n"
                               4174                 :                                  "                           JOIN d ON i.inhparent = d.oid)\n"
                               4175                 :                                  "                SELECT pg_catalog.pg_size_pretty(sum(pg_catalog.pg_table_size("
                               4176                 :                                  "d.oid))) AS tps,\n"
                               4177                 :                                  "                       pg_catalog.pg_size_pretty(sum("
                               4178                 :                                  "\n             CASE WHEN d.level = 1"
                               4179                 :                                  " THEN pg_catalog.pg_table_size(d.oid) ELSE 0 END)) AS dps\n"
                               4180                 :                                  "               FROM d) s");
                               4181                 :         }
                               4182                 :         else
                               4183                 :         {
                               4184                 :             /* PostgreSQL 12 has pg_partition_tree function */
 1375 drowley                  4185 UIC           0 :             appendPQExpBufferStr(&buf,
                               4186                 :                                  ",\n     LATERAL (SELECT pg_catalog.pg_size_pretty(sum("
                               4187                 :                                  "\n                 CASE WHEN ppt.isleaf AND ppt.level = 1"
                               4188                 :                                  "\n                      THEN pg_catalog.pg_table_size(ppt.relid)"
                               4189                 :                                  " ELSE 0 END)) AS dps"
                               4190                 :                                  ",\n                     pg_catalog.pg_size_pretty(sum("
                               4191                 :                                  "pg_catalog.pg_table_size(ppt.relid))) AS tps"
                               4192                 :                                  "\n              FROM pg_catalog.pg_partition_tree(c.oid) ppt) s");
                               4193                 :         }
 1463 alvherre                 4194 EUB             :     }
                               4195                 : 
 1463 alvherre                 4196 GIC          54 :     appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
                               4197              54 :     if (showTables)
                               4198              45 :         appendPQExpBufferStr(&buf, CppAsString2(RELKIND_PARTITIONED_TABLE) ",");
                               4199              54 :     if (showIndexes)
                               4200              45 :         appendPQExpBufferStr(&buf, CppAsString2(RELKIND_PARTITIONED_INDEX) ",");
                               4201              54 :     appendPQExpBufferStr(&buf, "''"); /* dummy */
                               4202              54 :     appendPQExpBufferStr(&buf, ")\n");
                               4203                 : 
                               4204              54 :     appendPQExpBufferStr(&buf, !showNested && !pattern ?
 1463 alvherre                 4205 ECB             :                          " AND NOT c.relispartition\n" : "");
                               4206                 : 
 1463 alvherre                 4207 CBC          54 :     if (!pattern)
                               4208              18 :         appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
  824 tgl                      4209 ECB             :                              "      AND n.nspname !~ '^pg_toast'\n"
 1463 alvherre                 4210                 :                              "      AND n.nspname <> 'information_schema'\n");
                               4211                 : 
  354 rhaas                    4212 GIC          54 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
  354 rhaas                    4213 ECB             :                                 "n.nspname", "c.relname", NULL,
                               4214                 :                                 "pg_catalog.pg_table_is_visible(c.oid)",
                               4215                 :                                 NULL, 3))
  262 michael                  4216                 :     {
  262 michael                  4217 CBC          12 :         termPQExpBuffer(&buf);
  354 rhaas                    4218 GIC          12 :         return false;
                               4219                 :     }
                               4220                 : 
 1463 alvherre                 4221 CBC          72 :     appendPQExpBuffer(&buf, "ORDER BY \"Schema\", %s%s\"Name\";",
                               4222                 :                       mixed_output ? "\"Type\" DESC, " : "",
 1463 alvherre                 4223 GIC          30 :                       showNested || pattern ? "\"Parent name\" NULLS FIRST, " : "");
                               4224                 : 
                               4225              42 :     res = PSQLexec(buf.data);
 1463 alvherre                 4226 CBC          42 :     termPQExpBuffer(&buf);
                               4227              42 :     if (!res)
 1463 alvherre                 4228 UIC           0 :         return false;
                               4229                 : 
 1463 alvherre                 4230 CBC          42 :     initPQExpBuffer(&title);
 1375 drowley                  4231 GIC          42 :     appendPQExpBufferStr(&title, tabletitle);
 1463 alvherre                 4232 ECB             : 
 1463 alvherre                 4233 GIC          42 :     myopt.nullPrint = NULL;
 1463 alvherre                 4234 CBC          42 :     myopt.title = title.data;
                               4235              42 :     myopt.translate_header = true;
                               4236              42 :     myopt.translate_columns = translate_columns;
 1463 alvherre                 4237 GBC          42 :     myopt.n_translate_columns = lengthof(translate_columns);
                               4238                 : 
 1463 alvherre                 4239 CBC          42 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 1463 alvherre                 4240 ECB             : 
 1463 alvherre                 4241 GIC          42 :     termPQExpBuffer(&title);
 1463 alvherre                 4242 ECB             : 
 1463 alvherre                 4243 CBC          42 :     PQclear(res);
                               4244              42 :     return true;
 1463 alvherre                 4245 ECB             : }
 7655 peter_e                  4246                 : 
                               4247                 : /*
 4462 rhaas                    4248                 :  * \dL
                               4249                 :  *
                               4250                 :  * Describes languages.
                               4251                 :  */
                               4252                 : bool
 4462 rhaas                    4253 CBC          15 : listLanguages(const char *pattern, bool verbose, bool showSystem)
                               4254                 : {
                               4255                 :     PQExpBufferData buf;
                               4256                 :     PGresult   *res;
 4462 rhaas                    4257 GIC          15 :     printQueryOpt myopt = pset.popt;
                               4258                 : 
                               4259              15 :     initPQExpBuffer(&buf);
                               4260                 : 
                               4261              15 :     printfPQExpBuffer(&buf,
  479 tgl                      4262 ECB             :                       "SELECT l.lanname AS \"%s\",\n"
                               4263                 :                       "       pg_catalog.pg_get_userbyid(l.lanowner) as \"%s\",\n"
                               4264                 :                       "       l.lanpltrusted AS \"%s\"",
                               4265                 :                       gettext_noop("Name"),
                               4266                 :                       gettext_noop("Owner"),
                               4267                 :                       gettext_noop("Trusted"));
 4462 rhaas                    4268                 : 
 4462 rhaas                    4269 GIC          15 :     if (verbose)
 4462 rhaas                    4270 ECB             :     {
 4382 bruce                    4271 UIC           0 :         appendPQExpBuffer(&buf,
                               4272                 :                           ",\n       NOT l.lanispl AS \"%s\",\n"
                               4273                 :                           "       l.lanplcallfoid::pg_catalog.regprocedure AS \"%s\",\n"
                               4274                 :                           "       l.lanvalidator::pg_catalog.regprocedure AS \"%s\",\n       "
                               4275                 :                           "l.laninline::pg_catalog.regprocedure AS \"%s\",\n       ",
                               4276                 :                           gettext_noop("Internal language"),
                               4277                 :                           gettext_noop("Call handler"),
  479 tgl                      4278 ECB             :                           gettext_noop("Validator"),
                               4279                 :                           gettext_noop("Inline handler"));
 4382 bruce                    4280 UBC           0 :         printACLColumn(&buf, "l.lanacl");
                               4281                 :     }
                               4282                 : 
 4462 rhaas                    4283 GIC          15 :     appendPQExpBuffer(&buf,
                               4284                 :                       ",\n       d.description AS \"%s\""
                               4285                 :                       "\nFROM pg_catalog.pg_language l\n"
                               4286                 :                       "LEFT JOIN pg_catalog.pg_description d\n"
                               4287                 :                       "  ON d.classoid = l.tableoid AND d.objoid = l.oid\n"
                               4288                 :                       "  AND d.objsubid = 0\n",
 4262 rhaas                    4289 EUB             :                       gettext_noop("Description"));
                               4290                 : 
 4266 rhaas                    4291 GIC          15 :     if (pattern)
  262 michael                  4292 ECB             :     {
  354 rhaas                    4293 GIC          15 :         if (!validateSQLNamePattern(&buf, pattern, false, false,
                               4294                 :                                     NULL, "l.lanname", NULL, NULL,
                               4295                 :                                     NULL, 2))
                               4296                 :         {
  262 michael                  4297              12 :             termPQExpBuffer(&buf);
  354 rhaas                    4298              12 :             return false;
                               4299                 :         }
  262 michael                  4300 ECB             :     }
                               4301                 : 
 4462 rhaas                    4302 CBC           3 :     if (!showSystem && !pattern)
 3429 heikki.linnakangas       4303 UIC           0 :         appendPQExpBufferStr(&buf, "WHERE l.lanplcallfoid != 0\n");
                               4304                 : 
                               4305                 : 
 3429 heikki.linnakangas       4306 CBC           3 :     appendPQExpBufferStr(&buf, "ORDER BY 1;");
 4462 rhaas                    4307 ECB             : 
 3090 fujii                    4308 GIC           3 :     res = PSQLexec(buf.data);
 4462 rhaas                    4309               3 :     termPQExpBuffer(&buf);
                               4310               3 :     if (!res)
 4462 rhaas                    4311 LBC           0 :         return false;
 4462 rhaas                    4312 EUB             : 
 4462 rhaas                    4313 GIC           3 :     myopt.nullPrint = NULL;
                               4314               3 :     myopt.title = _("List of languages");
 4462 rhaas                    4315 CBC           3 :     myopt.translate_header = true;
                               4316                 : 
 2685 tgl                      4317               3 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 4462 rhaas                    4318 ECB             : 
 4462 rhaas                    4319 CBC           3 :     PQclear(res);
 4462 rhaas                    4320 GBC           3 :     return true;
                               4321                 : }
 4462 rhaas                    4322 ECB             : 
                               4323                 : 
 7691 bruce                    4324                 : /*
                               4325                 :  * \dD
                               4326                 :  *
                               4327                 :  * Describes domains.
                               4328                 :  */
                               4329                 : bool
 4262 rhaas                    4330 GIC          21 : listDomains(const char *pattern, bool verbose, bool showSystem)
                               4331                 : {
                               4332                 :     PQExpBufferData buf;
                               4333                 :     PGresult   *res;
 7691 bruce                    4334              21 :     printQueryOpt myopt = pset.popt;
                               4335                 : 
 7655 peter_e                  4336              21 :     initPQExpBuffer(&buf);
                               4337                 : 
                               4338              21 :     printfPQExpBuffer(&buf,
 7522 bruce                    4339 ECB             :                       "SELECT n.nspname as \"%s\",\n"
                               4340                 :                       "       t.typname as \"%s\",\n"
                               4341                 :                       "       pg_catalog.format_type(t.typbasetype, t.typtypmod) as \"%s\",\n"
                               4342                 :                       "       (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type bt\n"
  479 tgl                      4343                 :                       "        WHERE c.oid = t.typcollation AND bt.oid = t.typbasetype AND t.typcollation <> bt.typcollation) as \"%s\",\n"
                               4344                 :                       "       CASE WHEN t.typnotnull THEN 'not null' END as \"%s\",\n"
 2348 peter_e                  4345                 :                       "       t.typdefault as \"%s\",\n"
                               4346                 :                       "       pg_catalog.array_to_string(ARRAY(\n"
 5158 tgl                      4347                 :                       "         SELECT pg_catalog.pg_get_constraintdef(r.oid, true) FROM pg_catalog.pg_constraint r WHERE t.oid = r.contypid\n"
                               4348                 :                       "       ), ' ') as \"%s\"",
                               4349                 :                       gettext_noop("Schema"),
                               4350                 :                       gettext_noop("Name"),
                               4351                 :                       gettext_noop("Type"),
                               4352                 :                       gettext_noop("Collation"),
                               4353                 :                       gettext_noop("Nullable"),
                               4354                 :                       gettext_noop("Default"),
                               4355                 :                       gettext_noop("Check"));
                               4356                 : 
 4262 rhaas                    4357 GIC          21 :     if (verbose)
                               4358                 :     {
  479 tgl                      4359 UIC           0 :         appendPQExpBufferStr(&buf, ",\n  ");
                               4360               0 :         printACLColumn(&buf, "t.typacl");
 4262 rhaas                    4361               0 :         appendPQExpBuffer(&buf,
                               4362                 :                           ",\n       d.description as \"%s\"",
                               4363                 :                           gettext_noop("Description"));
                               4364                 :     }
                               4365                 : 
 3429 heikki.linnakangas       4366 CBC          21 :     appendPQExpBufferStr(&buf,
                               4367                 :                          "\nFROM pg_catalog.pg_type t\n"
 2118 tgl                      4368 EUB             :                          "     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
 4262 rhaas                    4369                 : 
 4262 rhaas                    4370 GBC          21 :     if (verbose)
 3429 heikki.linnakangas       4371 UIC           0 :         appendPQExpBufferStr(&buf,
                               4372                 :                              "     LEFT JOIN pg_catalog.pg_description d "
                               4373                 :                              "ON d.classoid = t.tableoid AND d.objoid = t.oid "
                               4374                 :                              "AND d.objsubid = 0\n");
 4262 rhaas                    4375 ECB             : 
 3429 heikki.linnakangas       4376 GIC          21 :     appendPQExpBufferStr(&buf, "WHERE t.typtype = 'd'\n");
                               4377                 : 
 5050 bruce                    4378              21 :     if (!showSystem && !pattern)
 3429 heikki.linnakangas       4379 LBC           0 :         appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
 3429 heikki.linnakangas       4380 EUB             :                              "      AND n.nspname <> 'information_schema'\n");
                               4381                 : 
  354 rhaas                    4382 GIC          21 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
                               4383                 :                                 "n.nspname", "t.typname", NULL,
                               4384                 :                                 "pg_catalog.pg_type_is_visible(t.oid)",
  354 rhaas                    4385 ECB             :                                 NULL, 3))
                               4386                 :     {
  262 michael                  4387 CBC          12 :         termPQExpBuffer(&buf);
  354 rhaas                    4388 GBC          12 :         return false;
                               4389                 :     }
                               4390                 : 
 3429 heikki.linnakangas       4391 CBC           9 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
                               4392                 : 
 3090 fujii                    4393 GIC           9 :     res = PSQLexec(buf.data);
 7655 peter_e                  4394               9 :     termPQExpBuffer(&buf);
 7691 bruce                    4395               9 :     if (!res)
 7691 bruce                    4396 LBC           0 :         return false;
 7691 bruce                    4397 ECB             : 
 7691 bruce                    4398 GIC           9 :     myopt.nullPrint = NULL;
 7655 peter_e                  4399               9 :     myopt.title = _("List of domains");
 5382 bruce                    4400 CBC           9 :     myopt.translate_header = true;
                               4401                 : 
 2685 tgl                      4402               9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 7691 bruce                    4403 ECB             : 
 7691 bruce                    4404 CBC           9 :     PQclear(res);
 7691 bruce                    4405 GBC           9 :     return true;
                               4406                 : }
 7547 tgl                      4407 ECB             : 
 7423 bruce                    4408                 : /*
                               4409                 :  * \dc
                               4410                 :  *
                               4411                 :  * Describes conversions.
                               4412                 :  */
                               4413                 : bool
 4262 rhaas                    4414 CBC          21 : listConversions(const char *pattern, bool verbose, bool showSystem)
                               4415                 : {
                               4416                 :     PQExpBufferData buf;
                               4417                 :     PGresult   *res;
 7423 bruce                    4418 GIC          21 :     printQueryOpt myopt = pset.popt;
                               4419                 :     static const bool translate_columns[] =
                               4420                 :     {false, false, false, false, true, false};
                               4421                 : 
                               4422              21 :     initPQExpBuffer(&buf);
 7423 bruce                    4423 ECB             : 
 7423 bruce                    4424 GIC          21 :     printfPQExpBuffer(&buf,
                               4425                 :                       "SELECT n.nspname AS \"%s\",\n"
                               4426                 :                       "       c.conname AS \"%s\",\n"
 2118 tgl                      4427 ECB             :                       "       pg_catalog.pg_encoding_to_char(c.conforencoding) AS \"%s\",\n"
                               4428                 :                       "       pg_catalog.pg_encoding_to_char(c.contoencoding) AS \"%s\",\n"
                               4429                 :                       "       CASE WHEN c.condefault THEN '%s'\n"
                               4430                 :                       "       ELSE '%s' END AS \"%s\"",
 5597                          4431                 :                       gettext_noop("Schema"),
                               4432                 :                       gettext_noop("Name"),
                               4433                 :                       gettext_noop("Source"),
                               4434                 :                       gettext_noop("Destination"),
                               4435                 :                       gettext_noop("yes"), gettext_noop("no"),
                               4436                 :                       gettext_noop("Default?"));
                               4437                 : 
 4262 rhaas                    4438 GIC          21 :     if (verbose)
 4262 rhaas                    4439 UIC           0 :         appendPQExpBuffer(&buf,
                               4440                 :                           ",\n       d.description AS \"%s\"",
                               4441                 :                           gettext_noop("Description"));
                               4442                 : 
 3429 heikki.linnakangas       4443 GIC          21 :     appendPQExpBufferStr(&buf,
                               4444                 :                          "\nFROM pg_catalog.pg_conversion c\n"
                               4445                 :                          "     JOIN pg_catalog.pg_namespace n "
                               4446                 :                          "ON n.oid = c.connamespace\n");
 4262 rhaas                    4447 ECB             : 
 4262 rhaas                    4448 GBC          21 :     if (verbose)
 3429 heikki.linnakangas       4449 UIC           0 :         appendPQExpBufferStr(&buf,
                               4450                 :                              "LEFT JOIN pg_catalog.pg_description d "
                               4451                 :                              "ON d.classoid = c.tableoid\n"
 3429 heikki.linnakangas       4452 ECB             :                              "          AND d.objoid = c.oid "
                               4453                 :                              "AND d.objsubid = 0\n");
                               4454                 : 
 3429 heikki.linnakangas       4455 GIC          21 :     appendPQExpBufferStr(&buf, "WHERE true\n");
                               4456                 : 
 5050 bruce                    4457 CBC          21 :     if (!showSystem && !pattern)
 3429 heikki.linnakangas       4458 UBC           0 :         appendPQExpBufferStr(&buf, "  AND n.nspname <> 'pg_catalog'\n"
                               4459                 :                              "  AND n.nspname <> 'information_schema'\n");
                               4460                 : 
  354 rhaas                    4461 GIC          21 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
                               4462                 :                                 "n.nspname", "c.conname", NULL,
                               4463                 :                                 "pg_catalog.pg_conversion_is_visible(c.oid)",
  354 rhaas                    4464 ECB             :                                 NULL, 3))
                               4465                 :     {
  262 michael                  4466 CBC          12 :         termPQExpBuffer(&buf);
  354 rhaas                    4467 GBC          12 :         return false;
                               4468                 :     }
                               4469                 : 
 3429 heikki.linnakangas       4470 CBC           9 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
                               4471                 : 
 3090 fujii                    4472 GIC           9 :     res = PSQLexec(buf.data);
 7423 bruce                    4473               9 :     termPQExpBuffer(&buf);
                               4474               9 :     if (!res)
 7423 bruce                    4475 LBC           0 :         return false;
 7423 bruce                    4476 ECB             : 
 7423 bruce                    4477 GIC           9 :     myopt.nullPrint = NULL;
                               4478               9 :     myopt.title = _("List of conversions");
 5382 bruce                    4479 CBC           9 :     myopt.translate_header = true;
 5382 bruce                    4480 GIC           9 :     myopt.translate_columns = translate_columns;
 3382 tgl                      4481 CBC           9 :     myopt.n_translate_columns = lengthof(translate_columns);
 7423 bruce                    4482 ECB             : 
 2685 tgl                      4483 CBC           9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 7423 bruce                    4484 EUB             : 
 7423 bruce                    4485 GIC           9 :     PQclear(res);
 7423 bruce                    4486 CBC           9 :     return true;
 7423 bruce                    4487 ECB             : }
                               4488                 : 
  367 tgl                      4489                 : /*
                               4490                 :  * \dconfig
                               4491                 :  *
                               4492                 :  * Describes configuration parameters.
                               4493                 :  */
                               4494                 : bool
  367 tgl                      4495 CBC           6 : describeConfigurationParameters(const char *pattern, bool verbose,
                               4496                 :                                 bool showSystem)
                               4497                 : {
                               4498                 :     PQExpBufferData buf;
                               4499                 :     PGresult   *res;
  367 tgl                      4500 GIC           6 :     printQueryOpt myopt = pset.popt;
                               4501                 : 
                               4502               6 :     initPQExpBuffer(&buf);
                               4503               6 :     printfPQExpBuffer(&buf,
  367 tgl                      4504 ECB             :                       "SELECT s.name AS \"%s\", "
                               4505                 :                       "pg_catalog.current_setting(s.name) AS \"%s\"",
                               4506                 :                       gettext_noop("Parameter"),
                               4507                 :                       gettext_noop("Value"));
                               4508                 : 
  367 tgl                      4509 CBC           6 :     if (verbose)
                               4510                 :     {
                               4511               3 :         appendPQExpBuffer(&buf,
  367 tgl                      4512 ECB             :                           ", s.vartype AS \"%s\", s.context AS \"%s\", ",
                               4513                 :                           gettext_noop("Type"),
                               4514                 :                           gettext_noop("Context"));
  367 tgl                      4515 GIC           3 :         if (pset.sversion >= 150000)
                               4516               3 :             printACLColumn(&buf, "p.paracl");
                               4517                 :         else
  367 tgl                      4518 LBC           0 :             appendPQExpBuffer(&buf, "NULL AS \"%s\"",
                               4519                 :                               gettext_noop("Access privileges"));
  367 tgl                      4520 ECB             :     }
                               4521                 : 
  367 tgl                      4522 GIC           6 :     appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_settings s\n");
                               4523                 : 
  367 tgl                      4524 CBC           6 :     if (verbose && pset.sversion >= 150000)
                               4525               3 :         appendPQExpBufferStr(&buf,
                               4526                 :                              "  LEFT JOIN pg_catalog.pg_parameter_acl p\n"
  367 tgl                      4527 EUB             :                              "  ON pg_catalog.lower(s.name) = p.parname\n");
                               4528                 : 
  363 tgl                      4529 GIC           6 :     if (pattern)
                               4530               6 :         processSQLNamePattern(pset.db, &buf, pattern,
  363 tgl                      4531 ECB             :                               false, false,
                               4532                 :                               NULL, "pg_catalog.lower(s.name)", NULL,
  354 rhaas                    4533                 :                               NULL, NULL, NULL);
  363 tgl                      4534                 :     else
  361 tgl                      4535 UIC           0 :         appendPQExpBufferStr(&buf, "WHERE s.source <> 'default' AND\n"
                               4536                 :                              "      s.setting IS DISTINCT FROM s.boot_val\n");
                               4537                 : 
  367 tgl                      4538 CBC           6 :     appendPQExpBufferStr(&buf, "ORDER BY 1;");
  367 tgl                      4539 ECB             : 
  367 tgl                      4540 GIC           6 :     res = PSQLexec(buf.data);
                               4541               6 :     termPQExpBuffer(&buf);
                               4542               6 :     if (!res)
  367 tgl                      4543 UIC           0 :         return false;
  367 tgl                      4544 EUB             : 
  367 tgl                      4545 GIC           6 :     myopt.nullPrint = NULL;
  363                          4546               6 :     if (pattern)
  363 tgl                      4547 CBC           6 :         myopt.title = _("List of configuration parameters");
                               4548                 :     else
  363 tgl                      4549 LBC           0 :         myopt.title = _("List of non-default configuration parameters");
  367 tgl                      4550 CBC           6 :     myopt.translate_header = true;
  367 tgl                      4551 ECB             : 
  367 tgl                      4552 GBC           6 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               4553                 : 
  367 tgl                      4554 CBC           6 :     PQclear(res);
                               4555               6 :     return true;
  367 tgl                      4556 ECB             : }
                               4557                 : 
 3917 rhaas                    4558 EUB             : /*
 3917 rhaas                    4559 ECB             :  * \dy
                               4560                 :  *
                               4561                 :  * Describes Event Triggers.
                               4562                 :  */
                               4563                 : bool
 3917 rhaas                    4564 CBC          12 : listEventTriggers(const char *pattern, bool verbose)
                               4565                 : {
                               4566                 :     PQExpBufferData buf;
                               4567                 :     PGresult   *res;
 3917 rhaas                    4568 GIC          12 :     printQueryOpt myopt = pset.popt;
                               4569                 :     static const bool translate_columns[] =
                               4570                 :     {false, false, false, true, false, false, false};
                               4571                 : 
  479 tgl                      4572              12 :     if (pset.sversion < 90300)
  479 tgl                      4573 ECB             :     {
                               4574                 :         char        sverbuf[32];
                               4575                 : 
  479 tgl                      4576 UIC           0 :         pg_log_error("The server (version %s) does not support event triggers.",
  479 tgl                      4577 ECB             :                      formatPGVersionNumber(pset.sversion, false,
                               4578                 :                                            sverbuf, sizeof(sverbuf)));
  479 tgl                      4579 UIC           0 :         return true;
                               4580                 :     }
  479 tgl                      4581 ECB             : 
 3917 rhaas                    4582 GIC          12 :     initPQExpBuffer(&buf);
                               4583                 : 
                               4584              12 :     printfPQExpBuffer(&buf,
 3382 tgl                      4585 EUB             :                       "SELECT evtname as \"%s\", "
                               4586                 :                       "evtevent as \"%s\", "
                               4587                 :                       "pg_catalog.pg_get_userbyid(e.evtowner) as \"%s\",\n"
                               4588                 :                       " case evtenabled when 'O' then '%s'"
                               4589                 :                       "  when 'R' then '%s'"
                               4590                 :                       "  when 'A' then '%s'"
 3382 tgl                      4591 ECB             :                       "  when 'D' then '%s' end as \"%s\",\n"
                               4592                 :                       " e.evtfoid::pg_catalog.regproc as \"%s\", "
                               4593                 :                       "pg_catalog.array_to_string(array(select x"
                               4594                 :                       " from pg_catalog.unnest(evttags) as t(x)), ', ') as \"%s\"",
                               4595                 :                       gettext_noop("Name"),
                               4596                 :                       gettext_noop("Event"),
                               4597                 :                       gettext_noop("Owner"),
                               4598                 :                       gettext_noop("enabled"),
                               4599                 :                       gettext_noop("replica"),
                               4600                 :                       gettext_noop("always"),
                               4601                 :                       gettext_noop("disabled"),
                               4602                 :                       gettext_noop("Enabled"),
                               4603                 :                       gettext_noop("Function"),
                               4604                 :                       gettext_noop("Tags"));
 3917 rhaas                    4605 GIC          12 :     if (verbose)
 3917 rhaas                    4606 UIC           0 :         appendPQExpBuffer(&buf,
                               4607                 :                           ",\npg_catalog.obj_description(e.oid, 'pg_event_trigger') as \"%s\"",
                               4608                 :                           gettext_noop("Description"));
 3429 heikki.linnakangas       4609 GIC          12 :     appendPQExpBufferStr(&buf,
                               4610                 :                          "\nFROM pg_catalog.pg_event_trigger e ");
                               4611                 : 
  354 rhaas                    4612              12 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                               4613                 :                                 NULL, "evtname", NULL, NULL,
  354 rhaas                    4614 ECB             :                                 NULL, 1))
  262 michael                  4615 EUB             :     {
  262 michael                  4616 GIC           9 :         termPQExpBuffer(&buf);
  354 rhaas                    4617               9 :         return false;
  262 michael                  4618 ECB             :     }
                               4619                 : 
 3429 heikki.linnakangas       4620 GIC           3 :     appendPQExpBufferStr(&buf, "ORDER BY 1");
 3917 rhaas                    4621 ECB             : 
 3090 fujii                    4622 GIC           3 :     res = PSQLexec(buf.data);
 3917 rhaas                    4623               3 :     termPQExpBuffer(&buf);
                               4624               3 :     if (!res)
 3917 rhaas                    4625 LBC           0 :         return false;
 3917 rhaas                    4626 ECB             : 
 3917 rhaas                    4627 GIC           3 :     myopt.nullPrint = NULL;
                               4628               3 :     myopt.title = _("List of event triggers");
 3917 rhaas                    4629 CBC           3 :     myopt.translate_header = true;
 3917 rhaas                    4630 GIC           3 :     myopt.translate_columns = translate_columns;
 3382 tgl                      4631 CBC           3 :     myopt.n_translate_columns = lengthof(translate_columns);
 3917 rhaas                    4632 ECB             : 
 2685 tgl                      4633 CBC           3 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 3917 rhaas                    4634 EUB             : 
 3917 rhaas                    4635 GIC           3 :     PQclear(res);
 3917 rhaas                    4636 CBC           3 :     return true;
 3917 rhaas                    4637 ECB             : }
                               4638                 : 
  809 tomas.vondra             4639                 : /*
                               4640                 :  * \dX
                               4641                 :  *
                               4642                 :  * Describes extended statistics.
                               4643                 :  */
                               4644                 : bool
  809 tomas.vondra             4645 CBC          51 : listExtendedStats(const char *pattern)
                               4646                 : {
                               4647                 :     PQExpBufferData buf;
                               4648                 :     PGresult   *res;
  809 tomas.vondra             4649 GIC          51 :     printQueryOpt myopt = pset.popt;
                               4650                 : 
                               4651              51 :     if (pset.sversion < 100000)
                               4652                 :     {
                               4653                 :         char        sverbuf[32];
  809 tomas.vondra             4654 ECB             : 
  809 tomas.vondra             4655 UIC           0 :         pg_log_error("The server (version %s) does not support extended statistics.",
                               4656                 :                      formatPGVersionNumber(pset.sversion, false,
                               4657                 :                                            sverbuf, sizeof(sverbuf)));
  809 tomas.vondra             4658 LBC           0 :         return true;
                               4659                 :     }
  809 tomas.vondra             4660 ECB             : 
  809 tomas.vondra             4661 GIC          51 :     initPQExpBuffer(&buf);
                               4662              51 :     printfPQExpBuffer(&buf,
                               4663                 :                       "SELECT \n"
  456 michael                  4664 EUB             :                       "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text AS \"%s\", \n"
                               4665                 :                       "es.stxname AS \"%s\", \n",
                               4666                 :                       gettext_noop("Schema"),
  744 tomas.vondra             4667                 :                       gettext_noop("Name"));
                               4668                 : 
  744 tomas.vondra             4669 GIC          51 :     if (pset.sversion >= 140000)
  744 tomas.vondra             4670 CBC          51 :         appendPQExpBuffer(&buf,
  744 tomas.vondra             4671 ECB             :                           "pg_catalog.format('%%s FROM %%s', \n"
                               4672                 :                           "  pg_catalog.pg_get_statisticsobjdef_columns(es.oid), \n"
                               4673                 :                           "  es.stxrelid::pg_catalog.regclass) AS \"%s\"",
                               4674                 :                           gettext_noop("Definition"));
                               4675                 :     else
  744 tomas.vondra             4676 UIC           0 :         appendPQExpBuffer(&buf,
                               4677                 :                           "pg_catalog.format('%%s FROM %%s', \n"
  744 tomas.vondra             4678 ECB             :                           "  (SELECT pg_catalog.string_agg(pg_catalog.quote_ident(a.attname),', ') \n"
                               4679                 :                           "   FROM pg_catalog.unnest(es.stxkeys) s(attnum) \n"
                               4680                 :                           "   JOIN pg_catalog.pg_attribute a \n"
                               4681                 :                           "   ON (es.stxrelid = a.attrelid \n"
                               4682                 :                           "   AND a.attnum = s.attnum \n"
                               4683                 :                           "   AND NOT a.attisdropped)), \n"
                               4684                 :                           "es.stxrelid::pg_catalog.regclass) AS \"%s\"",
  744 tomas.vondra             4685 EUB             :                           gettext_noop("Definition"));
                               4686                 : 
  809 tomas.vondra             4687 GIC          51 :     appendPQExpBuffer(&buf,
                               4688                 :                       ",\nCASE WHEN 'd' = any(es.stxkind) THEN 'defined' \n"
                               4689                 :                       "END AS \"%s\", \n"
                               4690                 :                       "CASE WHEN 'f' = any(es.stxkind) THEN 'defined' \n"
                               4691                 :                       "END AS \"%s\"",
                               4692                 :                       gettext_noop("Ndistinct"),
                               4693                 :                       gettext_noop("Dependencies"));
                               4694                 : 
                               4695                 :     /*
  809 tomas.vondra             4696 ECB             :      * Include the MCV statistics kind.
                               4697                 :      */
  809 tomas.vondra             4698 GIC          51 :     if (pset.sversion >= 120000)
                               4699                 :     {
                               4700              51 :         appendPQExpBuffer(&buf,
                               4701                 :                           ",\nCASE WHEN 'm' = any(es.stxkind) THEN 'defined' \n"
                               4702                 :                           "END AS \"%s\" ",
                               4703                 :                           gettext_noop("MCV"));
                               4704                 :     }
                               4705                 : 
                               4706              51 :     appendPQExpBufferStr(&buf,
  809 tomas.vondra             4707 ECB             :                          " \nFROM pg_catalog.pg_statistic_ext es \n");
                               4708                 : 
  354 rhaas                    4709 CBC          51 :     if (!validateSQLNamePattern(&buf, pattern,
                               4710                 :                                 false, false,
                               4711                 :                                 "es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text", "es.stxname",
                               4712                 :                                 NULL, "pg_catalog.pg_statistics_obj_is_visible(es.oid)",
                               4713                 :                                 NULL, 3))
                               4714                 :     {
  262 michael                  4715              12 :         termPQExpBuffer(&buf);
  354 rhaas                    4716 GIC          12 :         return false;
                               4717                 :     }
  809 tomas.vondra             4718 ECB             : 
  809 tomas.vondra             4719 GIC          39 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
                               4720                 : 
                               4721              39 :     res = PSQLexec(buf.data);
                               4722              39 :     termPQExpBuffer(&buf);
                               4723              39 :     if (!res)
  809 tomas.vondra             4724 LBC           0 :         return false;
  809 tomas.vondra             4725 ECB             : 
  809 tomas.vondra             4726 GIC          39 :     myopt.nullPrint = NULL;
                               4727              39 :     myopt.title = _("List of extended statistics");
  809 tomas.vondra             4728 CBC          39 :     myopt.translate_header = true;
                               4729                 : 
                               4730              39 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
  809 tomas.vondra             4731 ECB             : 
  809 tomas.vondra             4732 CBC          39 :     PQclear(res);
  809 tomas.vondra             4733 GBC          39 :     return true;
                               4734                 : }
  809 tomas.vondra             4735 ECB             : 
 7423 bruce                    4736                 : /*
                               4737                 :  * \dC
                               4738                 :  *
                               4739                 :  * Describes casts.
                               4740                 :  */
                               4741                 : bool
 4266 rhaas                    4742 CBC          21 : listCasts(const char *pattern, bool verbose)
                               4743                 : {
                               4744                 :     PQExpBufferData buf;
                               4745                 :     PGresult   *res;
 7423 bruce                    4746 GIC          21 :     printQueryOpt myopt = pset.popt;
                               4747                 :     static const bool translate_columns[] = {false, false, false, true, false};
                               4748                 : 
                               4749              21 :     initPQExpBuffer(&buf);
                               4750                 : 
 7423 bruce                    4751 CBC          21 :     printfPQExpBuffer(&buf,
                               4752                 :                       "SELECT pg_catalog.format_type(castsource, NULL) AS \"%s\",\n"
                               4753                 :                       "       pg_catalog.format_type(casttarget, NULL) AS \"%s\",\n",
                               4754                 :                       gettext_noop("Source type"),
 1682 tgl                      4755 ECB             :                       gettext_noop("Target type"));
                               4756                 : 
                               4757                 :     /*
                               4758                 :      * We don't attempt to localize '(binary coercible)' or '(with inout)',
                               4759                 :      * because there's too much risk of gettext translating a function name
                               4760                 :      * that happens to match some string in the PO database.
                               4761                 :      */
  479 tgl                      4762 GIC          21 :     appendPQExpBuffer(&buf,
                               4763                 :                       "       CASE WHEN c.castmethod = '%c' THEN '(binary coercible)'\n"
                               4764                 :                       "            WHEN c.castmethod = '%c' THEN '(with inout)'\n"
                               4765                 :                       "            ELSE p.proname\n"
                               4766                 :                       "       END AS \"%s\",\n",
                               4767                 :                       COERCION_METHOD_BINARY,
                               4768                 :                       COERCION_METHOD_INOUT,
                               4769                 :                       gettext_noop("Function"));
                               4770                 : 
 1682 tgl                      4771 CBC          21 :     appendPQExpBuffer(&buf,
                               4772                 :                       "       CASE WHEN c.castcontext = '%c' THEN '%s'\n"
                               4773                 :                       "            WHEN c.castcontext = '%c' THEN '%s'\n"
                               4774                 :                       "            ELSE '%s'\n"
                               4775                 :                       "       END AS \"%s\"",
                               4776                 :                       COERCION_CODE_EXPLICIT,
                               4777                 :                       gettext_noop("no"),
                               4778                 :                       COERCION_CODE_ASSIGNMENT,
                               4779                 :                       gettext_noop("in assignment"),
 4266 rhaas                    4780 ECB             :                       gettext_noop("yes"),
                               4781                 :                       gettext_noop("Implicit?"));
                               4782                 : 
 4266 rhaas                    4783 GIC          21 :     if (verbose)
 4266 rhaas                    4784 UIC           0 :         appendPQExpBuffer(&buf,
                               4785                 :                           ",\n       d.description AS \"%s\"",
                               4786                 :                           gettext_noop("Description"));
                               4787                 : 
                               4788                 :     /*
                               4789                 :      * We need a left join to pg_proc for binary casts; the others are just
                               4790                 :      * paranoia.
                               4791                 :      */
 3429 heikki.linnakangas       4792 CBC          21 :     appendPQExpBufferStr(&buf,
 1682 tgl                      4793 EUB             :                          "\nFROM pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p\n"
                               4794                 :                          "     ON c.castfunc = p.oid\n"
                               4795                 :                          "     LEFT JOIN pg_catalog.pg_type ts\n"
                               4796                 :                          "     ON c.castsource = ts.oid\n"
                               4797                 :                          "     LEFT JOIN pg_catalog.pg_namespace ns\n"
                               4798                 :                          "     ON ns.oid = ts.typnamespace\n"
                               4799                 :                          "     LEFT JOIN pg_catalog.pg_type tt\n"
                               4800                 :                          "     ON c.casttarget = tt.oid\n"
 3429 heikki.linnakangas       4801 ECB             :                          "     LEFT JOIN pg_catalog.pg_namespace nt\n"
                               4802                 :                          "     ON nt.oid = tt.typnamespace\n");
                               4803                 : 
 4266 rhaas                    4804 GIC          21 :     if (verbose)
 3429 heikki.linnakangas       4805 UIC           0 :         appendPQExpBufferStr(&buf,
                               4806                 :                              "     LEFT JOIN pg_catalog.pg_description d\n"
                               4807                 :                              "     ON d.classoid = c.tableoid AND d.objoid = "
                               4808                 :                              "c.oid AND d.objsubid = 0\n");
                               4809                 : 
 3429 heikki.linnakangas       4810 GIC          21 :     appendPQExpBufferStr(&buf, "WHERE ( (true");
                               4811                 : 
                               4812                 :     /*
 5267 tgl                      4813 ECB             :      * Match name pattern against either internal or external name of either
 5267 tgl                      4814 EUB             :      * castsource or casttarget
                               4815                 :      */
  354 rhaas                    4816 GIC          21 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
                               4817                 :                                 "ns.nspname", "ts.typname",
                               4818                 :                                 "pg_catalog.format_type(ts.oid, NULL)",
  354 rhaas                    4819 ECB             :                                 "pg_catalog.pg_type_is_visible(ts.oid)",
                               4820                 :                                 NULL, 3))
  262 michael                  4821 GIC          12 :         goto error_return;
                               4822                 : 
 3429 heikki.linnakangas       4823               9 :     appendPQExpBufferStr(&buf, ") OR (true");
                               4824                 : 
  354 rhaas                    4825 CBC           9 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
                               4826                 :                                 "nt.nspname", "tt.typname",
                               4827                 :                                 "pg_catalog.format_type(tt.oid, NULL)",
                               4828                 :                                 "pg_catalog.pg_type_is_visible(tt.oid)",
                               4829                 :                                 NULL, 3))
  262 michael                  4830 LBC           0 :         goto error_return;
                               4831                 : 
 3429 heikki.linnakangas       4832 CBC           9 :     appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;");
                               4833                 : 
 3090 fujii                    4834               9 :     res = PSQLexec(buf.data);
 7423 bruce                    4835 GIC           9 :     termPQExpBuffer(&buf);
                               4836               9 :     if (!res)
 7423 bruce                    4837 UIC           0 :         return false;
                               4838                 : 
 7423 bruce                    4839 GBC           9 :     myopt.nullPrint = NULL;
 7423 bruce                    4840 GIC           9 :     myopt.title = _("List of casts");
 5382 bruce                    4841 CBC           9 :     myopt.translate_header = true;
 5382 bruce                    4842 GIC           9 :     myopt.translate_columns = translate_columns;
 3382 tgl                      4843 CBC           9 :     myopt.n_translate_columns = lengthof(translate_columns);
 7423 bruce                    4844 ECB             : 
 2685 tgl                      4845 CBC           9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 7423 bruce                    4846 EUB             : 
 7423 bruce                    4847 GIC           9 :     PQclear(res);
 7423 bruce                    4848 CBC           9 :     return true;
  262 michael                  4849 ECB             : 
  262 michael                  4850 CBC          12 : error_return:
                               4851              12 :     termPQExpBuffer(&buf);
                               4852              12 :     return false;
                               4853                 : }
 7423 bruce                    4854 ECB             : 
                               4855                 : /*
 4439 peter_e                  4856                 :  * \dO
                               4857                 :  *
                               4858                 :  * Describes collations.
                               4859                 :  */
                               4860                 : bool
 4439 peter_e                  4861 CBC          21 : listCollations(const char *pattern, bool verbose, bool showSystem)
                               4862                 : {
                               4863                 :     PQExpBufferData buf;
                               4864                 :     PGresult   *res;
 4439 peter_e                  4865 GIC          21 :     printQueryOpt myopt = pset.popt;
                               4866                 :     static const bool translate_columns[] = {false, false, false, false, false, false, false, true, false};
                               4867                 : 
                               4868              21 :     initPQExpBuffer(&buf);
                               4869                 : 
 4439 peter_e                  4870 CBC          21 :     printfPQExpBuffer(&buf,
                               4871                 :                       "SELECT\n"
                               4872                 :                       "  n.nspname AS \"%s\",\n"
                               4873                 :                       "  c.collname AS \"%s\",\n",
                               4874                 :                       gettext_noop("Schema"),
                               4875                 :                       gettext_noop("Name"));
                               4876                 : 
   32 peter                    4877 GNC          21 :     if (pset.sversion >= 100000)
                               4878              21 :         appendPQExpBuffer(&buf,
                               4879                 :                           "  CASE c.collprovider WHEN 'd' THEN 'default' WHEN 'c' THEN 'libc' WHEN 'i' THEN 'icu' END AS \"%s\",\n",
                               4880                 :                           gettext_noop("Provider"));
                               4881                 :     else
   32 peter                    4882 UNC           0 :         appendPQExpBuffer(&buf,
                               4883                 :                           "  'libc' AS \"%s\",\n",
                               4884                 :                           gettext_noop("Provider"));
                               4885                 : 
   32 peter                    4886 GNC          21 :     appendPQExpBuffer(&buf,
                               4887                 :                       "  c.collcollate AS \"%s\",\n"
                               4888                 :                       "  c.collctype AS \"%s\",\n",
 4439 peter_e                  4889 ECB             :                       gettext_noop("Collate"),
                               4890                 :                       gettext_noop("Ctype"));
                               4891                 : 
  388 peter                    4892 GIC          21 :     if (pset.sversion >= 150000)
                               4893              21 :         appendPQExpBuffer(&buf,
                               4894                 :                           "  c.colliculocale AS \"%s\",\n",
                               4895                 :                           gettext_noop("ICU Locale"));
                               4896                 :     else
  388 peter                    4897 UIC           0 :         appendPQExpBuffer(&buf,
                               4898                 :                           "  c.collcollate AS \"%s\",\n",
  388 peter                    4899 ECB             :                           gettext_noop("ICU Locale"));
                               4900                 : 
   32 peter                    4901 GNC          21 :     if (pset.sversion >= 160000)
 2208 peter_e                  4902 GIC          21 :         appendPQExpBuffer(&buf,
                               4903                 :                           "  c.collicurules AS \"%s\",\n",
                               4904                 :                           gettext_noop("ICU Rules"));
                               4905                 :     else
 1479 peter                    4906 UIC           0 :         appendPQExpBuffer(&buf,
                               4907                 :                           "  NULL AS \"%s\",\n",
                               4908                 :                           gettext_noop("ICU Rules"));
                               4909                 : 
 1479 peter                    4910 GIC          21 :     if (pset.sversion >= 120000)
                               4911              21 :         appendPQExpBuffer(&buf,
                               4912                 :                           "  CASE WHEN c.collisdeterministic THEN '%s' ELSE '%s' END AS \"%s\"",
 1479 peter                    4913 ECB             :                           gettext_noop("yes"), gettext_noop("no"),
                               4914                 :                           gettext_noop("Deterministic?"));
                               4915                 :     else
 1479 peter                    4916 UIC           0 :         appendPQExpBuffer(&buf,
                               4917                 :                           "  '%s' AS \"%s\"",
 1479 peter                    4918 EUB             :                           gettext_noop("yes"),
                               4919                 :                           gettext_noop("Deterministic?"));
                               4920                 : 
 4439 peter_e                  4921 GIC          21 :     if (verbose)
 4439 peter_e                  4922 LBC           0 :         appendPQExpBuffer(&buf,
                               4923                 :                           ",\n  pg_catalog.obj_description(c.oid, 'pg_collation') AS \"%s\"",
                               4924                 :                           gettext_noop("Description"));
                               4925                 : 
 3429 heikki.linnakangas       4926 GIC          21 :     appendPQExpBufferStr(&buf,
 2118 tgl                      4927 EUB             :                          "\nFROM pg_catalog.pg_collation c, pg_catalog.pg_namespace n\n"
                               4928                 :                          "WHERE n.oid = c.collnamespace\n");
                               4929                 : 
 4439 peter_e                  4930 GIC          21 :     if (!showSystem && !pattern)
 3429 heikki.linnakangas       4931 LBC           0 :         appendPQExpBufferStr(&buf, "      AND n.nspname <> 'pg_catalog'\n"
 3260 bruce                    4932 ECB             :                              "      AND n.nspname <> 'information_schema'\n");
                               4933                 : 
                               4934                 :     /*
                               4935                 :      * Hide collations that aren't usable in the current database's encoding.
                               4936                 :      * If you think to change this, note that pg_collation_is_visible rejects
 4383 tgl                      4937 EUB             :      * unusable collations, so you will need to hack name pattern processing
                               4938                 :      * somehow to avoid inconsistent behavior.
                               4939                 :      */
 3429 heikki.linnakangas       4940 GIC          21 :     appendPQExpBufferStr(&buf, "      AND c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))\n");
                               4941                 : 
  354 rhaas                    4942 CBC          21 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
  354 rhaas                    4943 EUB             :                                 "n.nspname", "c.collname", NULL,
                               4944                 :                                 "pg_catalog.pg_collation_is_visible(c.oid)",
                               4945                 :                                 NULL, 3))
                               4946                 :     {
  262 michael                  4947 CBC          12 :         termPQExpBuffer(&buf);
  354 rhaas                    4948 GIC          12 :         return false;
                               4949                 :     }
                               4950                 : 
 3429 heikki.linnakangas       4951 CBC           9 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 4439 peter_e                  4952 EUB             : 
 3090 fujii                    4953 GIC           9 :     res = PSQLexec(buf.data);
 4439 peter_e                  4954               9 :     termPQExpBuffer(&buf);
                               4955               9 :     if (!res)
 4439 peter_e                  4956 UIC           0 :         return false;
                               4957                 : 
 4439 peter_e                  4958 GIC           9 :     myopt.nullPrint = NULL;
                               4959               9 :     myopt.title = _("List of collations");
                               4960               9 :     myopt.translate_header = true;
 4439 peter_e                  4961 CBC           9 :     myopt.translate_columns = translate_columns;
 3382 tgl                      4962 GIC           9 :     myopt.n_translate_columns = lengthof(translate_columns);
 4439 peter_e                  4963 ECB             : 
 2685 tgl                      4964 GIC           9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               4965                 : 
 4439 peter_e                  4966               9 :     PQclear(res);
                               4967               9 :     return true;
 4439 peter_e                  4968 ECB             : }
                               4969                 : 
                               4970                 : /*
                               4971                 :  * \dn
 7397 tgl                      4972                 :  *
                               4973                 :  * Describes schemas (namespaces)
                               4974                 :  */
                               4975                 : bool
 4537 tgl                      4976 CBC          12 : listSchemas(const char *pattern, bool verbose, bool showSystem)
 7397 tgl                      4977 EUB             : {
                               4978                 :     PQExpBufferData buf;
 7397 tgl                      4979 ECB             :     PGresult   *res;
 7397 tgl                      4980 CBC          12 :     printQueryOpt myopt = pset.popt;
  529 akapila                  4981              12 :     int         pub_schema_tuples = 0;
                               4982              12 :     char      **footers = NULL;
 7397 tgl                      4983 ECB             : 
 7397 tgl                      4984 GIC          12 :     initPQExpBuffer(&buf);
 7397 tgl                      4985 CBC          12 :     printfPQExpBuffer(&buf,
                               4986                 :                       "SELECT n.nspname AS \"%s\",\n"
 5393 tgl                      4987 ECB             :                       "  pg_catalog.pg_get_userbyid(n.nspowner) AS \"%s\"",
 5597                          4988                 :                       gettext_noop("Name"),
                               4989                 :                       gettext_noop("Owner"));
                               4990                 : 
 6844 bruce                    4991 GIC          12 :     if (verbose)
                               4992                 :     {
 3429 heikki.linnakangas       4993 UIC           0 :         appendPQExpBufferStr(&buf, ",\n  ");
 5212 tgl                      4994               0 :         printACLColumn(&buf, "n.nspacl");
 6844 bruce                    4995               0 :         appendPQExpBuffer(&buf,
                               4996                 :                           ",\n  pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"",
 5597 tgl                      4997 ECB             :                           gettext_noop("Description"));
                               4998                 :     }
                               4999                 : 
 1375 drowley                  5000 GIC          12 :     appendPQExpBufferStr(&buf,
 1375 drowley                  5001 ECB             :                          "\nFROM pg_catalog.pg_namespace n\n");
 6844 bruce                    5002                 : 
 4537 tgl                      5003 CBC          12 :     if (!showSystem && !pattern)
 3429 heikki.linnakangas       5004 UIC           0 :         appendPQExpBufferStr(&buf,
 2118 tgl                      5005 ECB             :                              "WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'\n");
 4537                          5006                 : 
  354 rhaas                    5007 GIC          12 :     if (!validateSQLNamePattern(&buf, pattern,
                               5008              12 :                                 !showSystem && !pattern, false,
                               5009                 :                                 NULL, "n.nspname", NULL,
                               5010                 :                                 NULL,
                               5011                 :                                 NULL, 2))
  262 michael                  5012 CBC           9 :         goto error_return;
                               5013                 : 
 3429 heikki.linnakangas       5014 GBC           3 :     appendPQExpBufferStr(&buf, "ORDER BY 1;");
 7397 tgl                      5015 EUB             : 
 3090 fujii                    5016 GBC           3 :     res = PSQLexec(buf.data);
 7397 tgl                      5017 GIC           3 :     if (!res)
  262 michael                  5018 UIC           0 :         goto error_return;
                               5019                 : 
 7397 tgl                      5020 GIC           3 :     myopt.nullPrint = NULL;
 7397 tgl                      5021 CBC           3 :     myopt.title = _("List of schemas");
 5382 bruce                    5022 GIC           3 :     myopt.translate_header = true;
                               5023                 : 
  529 akapila                  5024 CBC           3 :     if (pattern && pset.sversion >= 150000)
  529 akapila                  5025 EUB             :     {
                               5026                 :         PGresult   *result;
                               5027                 :         int         i;
  529 akapila                  5028 ECB             : 
  529 akapila                  5029 CBC           3 :         printfPQExpBuffer(&buf,
                               5030                 :                           "SELECT pubname \n"
                               5031                 :                           "FROM pg_catalog.pg_publication p\n"
                               5032                 :                           "     JOIN pg_catalog.pg_publication_namespace pn ON p.oid = pn.pnpubid\n"
  334 peter                    5033 ECB             :                           "     JOIN pg_catalog.pg_namespace n ON n.oid = pn.pnnspid \n"
                               5034                 :                           "WHERE n.nspname = '%s'\n"
  529 akapila                  5035                 :                           "ORDER BY 1",
                               5036                 :                           pattern);
  529 akapila                  5037 CBC           3 :         result = PSQLexec(buf.data);
                               5038               3 :         if (!result)
  262 michael                  5039 UBC           0 :             goto error_return;
                               5040                 :         else
  529 akapila                  5041 CBC           3 :             pub_schema_tuples = PQntuples(result);
  529 akapila                  5042 ECB             : 
  529 akapila                  5043 CBC           3 :         if (pub_schema_tuples > 0)
                               5044                 :         {
  529 akapila                  5045 ECB             :             /*
                               5046                 :              * Allocate memory for footers. Size of footers will be 1 (for
                               5047                 :              * storing "Publications:" string) + publication schema mapping
                               5048                 :              * count +  1 (for storing NULL).
                               5049                 :              */
  529 akapila                  5050 LBC           0 :             footers = (char **) pg_malloc((1 + pub_schema_tuples + 1) * sizeof(char *));
  529 akapila                  5051 UIC           0 :             footers[0] = pg_strdup(_("Publications:"));
                               5052                 : 
                               5053                 :             /* Might be an empty set - that's ok */
                               5054               0 :             for (i = 0; i < pub_schema_tuples; i++)
                               5055                 :             {
  367 tomas.vondra             5056               0 :                 printfPQExpBuffer(&buf, "    \"%s\"",
                               5057                 :                                   PQgetvalue(result, i, 0));
  529 akapila                  5058 ECB             : 
  529 akapila                  5059 LBC           0 :                 footers[i + 1] = pg_strdup(buf.data);
  529 akapila                  5060 EUB             :             }
                               5061                 : 
  529 akapila                  5062 LBC           0 :             footers[i + 1] = NULL;
  529 akapila                  5063 UIC           0 :             myopt.footers = footers;
  529 akapila                  5064 ECB             :         }
                               5065                 : 
  529 akapila                  5066 GIC           3 :         PQclear(result);
                               5067                 :     }
                               5068                 : 
 2685 tgl                      5069               3 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               5070                 : 
  529 akapila                  5071 GBC           3 :     termPQExpBuffer(&buf);
 7397 tgl                      5072               3 :     PQclear(res);
                               5073                 : 
                               5074                 :     /* Free the memory allocated for the footer */
  529 akapila                  5075               3 :     if (footers)
                               5076                 :     {
  529 akapila                  5077 UBC           0 :         char      **footer = NULL;
                               5078                 : 
  529 akapila                  5079 UIC           0 :         for (footer = footers; *footer; footer++)
  529 akapila                  5080 UBC           0 :             pg_free(*footer);
                               5081                 : 
  529 akapila                  5082 UIC           0 :         pg_free(footers);
  529 akapila                  5083 EUB             :     }
                               5084                 : 
 7397 tgl                      5085 GIC           3 :     return true;
                               5086                 : 
  262 michael                  5087 CBC           9 : error_return:
  262 michael                  5088 GIC           9 :     termPQExpBuffer(&buf);
                               5089               9 :     return false;
 7397 tgl                      5090 ECB             : }
                               5091                 : 
 5710                          5092                 : 
                               5093                 : /*
                               5094                 :  * \dFp
                               5095                 :  * list text search parsers
                               5096                 :  */
                               5097                 : bool
 5710 tgl                      5098 GBC          21 : listTSParsers(const char *pattern, bool verbose)
                               5099                 : {
 5710 tgl                      5100 EUB             :     PQExpBufferData buf;
                               5101                 :     PGresult   *res;
 5710 tgl                      5102 GIC          21 :     printQueryOpt myopt = pset.popt;
 5710 tgl                      5103 EUB             : 
 5710 tgl                      5104 GIC          21 :     if (verbose)
 5710 tgl                      5105 UIC           0 :         return listTSParsersVerbose(pattern);
 5710 tgl                      5106 ECB             : 
 5710 tgl                      5107 GIC          21 :     initPQExpBuffer(&buf);
 5710 tgl                      5108 ECB             : 
 5710 tgl                      5109 CBC          21 :     printfPQExpBuffer(&buf,
 2187 peter_e                  5110 ECB             :                       "SELECT\n"
                               5111                 :                       "  n.nspname as \"%s\",\n"
                               5112                 :                       "  p.prsname as \"%s\",\n"
                               5113                 :                       "  pg_catalog.obj_description(p.oid, 'pg_ts_parser') as \"%s\"\n"
                               5114                 :                       "FROM pg_catalog.pg_ts_parser p\n"
                               5115                 :                       "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n",
                               5116                 :                       gettext_noop("Schema"),
                               5117                 :                       gettext_noop("Name"),
                               5118                 :                       gettext_noop("Description")
 5710 tgl                      5119                 :         );
                               5120                 : 
  354 rhaas                    5121 GIC          21 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                               5122                 :                                 "n.nspname", "p.prsname", NULL,
  354 rhaas                    5123 ECB             :                                 "pg_catalog.pg_ts_parser_is_visible(p.oid)",
                               5124                 :                                 NULL, 3))
  262 michael                  5125                 :     {
  262 michael                  5126 GBC          12 :         termPQExpBuffer(&buf);
  354 rhaas                    5127 GIC          12 :         return false;
  262 michael                  5128 ECB             :     }
                               5129                 : 
 3429 heikki.linnakangas       5130 CBC           9 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
                               5131                 : 
 3090 fujii                    5132 GIC           9 :     res = PSQLexec(buf.data);
 5710 tgl                      5133               9 :     termPQExpBuffer(&buf);
                               5134               9 :     if (!res)
 5710 tgl                      5135 UIC           0 :         return false;
                               5136                 : 
 5710 tgl                      5137 GIC           9 :     myopt.nullPrint = NULL;
                               5138               9 :     myopt.title = _("List of text search parsers");
 5382 bruce                    5139               9 :     myopt.translate_header = true;
                               5140                 : 
 2685 tgl                      5141               9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 5710 tgl                      5142 ECB             : 
 5710 tgl                      5143 GIC           9 :     PQclear(res);
                               5144               9 :     return true;
                               5145                 : }
                               5146                 : 
 5710 tgl                      5147 ECB             : /*
                               5148                 :  * full description of parsers
                               5149                 :  */
                               5150                 : static bool
 5710 tgl                      5151 LBC           0 : listTSParsersVerbose(const char *pattern)
                               5152                 : {
 5710 tgl                      5153 ECB             :     PQExpBufferData buf;
                               5154                 :     PGresult   *res;
                               5155                 :     int         i;
 5710 tgl                      5156 EUB             : 
 5710 tgl                      5157 UIC           0 :     initPQExpBuffer(&buf);
 5710 tgl                      5158 ECB             : 
 5710 tgl                      5159 LBC           0 :     printfPQExpBuffer(&buf,
 2187 peter_e                  5160 ECB             :                       "SELECT p.oid,\n"
                               5161                 :                       "  n.nspname,\n"
                               5162                 :                       "  p.prsname\n"
                               5163                 :                       "FROM pg_catalog.pg_ts_parser p\n"
 2118 tgl                      5164                 :                       "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n"
 5710                          5165                 :         );
                               5166                 : 
  354 rhaas                    5167 UIC           0 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                               5168                 :                                 "n.nspname", "p.prsname", NULL,
                               5169                 :                                 "pg_catalog.pg_ts_parser_is_visible(p.oid)",
                               5170                 :                                 NULL, 3))
                               5171                 :     {
  262 michael                  5172 UBC           0 :         termPQExpBuffer(&buf);
  354 rhaas                    5173 UIC           0 :         return false;
                               5174                 :     }
                               5175                 : 
 3429 heikki.linnakangas       5176               0 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
                               5177                 : 
 3090 fujii                    5178 UBC           0 :     res = PSQLexec(buf.data);
 5710 tgl                      5179 UIC           0 :     termPQExpBuffer(&buf);
 5710 tgl                      5180 UBC           0 :     if (!res)
 5710 tgl                      5181 UIC           0 :         return false;
                               5182                 : 
                               5183               0 :     if (PQntuples(res) == 0)
                               5184                 :     {
                               5185               0 :         if (!pset.quiet)
                               5186                 :         {
 2082                          5187               0 :             if (pattern)
 1469 peter                    5188 UBC           0 :                 pg_log_error("Did not find any text search parser named \"%s\".",
                               5189                 :                              pattern);
                               5190                 :             else
 1469 peter                    5191 UIC           0 :                 pg_log_error("Did not find any text search parsers.");
                               5192                 :         }
 5710 tgl                      5193 UBC           0 :         PQclear(res);
                               5194               0 :         return false;
                               5195                 :     }
                               5196                 : 
                               5197               0 :     for (i = 0; i < PQntuples(res); i++)
                               5198                 :     {
 5710 tgl                      5199 EUB             :         const char *oid;
 5710 tgl                      5200 UBC           0 :         const char *nspname = NULL;
 5710 tgl                      5201 EUB             :         const char *prsname;
                               5202                 : 
 5710 tgl                      5203 UIC           0 :         oid = PQgetvalue(res, i, 0);
 5710 tgl                      5204 UBC           0 :         if (!PQgetisnull(res, i, 1))
 5710 tgl                      5205 UIC           0 :             nspname = PQgetvalue(res, i, 1);
 5710 tgl                      5206 UBC           0 :         prsname = PQgetvalue(res, i, 2);
                               5207                 : 
                               5208               0 :         if (!describeOneTSParser(oid, nspname, prsname))
 5710 tgl                      5209 EUB             :         {
 5710 tgl                      5210 UIC           0 :             PQclear(res);
                               5211               0 :             return false;
 5710 tgl                      5212 EUB             :         }
                               5213                 : 
 5710 tgl                      5214 UBC           0 :         if (cancel_pressed)
 5710 tgl                      5215 EUB             :         {
 5710 tgl                      5216 UIC           0 :             PQclear(res);
                               5217               0 :             return false;
 5710 tgl                      5218 EUB             :         }
                               5219                 :     }
                               5220                 : 
 5710 tgl                      5221 UBC           0 :     PQclear(res);
 5710 tgl                      5222 UIC           0 :     return true;
                               5223                 : }
 5710 tgl                      5224 EUB             : 
                               5225                 : static bool
 5710 tgl                      5226 UBC           0 : describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
 5710 tgl                      5227 EUB             : {
                               5228                 :     PQExpBufferData buf;
                               5229                 :     PGresult   *res;
                               5230                 :     PQExpBufferData title;
 5710 tgl                      5231 UBC           0 :     printQueryOpt myopt = pset.popt;
 5382 bruce                    5232 EUB             :     static const bool translate_columns[] = {true, false, false};
                               5233                 : 
 5710 tgl                      5234 UIC           0 :     initPQExpBuffer(&buf);
 5710 tgl                      5235 EUB             : 
 5710 tgl                      5236 UIC           0 :     printfPQExpBuffer(&buf,
 2187 peter_e                  5237 EUB             :                       "SELECT '%s' AS \"%s\",\n"
                               5238                 :                       "   p.prsstart::pg_catalog.regproc AS \"%s\",\n"
                               5239                 :                       "   pg_catalog.obj_description(p.prsstart, 'pg_proc') as \"%s\"\n"
                               5240                 :                       " FROM pg_catalog.pg_ts_parser p\n"
                               5241                 :                       " WHERE p.oid = '%s'\n"
                               5242                 :                       "UNION ALL\n"
                               5243                 :                       "SELECT '%s',\n"
                               5244                 :                       "   p.prstoken::pg_catalog.regproc,\n"
                               5245                 :                       "   pg_catalog.obj_description(p.prstoken, 'pg_proc')\n"
                               5246                 :                       " FROM pg_catalog.pg_ts_parser p\n"
                               5247                 :                       " WHERE p.oid = '%s'\n"
                               5248                 :                       "UNION ALL\n"
                               5249                 :                       "SELECT '%s',\n"
                               5250                 :                       "   p.prsend::pg_catalog.regproc,\n"
                               5251                 :                       "   pg_catalog.obj_description(p.prsend, 'pg_proc')\n"
                               5252                 :                       " FROM pg_catalog.pg_ts_parser p\n"
                               5253                 :                       " WHERE p.oid = '%s'\n"
                               5254                 :                       "UNION ALL\n"
                               5255                 :                       "SELECT '%s',\n"
                               5256                 :                       "   p.prsheadline::pg_catalog.regproc,\n"
 2118 tgl                      5257                 :                       "   pg_catalog.obj_description(p.prsheadline, 'pg_proc')\n"
                               5258                 :                       " FROM pg_catalog.pg_ts_parser p\n"
                               5259                 :                       " WHERE p.oid = '%s'\n"
                               5260                 :                       "UNION ALL\n"
                               5261                 :                       "SELECT '%s',\n"
                               5262                 :                       "   p.prslextype::pg_catalog.regproc,\n"
                               5263                 :                       "   pg_catalog.obj_description(p.prslextype, 'pg_proc')\n"
                               5264                 :                       " FROM pg_catalog.pg_ts_parser p\n"
                               5265                 :                       " WHERE p.oid = '%s';",
                               5266                 :                       gettext_noop("Start parse"),
                               5267                 :                       gettext_noop("Method"),
                               5268                 :                       gettext_noop("Function"),
                               5269                 :                       gettext_noop("Description"),
                               5270                 :                       oid,
                               5271                 :                       gettext_noop("Get next token"),
                               5272                 :                       oid,
                               5273                 :                       gettext_noop("End parse"),
                               5274                 :                       oid,
                               5275                 :                       gettext_noop("Get headline"),
                               5276                 :                       oid,
                               5277                 :                       gettext_noop("Get token types"),
                               5278                 :                       oid);
                               5279                 : 
 3090 fujii                    5280 UIC           0 :     res = PSQLexec(buf.data);
 5710 tgl                      5281               0 :     termPQExpBuffer(&buf);
                               5282               0 :     if (!res)
                               5283               0 :         return false;
                               5284                 : 
                               5285               0 :     myopt.nullPrint = NULL;
 2082                          5286               0 :     initPQExpBuffer(&title);
 5710                          5287               0 :     if (nspname)
 2082                          5288               0 :         printfPQExpBuffer(&title, _("Text search parser \"%s.%s\""),
                               5289                 :                           nspname, prsname);
                               5290                 :     else
                               5291               0 :         printfPQExpBuffer(&title, _("Text search parser \"%s\""), prsname);
                               5292               0 :     myopt.title = title.data;
 5710                          5293               0 :     myopt.footers = NULL;
 3995 rhaas                    5294               0 :     myopt.topt.default_footer = false;
 5382 bruce                    5295               0 :     myopt.translate_header = true;
                               5296               0 :     myopt.translate_columns = translate_columns;
 3382 tgl                      5297               0 :     myopt.n_translate_columns = lengthof(translate_columns);
                               5298                 : 
 2685                          5299               0 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               5300                 : 
 5710 tgl                      5301 UBC           0 :     PQclear(res);
 5710 tgl                      5302 EUB             : 
 5710 tgl                      5303 UBC           0 :     initPQExpBuffer(&buf);
 5710 tgl                      5304 EUB             : 
 5710 tgl                      5305 UIC           0 :     printfPQExpBuffer(&buf,
 2187 peter_e                  5306 EUB             :                       "SELECT t.alias as \"%s\",\n"
                               5307                 :                       "  t.description as \"%s\"\n"
 2118 tgl                      5308                 :                       "FROM pg_catalog.ts_token_type( '%s'::pg_catalog.oid ) as t\n"
 5710                          5309                 :                       "ORDER BY 1;",
                               5310                 :                       gettext_noop("Token name"),
                               5311                 :                       gettext_noop("Description"),
                               5312                 :                       oid);
                               5313                 : 
 3090 fujii                    5314 UBC           0 :     res = PSQLexec(buf.data);
 5710 tgl                      5315               0 :     termPQExpBuffer(&buf);
                               5316               0 :     if (!res)
  262 michael                  5317 EUB             :     {
  262 michael                  5318 UBC           0 :         termPQExpBuffer(&title);
 5710 tgl                      5319 UIC           0 :         return false;
  262 michael                  5320 EUB             :     }
                               5321                 : 
 5710 tgl                      5322 UBC           0 :     myopt.nullPrint = NULL;
 5710 tgl                      5323 UIC           0 :     if (nspname)
 2082 tgl                      5324 UBC           0 :         printfPQExpBuffer(&title, _("Token types for parser \"%s.%s\""),
                               5325                 :                           nspname, prsname);
 5710 tgl                      5326 EUB             :     else
 2082 tgl                      5327 UIC           0 :         printfPQExpBuffer(&title, _("Token types for parser \"%s\""), prsname);
                               5328               0 :     myopt.title = title.data;
 5710                          5329               0 :     myopt.footers = NULL;
 3995 rhaas                    5330               0 :     myopt.topt.default_footer = true;
 5382 bruce                    5331               0 :     myopt.translate_header = true;
                               5332               0 :     myopt.translate_columns = NULL;
 3382 tgl                      5333               0 :     myopt.n_translate_columns = 0;
                               5334                 : 
 2685 tgl                      5335 UBC           0 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 5710 tgl                      5336 EUB             : 
 2082 tgl                      5337 UBC           0 :     termPQExpBuffer(&title);
 5710 tgl                      5338 UIC           0 :     PQclear(res);
 5710 tgl                      5339 UBC           0 :     return true;
 5710 tgl                      5340 EUB             : }
                               5341                 : 
                               5342                 : 
                               5343                 : /*
                               5344                 :  * \dFd
                               5345                 :  * list text search dictionaries
                               5346                 :  */
                               5347                 : bool
 5710 tgl                      5348 GBC          21 : listTSDictionaries(const char *pattern, bool verbose)
 5710 tgl                      5349 EUB             : {
                               5350                 :     PQExpBufferData buf;
                               5351                 :     PGresult   *res;
 5710 tgl                      5352 GBC          21 :     printQueryOpt myopt = pset.popt;
 5710 tgl                      5353 EUB             : 
 5710 tgl                      5354 GBC          21 :     initPQExpBuffer(&buf);
                               5355                 : 
                               5356              21 :     printfPQExpBuffer(&buf,
                               5357                 :                       "SELECT\n"
 5710 tgl                      5358 EUB             :                       "  n.nspname as \"%s\",\n"
                               5359                 :                       "  d.dictname as \"%s\",\n",
 5597                          5360                 :                       gettext_noop("Schema"),
                               5361                 :                       gettext_noop("Name"));
                               5362                 : 
 5710 tgl                      5363 GIC          21 :     if (verbose)
                               5364                 :     {
 5710 tgl                      5365 UIC           0 :         appendPQExpBuffer(&buf,
                               5366                 :                           "  ( SELECT COALESCE(nt.nspname, '(null)')::pg_catalog.text || '.' || t.tmplname FROM\n"
                               5367                 :                           "    pg_catalog.pg_ts_template t\n"
                               5368                 :                           "    LEFT JOIN pg_catalog.pg_namespace nt ON nt.oid = t.tmplnamespace\n"
 2187 peter_e                  5369 ECB             :                           "    WHERE d.dicttemplate = t.oid ) AS  \"%s\",\n"
                               5370                 :                           "  d.dictinitoption as \"%s\",\n",
                               5371                 :                           gettext_noop("Template"),
                               5372                 :                           gettext_noop("Init options"));
 5710 tgl                      5373                 :     }
                               5374                 : 
 5710 tgl                      5375 CBC          21 :     appendPQExpBuffer(&buf,
                               5376                 :                       "  pg_catalog.obj_description(d.oid, 'pg_ts_dict') as \"%s\"\n",
 5597 tgl                      5377 ECB             :                       gettext_noop("Description"));
                               5378                 : 
 3429 heikki.linnakangas       5379 GIC          21 :     appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_dict d\n"
                               5380                 :                          "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace\n");
                               5381                 : 
  354 rhaas                    5382              21 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                               5383                 :                                 "n.nspname", "d.dictname", NULL,
  354 rhaas                    5384 ECB             :                                 "pg_catalog.pg_ts_dict_is_visible(d.oid)",
                               5385                 :                                 NULL, 3))
  262 michael                  5386 EUB             :     {
  262 michael                  5387 GIC          12 :         termPQExpBuffer(&buf);
  354 rhaas                    5388              12 :         return false;
                               5389                 :     }
                               5390                 : 
 3429 heikki.linnakangas       5391               9 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
                               5392                 : 
 3090 fujii                    5393               9 :     res = PSQLexec(buf.data);
 5710 tgl                      5394               9 :     termPQExpBuffer(&buf);
                               5395               9 :     if (!res)
 5710 tgl                      5396 LBC           0 :         return false;
                               5397                 : 
 5710 tgl                      5398 GIC           9 :     myopt.nullPrint = NULL;
                               5399               9 :     myopt.title = _("List of text search dictionaries");
 5382 bruce                    5400 CBC           9 :     myopt.translate_header = true;
                               5401                 : 
 2685 tgl                      5402 GIC           9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 5710 tgl                      5403 ECB             : 
 5710 tgl                      5404 GIC           9 :     PQclear(res);
                               5405               9 :     return true;
                               5406                 : }
                               5407                 : 
 5710 tgl                      5408 ECB             : 
                               5409                 : /*
                               5410                 :  * \dFt
                               5411                 :  * list text search templates
                               5412                 :  */
                               5413                 : bool
 5710 tgl                      5414 CBC          21 : listTSTemplates(const char *pattern, bool verbose)
 5710 tgl                      5415 ECB             : {
                               5416                 :     PQExpBufferData buf;
 5710 tgl                      5417 EUB             :     PGresult   *res;
 5710 tgl                      5418 GIC          21 :     printQueryOpt myopt = pset.popt;
 5710 tgl                      5419 ECB             : 
 5710 tgl                      5420 CBC          21 :     initPQExpBuffer(&buf);
 5710 tgl                      5421 ECB             : 
 5709 tgl                      5422 GIC          21 :     if (verbose)
 5709 tgl                      5423 LBC           0 :         printfPQExpBuffer(&buf,
                               5424                 :                           "SELECT\n"
 5709 tgl                      5425 ECB             :                           "  n.nspname AS \"%s\",\n"
                               5426                 :                           "  t.tmplname AS \"%s\",\n"
                               5427                 :                           "  t.tmplinit::pg_catalog.regproc AS \"%s\",\n"
                               5428                 :                           "  t.tmpllexize::pg_catalog.regproc AS \"%s\",\n"
                               5429                 :                           "  pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
                               5430                 :                           gettext_noop("Schema"),
                               5431                 :                           gettext_noop("Name"),
                               5432                 :                           gettext_noop("Init"),
                               5433                 :                           gettext_noop("Lexize"),
                               5434                 :                           gettext_noop("Description"));
                               5435                 :     else
 5709 tgl                      5436 GIC          21 :         printfPQExpBuffer(&buf,
                               5437                 :                           "SELECT\n"
                               5438                 :                           "  n.nspname AS \"%s\",\n"
 5709 tgl                      5439 ECB             :                           "  t.tmplname AS \"%s\",\n"
                               5440                 :                           "  pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n",
 5597                          5441                 :                           gettext_noop("Schema"),
                               5442                 :                           gettext_noop("Name"),
                               5443                 :                           gettext_noop("Description"));
 5710 tgl                      5444 EUB             : 
 3429 heikki.linnakangas       5445 GIC          21 :     appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_template t\n"
                               5446                 :                          "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.tmplnamespace\n");
                               5447                 : 
  354 rhaas                    5448              21 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                               5449                 :                                 "n.nspname", "t.tmplname", NULL,
                               5450                 :                                 "pg_catalog.pg_ts_template_is_visible(t.oid)",
                               5451                 :                                 NULL, 3))
                               5452                 :     {
  262 michael                  5453              12 :         termPQExpBuffer(&buf);
  354 rhaas                    5454              12 :         return false;
                               5455                 :     }
                               5456                 : 
 3429 heikki.linnakangas       5457 CBC           9 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
                               5458                 : 
 3090 fujii                    5459 GIC           9 :     res = PSQLexec(buf.data);
 5710 tgl                      5460               9 :     termPQExpBuffer(&buf);
                               5461               9 :     if (!res)
 5710 tgl                      5462 UIC           0 :         return false;
                               5463                 : 
 5710 tgl                      5464 GIC           9 :     myopt.nullPrint = NULL;
                               5465               9 :     myopt.title = _("List of text search templates");
 5382 bruce                    5466 CBC           9 :     myopt.translate_header = true;
                               5467                 : 
 2685 tgl                      5468 GIC           9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 5710 tgl                      5469 ECB             : 
 5710 tgl                      5470 GIC           9 :     PQclear(res);
                               5471               9 :     return true;
                               5472                 : }
                               5473                 : 
 5710 tgl                      5474 ECB             : 
                               5475                 : /*
                               5476                 :  * \dF
                               5477                 :  * list text search configurations
                               5478                 :  */
                               5479                 : bool
 5710 tgl                      5480 CBC          21 : listTSConfigs(const char *pattern, bool verbose)
 5710 tgl                      5481 ECB             : {
                               5482                 :     PQExpBufferData buf;
 5710 tgl                      5483 EUB             :     PGresult   *res;
 5710 tgl                      5484 GIC          21 :     printQueryOpt myopt = pset.popt;
 5710 tgl                      5485 ECB             : 
 5710 tgl                      5486 CBC          21 :     if (verbose)
 5710 tgl                      5487 LBC           0 :         return listTSConfigsVerbose(pattern);
                               5488                 : 
 5710 tgl                      5489 CBC          21 :     initPQExpBuffer(&buf);
                               5490                 : 
                               5491              21 :     printfPQExpBuffer(&buf,
 2187 peter_e                  5492 ECB             :                       "SELECT\n"
                               5493                 :                       "   n.nspname as \"%s\",\n"
                               5494                 :                       "   c.cfgname as \"%s\",\n"
                               5495                 :                       "   pg_catalog.obj_description(c.oid, 'pg_ts_config') as \"%s\"\n"
                               5496                 :                       "FROM pg_catalog.pg_ts_config c\n"
                               5497                 :                       "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace\n",
                               5498                 :                       gettext_noop("Schema"),
                               5499                 :                       gettext_noop("Name"),
                               5500                 :                       gettext_noop("Description")
 5710 tgl                      5501                 :         );
                               5502                 : 
  354 rhaas                    5503 GIC          21 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                               5504                 :                                 "n.nspname", "c.cfgname", NULL,
  354 rhaas                    5505 ECB             :                                 "pg_catalog.pg_ts_config_is_visible(c.oid)",
                               5506                 :                                 NULL, 3))
  262 michael                  5507                 :     {
  262 michael                  5508 GBC          12 :         termPQExpBuffer(&buf);
  354 rhaas                    5509 GIC          12 :         return false;
  262 michael                  5510 ECB             :     }
                               5511                 : 
 3429 heikki.linnakangas       5512 CBC           9 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
                               5513                 : 
 3090 fujii                    5514 GIC           9 :     res = PSQLexec(buf.data);
 5710 tgl                      5515               9 :     termPQExpBuffer(&buf);
                               5516               9 :     if (!res)
 5710 tgl                      5517 UIC           0 :         return false;
                               5518                 : 
 5710 tgl                      5519 GIC           9 :     myopt.nullPrint = NULL;
                               5520               9 :     myopt.title = _("List of text search configurations");
 5382 bruce                    5521               9 :     myopt.translate_header = true;
                               5522                 : 
 2685 tgl                      5523               9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 5710 tgl                      5524 ECB             : 
 5710 tgl                      5525 GIC           9 :     PQclear(res);
                               5526               9 :     return true;
                               5527                 : }
                               5528                 : 
 5710 tgl                      5529 ECB             : static bool
 5710 tgl                      5530 LBC           0 : listTSConfigsVerbose(const char *pattern)
                               5531                 : {
                               5532                 :     PQExpBufferData buf;
 5710 tgl                      5533 ECB             :     PGresult   *res;
                               5534                 :     int         i;
                               5535                 : 
 5710 tgl                      5536 LBC           0 :     initPQExpBuffer(&buf);
 5710 tgl                      5537 ECB             : 
 5710 tgl                      5538 UBC           0 :     printfPQExpBuffer(&buf,
                               5539                 :                       "SELECT c.oid, c.cfgname,\n"
 2187 peter_e                  5540 ECB             :                       "   n.nspname,\n"
                               5541                 :                       "   p.prsname,\n"
                               5542                 :                       "   np.nspname as pnspname\n"
                               5543                 :                       "FROM pg_catalog.pg_ts_config c\n"
 2118 tgl                      5544                 :                       "   LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace,\n"
                               5545                 :                       " pg_catalog.pg_ts_parser p\n"
                               5546                 :                       "   LEFT JOIN pg_catalog.pg_namespace np ON np.oid = p.prsnamespace\n"
 5710                          5547                 :                       "WHERE  p.oid = c.cfgparser\n"
                               5548                 :         );
                               5549                 : 
  354 rhaas                    5550 UIC           0 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
  354 rhaas                    5551 EUB             :                                 "n.nspname", "c.cfgname", NULL,
                               5552                 :                                 "pg_catalog.pg_ts_config_is_visible(c.oid)",
                               5553                 :                                 NULL, 3))
                               5554                 :     {
  262 michael                  5555 UIC           0 :         termPQExpBuffer(&buf);
  354 rhaas                    5556               0 :         return false;
  262 michael                  5557 EUB             :     }
                               5558                 : 
 3429 heikki.linnakangas       5559 UBC           0 :     appendPQExpBufferStr(&buf, "ORDER BY 3, 2;");
                               5560                 : 
 3090 fujii                    5561 UIC           0 :     res = PSQLexec(buf.data);
 5710 tgl                      5562               0 :     termPQExpBuffer(&buf);
                               5563               0 :     if (!res)
                               5564               0 :         return false;
                               5565                 : 
                               5566               0 :     if (PQntuples(res) == 0)
                               5567                 :     {
                               5568               0 :         if (!pset.quiet)
                               5569                 :         {
 2082                          5570               0 :             if (pattern)
 1469 peter                    5571 UBC           0 :                 pg_log_error("Did not find any text search configuration named \"%s\".",
                               5572                 :                              pattern);
                               5573                 :             else
 1469 peter                    5574 UIC           0 :                 pg_log_error("Did not find any text search configurations.");
                               5575                 :         }
 5710 tgl                      5576 UBC           0 :         PQclear(res);
                               5577               0 :         return false;
                               5578                 :     }
                               5579                 : 
                               5580               0 :     for (i = 0; i < PQntuples(res); i++)
                               5581                 :     {
 5710 tgl                      5582 EUB             :         const char *oid;
                               5583                 :         const char *cfgname;
 5710 tgl                      5584 UBC           0 :         const char *nspname = NULL;
 5710 tgl                      5585 EUB             :         const char *prsname;
 5710 tgl                      5586 UIC           0 :         const char *pnspname = NULL;
 5710 tgl                      5587 EUB             : 
 5710 tgl                      5588 UIC           0 :         oid = PQgetvalue(res, i, 0);
 5710 tgl                      5589 UBC           0 :         cfgname = PQgetvalue(res, i, 1);
 5710 tgl                      5590 UIC           0 :         if (!PQgetisnull(res, i, 2))
 5710 tgl                      5591 UBC           0 :             nspname = PQgetvalue(res, i, 2);
                               5592               0 :         prsname = PQgetvalue(res, i, 3);
 5710 tgl                      5593 UIC           0 :         if (!PQgetisnull(res, i, 4))
                               5594               0 :             pnspname = PQgetvalue(res, i, 4);
 5710 tgl                      5595 EUB             : 
 5710 tgl                      5596 UIC           0 :         if (!describeOneTSConfig(oid, nspname, cfgname, pnspname, prsname))
 5710 tgl                      5597 EUB             :         {
 5710 tgl                      5598 UBC           0 :             PQclear(res);
 5710 tgl                      5599 UIC           0 :             return false;
                               5600                 :         }
 5710 tgl                      5601 EUB             : 
 5710 tgl                      5602 UIC           0 :         if (cancel_pressed)
                               5603                 :         {
                               5604               0 :             PQclear(res);
 5710 tgl                      5605 UBC           0 :             return false;
                               5606                 :         }
 5710 tgl                      5607 EUB             :     }
                               5608                 : 
 5710 tgl                      5609 UBC           0 :     PQclear(res);
                               5610               0 :     return true;
 5710 tgl                      5611 EUB             : }
                               5612                 : 
                               5613                 : static bool
 5710 tgl                      5614 UBC           0 : describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname,
 5710 tgl                      5615 EUB             :                     const char *pnspname, const char *prsname)
                               5616                 : {
                               5617                 :     PQExpBufferData buf,
                               5618                 :                 title;
                               5619                 :     PGresult   *res;
 5710 tgl                      5620 UBC           0 :     printQueryOpt myopt = pset.popt;
                               5621                 : 
 5710 tgl                      5622 UIC           0 :     initPQExpBuffer(&buf);
 5710 tgl                      5623 EUB             : 
 5710 tgl                      5624 UIC           0 :     printfPQExpBuffer(&buf,
 2187 peter_e                  5625 EUB             :                       "SELECT\n"
                               5626                 :                       "  ( SELECT t.alias FROM\n"
                               5627                 :                       "    pg_catalog.ts_token_type(c.cfgparser) AS t\n"
                               5628                 :                       "    WHERE t.tokid = m.maptokentype ) AS \"%s\",\n"
                               5629                 :                       "  pg_catalog.btrim(\n"
 2118 tgl                      5630                 :                       "    ARRAY( SELECT mm.mapdict::pg_catalog.regdictionary\n"
 2187 peter_e                  5631                 :                       "           FROM pg_catalog.pg_ts_config_map AS mm\n"
                               5632                 :                       "           WHERE mm.mapcfg = m.mapcfg AND mm.maptokentype = m.maptokentype\n"
                               5633                 :                       "           ORDER BY mapcfg, maptokentype, mapseqno\n"
                               5634                 :                       "    ) :: pg_catalog.text,\n"
                               5635                 :                       "  '{}') AS \"%s\"\n"
                               5636                 :                       "FROM pg_catalog.pg_ts_config AS c, pg_catalog.pg_ts_config_map AS m\n"
                               5637                 :                       "WHERE c.oid = '%s' AND m.mapcfg = c.oid\n"
                               5638                 :                       "GROUP BY m.mapcfg, m.maptokentype, c.cfgparser\n"
                               5639                 :                       "ORDER BY 1;",
                               5640                 :                       gettext_noop("Token"),
 5597 tgl                      5641                 :                       gettext_noop("Dictionaries"),
                               5642                 :                       oid);
 5710                          5643                 : 
 3090 fujii                    5644 UIC           0 :     res = PSQLexec(buf.data);
 5710 tgl                      5645 UBC           0 :     termPQExpBuffer(&buf);
 5710 tgl                      5646 UIC           0 :     if (!res)
                               5647               0 :         return false;
                               5648                 : 
                               5649               0 :     initPQExpBuffer(&title);
                               5650                 : 
                               5651               0 :     if (nspname)
 5597                          5652               0 :         appendPQExpBuffer(&title, _("Text search configuration \"%s.%s\""),
                               5653                 :                           nspname, cfgname);
                               5654                 :     else
                               5655               0 :         appendPQExpBuffer(&title, _("Text search configuration \"%s\""),
                               5656                 :                           cfgname);
                               5657                 : 
 5710                          5658               0 :     if (pnspname)
 5597                          5659               0 :         appendPQExpBuffer(&title, _("\nParser: \"%s.%s\""),
                               5660                 :                           pnspname, prsname);
                               5661                 :     else
                               5662               0 :         appendPQExpBuffer(&title, _("\nParser: \"%s\""),
                               5663                 :                           prsname);
                               5664                 : 
 5710 tgl                      5665 UBC           0 :     myopt.nullPrint = NULL;
                               5666               0 :     myopt.title = title.data;
                               5667               0 :     myopt.footers = NULL;
 3995 rhaas                    5668               0 :     myopt.topt.default_footer = false;
 5382 bruce                    5669 UIC           0 :     myopt.translate_header = true;
 5710 tgl                      5670 EUB             : 
 2685 tgl                      5671 UIC           0 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 5710 tgl                      5672 EUB             : 
 5710 tgl                      5673 UBC           0 :     termPQExpBuffer(&title);
                               5674                 : 
 5710 tgl                      5675 UIC           0 :     PQclear(res);
 5710 tgl                      5676 UBC           0 :     return true;
                               5677                 : }
                               5678                 : 
 5224 peter_e                  5679 EUB             : 
                               5680                 : /*
                               5681                 :  * \dew
                               5682                 :  *
                               5683                 :  * Describes foreign-data wrappers
                               5684                 :  */
                               5685                 : bool
 5224 peter_e                  5686 GBC          57 : listForeignDataWrappers(const char *pattern, bool verbose)
 5224 peter_e                  5687 EUB             : {
                               5688                 :     PQExpBufferData buf;
                               5689                 :     PGresult   *res;
 5224 peter_e                  5690 GBC          57 :     printQueryOpt myopt = pset.popt;
                               5691                 : 
                               5692              57 :     initPQExpBuffer(&buf);
 5224 peter_e                  5693 GIC          57 :     printfPQExpBuffer(&buf,
 4262 rhaas                    5694 EUB             :                       "SELECT fdw.fdwname AS \"%s\",\n"
                               5695                 :                       "  pg_catalog.pg_get_userbyid(fdw.fdwowner) AS \"%s\",\n"
  479 tgl                      5696                 :                       "  fdw.fdwhandler::pg_catalog.regproc AS \"%s\",\n"
 4262 rhaas                    5697                 :                       "  fdw.fdwvalidator::pg_catalog.regproc AS \"%s\"",
                               5698                 :                       gettext_noop("Name"),
                               5699                 :                       gettext_noop("Owner"),
                               5700                 :                       gettext_noop("Handler"),
                               5701                 :                       gettext_noop("Validator"));
                               5702                 : 
 5224 peter_e                  5703 GIC          57 :     if (verbose)
                               5704                 :     {
 3429 heikki.linnakangas       5705              42 :         appendPQExpBufferStr(&buf, ",\n  ");
 5212 tgl                      5706              42 :         printACLColumn(&buf, "fdwacl");
 5224 peter_e                  5707 CBC          42 :         appendPQExpBuffer(&buf,
                               5708                 :                           ",\n CASE WHEN fdwoptions IS NULL THEN '' ELSE "
                               5709                 :                           "  '(' || pg_catalog.array_to_string(ARRAY(SELECT "
                               5710                 :                           "  pg_catalog.quote_ident(option_name) ||  ' ' || "
 2083 tgl                      5711 ECB             :                           "  pg_catalog.quote_literal(option_value)  FROM "
                               5712                 :                           "  pg_catalog.pg_options_to_table(fdwoptions)),  ', ') || ')' "
  479                          5713                 :                           "  END AS \"%s\""
                               5714                 :                           ",\n  d.description AS \"%s\" ",
                               5715                 :                           gettext_noop("FDW options"),
                               5716                 :                           gettext_noop("Description"));
                               5717                 :     }
                               5718                 : 
 3429 heikki.linnakangas       5719 GIC          57 :     appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n");
                               5720                 : 
  479 tgl                      5721              57 :     if (verbose)
 3429 heikki.linnakangas       5722              42 :         appendPQExpBufferStr(&buf,
                               5723                 :                              "LEFT JOIN pg_catalog.pg_description d\n"
 3429 heikki.linnakangas       5724 ECB             :                              "       ON d.classoid = fdw.tableoid "
                               5725                 :                              "AND d.objoid = fdw.oid AND d.objsubid = 0\n");
 5224 peter_e                  5726                 : 
  354 rhaas                    5727 CBC          57 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
  354 rhaas                    5728 ECB             :                                 NULL, "fdwname", NULL, NULL,
                               5729                 :                                 NULL, 1))
                               5730                 :     {
  262 michael                  5731 GIC           9 :         termPQExpBuffer(&buf);
  354 rhaas                    5732               9 :         return false;
                               5733                 :     }
                               5734                 : 
 3429 heikki.linnakangas       5735              48 :     appendPQExpBufferStr(&buf, "ORDER BY 1;");
                               5736                 : 
 3090 fujii                    5737              48 :     res = PSQLexec(buf.data);
 5224 peter_e                  5738              48 :     termPQExpBuffer(&buf);
                               5739              48 :     if (!res)
 5224 peter_e                  5740 LBC           0 :         return false;
                               5741                 : 
 5224 peter_e                  5742 CBC          48 :     myopt.nullPrint = NULL;
                               5743              48 :     myopt.title = _("List of foreign-data wrappers");
 5224 peter_e                  5744 GIC          48 :     myopt.translate_header = true;
                               5745                 : 
 2685 tgl                      5746              48 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               5747                 : 
 5224 peter_e                  5748 CBC          48 :     PQclear(res);
 5224 peter_e                  5749 GIC          48 :     return true;
                               5750                 : }
                               5751                 : 
 5224 peter_e                  5752 ECB             : /*
                               5753                 :  * \des
                               5754                 :  *
                               5755                 :  * Describes foreign servers.
                               5756                 :  */
                               5757                 : bool
 5224 peter_e                  5758 CBC          60 : listForeignServers(const char *pattern, bool verbose)
 5224 peter_e                  5759 ECB             : {
                               5760                 :     PQExpBufferData buf;
 5224 peter_e                  5761 EUB             :     PGresult   *res;
 5224 peter_e                  5762 GIC          60 :     printQueryOpt myopt = pset.popt;
 5224 peter_e                  5763 ECB             : 
 5224 peter_e                  5764 CBC          60 :     initPQExpBuffer(&buf);
                               5765              60 :     printfPQExpBuffer(&buf,
                               5766                 :                       "SELECT s.srvname AS \"%s\",\n"
 5224 peter_e                  5767 ECB             :                       "  pg_catalog.pg_get_userbyid(s.srvowner) AS \"%s\",\n"
                               5768                 :                       "  f.fdwname AS \"%s\"",
                               5769                 :                       gettext_noop("Name"),
                               5770                 :                       gettext_noop("Owner"),
                               5771                 :                       gettext_noop("Foreign-data wrapper"));
                               5772                 : 
 5224 peter_e                  5773 GIC          60 :     if (verbose)
                               5774                 :     {
 3429 heikki.linnakangas       5775              24 :         appendPQExpBufferStr(&buf, ",\n  ");
 5212 tgl                      5776              24 :         printACLColumn(&buf, "s.srvacl");
 5224 peter_e                  5777              24 :         appendPQExpBuffer(&buf,
                               5778                 :                           ",\n"
 5212 tgl                      5779 ECB             :                           "  s.srvtype AS \"%s\",\n"
                               5780                 :                           "  s.srvversion AS \"%s\",\n"
                               5781                 :                           "  CASE WHEN srvoptions IS NULL THEN '' ELSE "
                               5782                 :                           "  '(' || pg_catalog.array_to_string(ARRAY(SELECT "
 2083                          5783                 :                           "  pg_catalog.quote_ident(option_name) ||  ' ' || "
                               5784                 :                           "  pg_catalog.quote_literal(option_value)  FROM "
                               5785                 :                           "  pg_catalog.pg_options_to_table(srvoptions)),  ', ') || ')' "
 4245 rhaas                    5786                 :                           "  END AS \"%s\",\n"
                               5787                 :                           "  d.description AS \"%s\"",
                               5788                 :                           gettext_noop("Type"),
                               5789                 :                           gettext_noop("Version"),
                               5790                 :                           gettext_noop("FDW options"),
                               5791                 :                           gettext_noop("Description"));
                               5792                 :     }
                               5793                 : 
 3429 heikki.linnakangas       5794 CBC          60 :     appendPQExpBufferStr(&buf,
                               5795                 :                          "\nFROM pg_catalog.pg_foreign_server s\n"
 2118 tgl                      5796 ECB             :                          "     JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid=s.srvfdw\n");
 5224 peter_e                  5797                 : 
 4262 rhaas                    5798 CBC          60 :     if (verbose)
 3429 heikki.linnakangas       5799 GIC          24 :         appendPQExpBufferStr(&buf,
                               5800                 :                              "LEFT JOIN pg_catalog.pg_description d\n       "
                               5801                 :                              "ON d.classoid = s.tableoid AND d.objoid = s.oid "
                               5802                 :                              "AND d.objsubid = 0\n");
                               5803                 : 
  354 rhaas                    5804              60 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                               5805                 :                                 NULL, "s.srvname", NULL, NULL,
                               5806                 :                                 NULL, 1))
                               5807                 :     {
  262 michael                  5808              21 :         termPQExpBuffer(&buf);
  354 rhaas                    5809              21 :         return false;
                               5810                 :     }
                               5811                 : 
 3429 heikki.linnakangas       5812              39 :     appendPQExpBufferStr(&buf, "ORDER BY 1;");
                               5813                 : 
 3090 fujii                    5814              39 :     res = PSQLexec(buf.data);
 5224 peter_e                  5815 CBC          39 :     termPQExpBuffer(&buf);
 5224 peter_e                  5816 GIC          39 :     if (!res)
 5224 peter_e                  5817 UIC           0 :         return false;
                               5818                 : 
 5224 peter_e                  5819 CBC          39 :     myopt.nullPrint = NULL;
                               5820              39 :     myopt.title = _("List of foreign servers");
 5224 peter_e                  5821 GIC          39 :     myopt.translate_header = true;
                               5822                 : 
 2685 tgl                      5823              39 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               5824                 : 
 5224 peter_e                  5825 CBC          39 :     PQclear(res);
 5224 peter_e                  5826 GIC          39 :     return true;
                               5827                 : }
                               5828                 : 
 5224 peter_e                  5829 ECB             : /*
                               5830                 :  * \deu
                               5831                 :  *
                               5832                 :  * Describes user mappings.
                               5833                 :  */
                               5834                 : bool
 5224 peter_e                  5835 CBC          30 : listUserMappings(const char *pattern, bool verbose)
 5224 peter_e                  5836 ECB             : {
                               5837                 :     PQExpBufferData buf;
 5224 peter_e                  5838 EUB             :     PGresult   *res;
 5224 peter_e                  5839 GIC          30 :     printQueryOpt myopt = pset.popt;
 5224 peter_e                  5840 ECB             : 
 5224 peter_e                  5841 CBC          30 :     initPQExpBuffer(&buf);
                               5842              30 :     printfPQExpBuffer(&buf,
                               5843                 :                       "SELECT um.srvname AS \"%s\",\n"
 5224 peter_e                  5844 ECB             :                       "  um.usename AS \"%s\"",
                               5845                 :                       gettext_noop("Server"),
 5128                          5846                 :                       gettext_noop("User name"));
 5224                          5847                 : 
 5224 peter_e                  5848 GIC          30 :     if (verbose)
                               5849              18 :         appendPQExpBuffer(&buf,
                               5850                 :                           ",\n CASE WHEN umoptions IS NULL THEN '' ELSE "
                               5851                 :                           "  '(' || pg_catalog.array_to_string(ARRAY(SELECT "
                               5852                 :                           "  pg_catalog.quote_ident(option_name) ||  ' ' || "
                               5853                 :                           "  pg_catalog.quote_literal(option_value)  FROM "
                               5854                 :                           "  pg_catalog.pg_options_to_table(umoptions)),  ', ') || ')' "
                               5855                 :                           "  END AS \"%s\"",
 2126 peter_e                  5856 ECB             :                           gettext_noop("FDW options"));
                               5857                 : 
 3429 heikki.linnakangas       5858 GIC          30 :     appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_user_mappings um\n");
                               5859                 : 
  354 rhaas                    5860 CBC          30 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                               5861                 :                                 NULL, "um.srvname", "um.usename", NULL,
  354 rhaas                    5862 ECB             :                                 NULL, 1))
  262 michael                  5863                 :     {
  262 michael                  5864 UIC           0 :         termPQExpBuffer(&buf);
  354 rhaas                    5865               0 :         return false;
                               5866                 :     }
                               5867                 : 
 3429 heikki.linnakangas       5868 GIC          30 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
 5224 peter_e                  5869 ECB             : 
 3090 fujii                    5870 CBC          30 :     res = PSQLexec(buf.data);
 5224 peter_e                  5871 GIC          30 :     termPQExpBuffer(&buf);
                               5872              30 :     if (!res)
 5224 peter_e                  5873 UIC           0 :         return false;
                               5874                 : 
 5224 peter_e                  5875 GIC          30 :     myopt.nullPrint = NULL;
                               5876              30 :     myopt.title = _("List of user mappings");
                               5877              30 :     myopt.translate_header = true;
                               5878                 : 
 2685 tgl                      5879 CBC          30 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               5880                 : 
 5224 peter_e                  5881              30 :     PQclear(res);
 5224 peter_e                  5882 GIC          30 :     return true;
                               5883                 : }
                               5884                 : 
 4481 rhaas                    5885 EUB             : /*
                               5886                 :  * \det
                               5887                 :  *
                               5888                 :  * Describes foreign tables.
 4481 rhaas                    5889 ECB             :  */
                               5890                 : bool
 4481 rhaas                    5891 CBC           9 : listForeignTables(const char *pattern, bool verbose)
 4481 rhaas                    5892 ECB             : {
                               5893                 :     PQExpBufferData buf;
 4481 rhaas                    5894 EUB             :     PGresult   *res;
 4481 rhaas                    5895 GIC           9 :     printQueryOpt myopt = pset.popt;
 4481 rhaas                    5896 ECB             : 
 4481 rhaas                    5897 CBC           9 :     initPQExpBuffer(&buf);
                               5898               9 :     printfPQExpBuffer(&buf,
                               5899                 :                       "SELECT n.nspname AS \"%s\",\n"
 4481 rhaas                    5900 ECB             :                       "  c.relname AS \"%s\",\n"
                               5901                 :                       "  s.srvname AS \"%s\"",
                               5902                 :                       gettext_noop("Schema"),
                               5903                 :                       gettext_noop("Table"),
                               5904                 :                       gettext_noop("Server"));
                               5905                 : 
 4481 rhaas                    5906 GIC           9 :     if (verbose)
                               5907               9 :         appendPQExpBuffer(&buf,
                               5908                 :                           ",\n CASE WHEN ftoptions IS NULL THEN '' ELSE "
                               5909                 :                           "  '(' || pg_catalog.array_to_string(ARRAY(SELECT "
                               5910                 :                           "  pg_catalog.quote_ident(option_name) ||  ' ' || "
                               5911                 :                           "  pg_catalog.quote_literal(option_value)  FROM "
 2083 tgl                      5912 ECB             :                           "  pg_catalog.pg_options_to_table(ftoptions)),  ', ') || ')' "
                               5913                 :                           "  END AS \"%s\",\n"
                               5914                 :                           "  d.description AS \"%s\"",
                               5915                 :                           gettext_noop("FDW options"),
 4262 rhaas                    5916                 :                           gettext_noop("Description"));
                               5917                 : 
 3429 heikki.linnakangas       5918 CBC           9 :     appendPQExpBufferStr(&buf,
 3429 heikki.linnakangas       5919 ECB             :                          "\nFROM pg_catalog.pg_foreign_table ft\n"
                               5920                 :                          "  INNER JOIN pg_catalog.pg_class c"
                               5921                 :                          " ON c.oid = ft.ftrelid\n"
                               5922                 :                          "  INNER JOIN pg_catalog.pg_namespace n"
                               5923                 :                          " ON n.oid = c.relnamespace\n"
                               5924                 :                          "  INNER JOIN pg_catalog.pg_foreign_server s"
                               5925                 :                          " ON s.oid = ft.ftserver\n");
 4262 rhaas                    5926 GIC           9 :     if (verbose)
 3429 heikki.linnakangas       5927 CBC           9 :         appendPQExpBufferStr(&buf,
 3429 heikki.linnakangas       5928 ECB             :                              "   LEFT JOIN pg_catalog.pg_description d\n"
                               5929                 :                              "          ON d.classoid = c.tableoid AND "
                               5930                 :                              "d.objoid = c.oid AND d.objsubid = 0\n");
                               5931                 : 
  354 rhaas                    5932 GIC           9 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                               5933                 :                                 "n.nspname", "c.relname", NULL,
                               5934                 :                                 "pg_catalog.pg_table_is_visible(c.oid)",
                               5935                 :                                 NULL, 3))
                               5936                 :     {
  262 michael                  5937 UIC           0 :         termPQExpBuffer(&buf);
  354 rhaas                    5938               0 :         return false;
  262 michael                  5939 ECB             :     }
                               5940                 : 
 3429 heikki.linnakangas       5941 GIC           9 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
                               5942                 : 
 3090 fujii                    5943               9 :     res = PSQLexec(buf.data);
 4481 rhaas                    5944               9 :     termPQExpBuffer(&buf);
                               5945               9 :     if (!res)
 4481 rhaas                    5946 UIC           0 :         return false;
 4481 rhaas                    5947 ECB             : 
 4481 rhaas                    5948 CBC           9 :     myopt.nullPrint = NULL;
 4481 rhaas                    5949 GIC           9 :     myopt.title = _("List of foreign tables");
                               5950               9 :     myopt.translate_header = true;
                               5951                 : 
 2685 tgl                      5952               9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 4481 rhaas                    5953 ECB             : 
 4481 rhaas                    5954 GIC           9 :     PQclear(res);
                               5955               9 :     return true;
                               5956                 : }
                               5957                 : 
 4443 tgl                      5958 EUB             : /*
                               5959                 :  * \dx
                               5960                 :  *
                               5961                 :  * Briefly describes installed extensions.
 4443 tgl                      5962 ECB             :  */
                               5963                 : bool
 4443 tgl                      5964 CBC          12 : listExtensions(const char *pattern)
 4443 tgl                      5965 ECB             : {
                               5966                 :     PQExpBufferData buf;
 4443 tgl                      5967 EUB             :     PGresult   *res;
 4443 tgl                      5968 GIC          12 :     printQueryOpt myopt = pset.popt;
 4443 tgl                      5969 ECB             : 
 4443 tgl                      5970 CBC          12 :     initPQExpBuffer(&buf);
                               5971              12 :     printfPQExpBuffer(&buf,
                               5972                 :                       "SELECT e.extname AS \"%s\", "
 2118 tgl                      5973 ECB             :                       "e.extversion AS \"%s\", n.nspname AS \"%s\", c.description AS \"%s\"\n"
                               5974                 :                       "FROM pg_catalog.pg_extension e "
                               5975                 :                       "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace "
                               5976                 :                       "LEFT JOIN pg_catalog.pg_description c ON c.objoid = e.oid "
                               5977                 :                       "AND c.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass\n",
                               5978                 :                       gettext_noop("Name"),
                               5979                 :                       gettext_noop("Version"),
                               5980                 :                       gettext_noop("Schema"),
                               5981                 :                       gettext_noop("Description"));
                               5982                 : 
  354 rhaas                    5983 GIC          12 :     if (!validateSQLNamePattern(&buf, pattern,
                               5984                 :                                 false, false,
  354 rhaas                    5985 ECB             :                                 NULL, "e.extname", NULL,
                               5986                 :                                 NULL,
                               5987                 :                                 NULL, 1))
                               5988                 :     {
  262 michael                  5989 CBC           9 :         termPQExpBuffer(&buf);
  354 rhaas                    5990 GIC           9 :         return false;
  262 michael                  5991 ECB             :     }
 4443 tgl                      5992                 : 
 3429 heikki.linnakangas       5993 GIC           3 :     appendPQExpBufferStr(&buf, "ORDER BY 1;");
                               5994                 : 
 3090 fujii                    5995               3 :     res = PSQLexec(buf.data);
 4443 tgl                      5996               3 :     termPQExpBuffer(&buf);
                               5997               3 :     if (!res)
 4443 tgl                      5998 UIC           0 :         return false;
                               5999                 : 
 4443 tgl                      6000 GIC           3 :     myopt.nullPrint = NULL;
                               6001               3 :     myopt.title = _("List of installed extensions");
                               6002               3 :     myopt.translate_header = true;
                               6003                 : 
 2685 tgl                      6004 CBC           3 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               6005                 : 
 4443 tgl                      6006 GIC           3 :     PQclear(res);
                               6007               3 :     return true;
                               6008                 : }
                               6009                 : 
 4443 tgl                      6010 ECB             : /*
                               6011                 :  * \dx+
                               6012                 :  *
                               6013                 :  * List contents of installed extensions.
                               6014                 :  */
                               6015                 : bool
 4443 tgl                      6016 CBC          10 : listExtensionContents(const char *pattern)
 4443 tgl                      6017 ECB             : {
                               6018                 :     PQExpBufferData buf;
 4443 tgl                      6019 EUB             :     PGresult   *res;
                               6020                 :     int         i;
 4443 tgl                      6021 ECB             : 
 4443 tgl                      6022 CBC          10 :     initPQExpBuffer(&buf);
                               6023              10 :     printfPQExpBuffer(&buf,
                               6024                 :                       "SELECT e.extname, e.oid\n"
 4443 tgl                      6025 ECB             :                       "FROM pg_catalog.pg_extension e\n");
                               6026                 : 
  354 rhaas                    6027 CBC          10 :     if (!validateSQLNamePattern(&buf, pattern,
  354 rhaas                    6028 ECB             :                                 false, false,
                               6029                 :                                 NULL, "e.extname", NULL,
                               6030                 :                                 NULL,
                               6031                 :                                 NULL, 1))
                               6032                 :     {
  262 michael                  6033 UIC           0 :         termPQExpBuffer(&buf);
  354 rhaas                    6034               0 :         return false;
                               6035                 :     }
                               6036                 : 
 3429 heikki.linnakangas       6037 CBC          10 :     appendPQExpBufferStr(&buf, "ORDER BY 1;");
                               6038                 : 
 3090 fujii                    6039 GIC          10 :     res = PSQLexec(buf.data);
 4443 tgl                      6040              10 :     termPQExpBuffer(&buf);
                               6041              10 :     if (!res)
 4443 tgl                      6042 UIC           0 :         return false;
 4443 tgl                      6043 ECB             : 
 4443 tgl                      6044 CBC          10 :     if (PQntuples(res) == 0)
                               6045                 :     {
 4443 tgl                      6046 UIC           0 :         if (!pset.quiet)
                               6047                 :         {
 4443 tgl                      6048 LBC           0 :             if (pattern)
 1469 peter                    6049 UIC           0 :                 pg_log_error("Did not find any extension named \"%s\".",
                               6050                 :                              pattern);
                               6051                 :             else
                               6052               0 :                 pg_log_error("Did not find any extensions.");
                               6053                 :         }
 4443 tgl                      6054 UBC           0 :         PQclear(res);
                               6055               0 :         return false;
                               6056                 :     }
                               6057                 : 
 4443 tgl                      6058 CBC          20 :     for (i = 0; i < PQntuples(res); i++)
                               6059                 :     {
 4443 tgl                      6060 ECB             :         const char *extname;
                               6061                 :         const char *oid;
                               6062                 : 
 4443 tgl                      6063 GBC          10 :         extname = PQgetvalue(res, i, 0);
 4443 tgl                      6064 GIC          10 :         oid = PQgetvalue(res, i, 1);
 4443 tgl                      6065 ECB             : 
 4443 tgl                      6066 GIC          10 :         if (!listOneExtensionContents(extname, oid))
 4443 tgl                      6067 EUB             :         {
 4443 tgl                      6068 UIC           0 :             PQclear(res);
 4443 tgl                      6069 UBC           0 :             return false;
 4443 tgl                      6070 EUB             :         }
 4443 tgl                      6071 GIC          10 :         if (cancel_pressed)
                               6072                 :         {
 4443 tgl                      6073 UBC           0 :             PQclear(res);
 4443 tgl                      6074 UIC           0 :             return false;
 4443 tgl                      6075 EUB             :         }
                               6076                 :     }
                               6077                 : 
 4443 tgl                      6078 GIC          10 :     PQclear(res);
 4443 tgl                      6079 CBC          10 :     return true;
                               6080                 : }
                               6081                 : 
                               6082                 : static bool
 4443 tgl                      6083 GIC          10 : listOneExtensionContents(const char *extname, const char *oid)
 4443 tgl                      6084 ECB             : {
                               6085                 :     PQExpBufferData buf;
                               6086                 :     PGresult   *res;
 2082                          6087                 :     PQExpBufferData title;
 4443 tgl                      6088 GIC          10 :     printQueryOpt myopt = pset.popt;
 4443 tgl                      6089 EUB             : 
 4443 tgl                      6090 GBC          10 :     initPQExpBuffer(&buf);
 4443 tgl                      6091 GIC          10 :     printfPQExpBuffer(&buf,
 2118 tgl                      6092 ECB             :                       "SELECT pg_catalog.pg_describe_object(classid, objid, 0) AS \"%s\"\n"
                               6093                 :                       "FROM pg_catalog.pg_depend\n"
 4443 tgl                      6094 EUB             :                       "WHERE refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass AND refobjid = '%s' AND deptype = 'e'\n"
                               6095                 :                       "ORDER BY 1;",
                               6096                 :                       gettext_noop("Object description"),
                               6097                 :                       oid);
                               6098                 : 
 3090 fujii                    6099 CBC          10 :     res = PSQLexec(buf.data);
 4443 tgl                      6100              10 :     termPQExpBuffer(&buf);
 4443 tgl                      6101 GIC          10 :     if (!res)
 4443 tgl                      6102 UIC           0 :         return false;
                               6103                 : 
 4443 tgl                      6104 CBC          10 :     myopt.nullPrint = NULL;
 2082 tgl                      6105 GIC          10 :     initPQExpBuffer(&title);
                               6106              10 :     printfPQExpBuffer(&title, _("Objects in extension \"%s\""), extname);
                               6107              10 :     myopt.title = title.data;
 4443                          6108              10 :     myopt.translate_header = true;
 4443 tgl                      6109 ECB             : 
 2685 tgl                      6110 GIC          10 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
 4443 tgl                      6111 ECB             : 
 2082 tgl                      6112 CBC          10 :     termPQExpBuffer(&title);
 4443 tgl                      6113 GIC          10 :     PQclear(res);
                               6114              10 :     return true;
                               6115                 : }
                               6116                 : 
                               6117                 : /*
                               6118                 :  * validateSQLNamePattern
                               6119                 :  *
  354 rhaas                    6120 ECB             :  * Wrapper around string_utils's processSQLNamePattern which also checks the
                               6121                 :  * pattern's validity.  In addition to that function's parameters, takes a
                               6122                 :  * 'maxparts' parameter specifying the maximum number of dotted names the
  354 rhaas                    6123 EUB             :  * pattern is allowed to have, and a 'added_clause' parameter that returns by
                               6124                 :  * reference whether a clause was added to 'buf'.  Returns whether the pattern
  354 rhaas                    6125 ECB             :  * passed validation, after logging any errors.
                               6126                 :  */
                               6127                 : static bool
  354 rhaas                    6128 CBC        3063 : validateSQLNamePattern(PQExpBuffer buf, const char *pattern, bool have_where,
  354 rhaas                    6129 ECB             :                        bool force_escape, const char *schemavar,
                               6130                 :                        const char *namevar, const char *altnamevar,
                               6131                 :                        const char *visibilityrule, bool *added_clause,
                               6132                 :                        int maxparts)
                               6133                 : {
  332 tgl                      6134                 :     PQExpBufferData dbbuf;
  354 rhaas                    6135                 :     int         dotcnt;
                               6136                 :     bool        added;
                               6137                 : 
  354 rhaas                    6138 GIC        3063 :     initPQExpBuffer(&dbbuf);
                               6139            3063 :     added = processSQLNamePattern(pset.db, buf, pattern, have_where, force_escape,
                               6140                 :                                   schemavar, namevar, altnamevar,
                               6141                 :                                   visibilityrule, &dbbuf, &dotcnt);
                               6142            3063 :     if (added_clause != NULL)
                               6143              84 :         *added_clause = added;
                               6144                 : 
                               6145            3063 :     if (dotcnt >= maxparts)
                               6146                 :     {
                               6147             219 :         pg_log_error("improper qualified name (too many dotted names): %s",
                               6148                 :                      pattern);
  262 michael                  6149 CBC         219 :         goto error_return;
                               6150                 :     }
                               6151                 : 
  332 tgl                      6152 GIC        2844 :     if (maxparts > 1 && dotcnt == maxparts - 1)
                               6153                 :     {
  354 rhaas                    6154             309 :         if (PQdb(pset.db) == NULL)
                               6155                 :         {
  354 rhaas                    6156 UIC           0 :             pg_log_error("You are currently not connected to a database.");
  262 michael                  6157               0 :             goto error_return;
                               6158                 :         }
  354 rhaas                    6159 CBC         309 :         if (strcmp(PQdb(pset.db), dbbuf.data) != 0)
  354 rhaas                    6160 ECB             :         {
  354 rhaas                    6161 GIC         225 :             pg_log_error("cross-database references are not implemented: %s",
                               6162                 :                          pattern);
  262 michael                  6163 CBC         225 :             goto error_return;
  354 rhaas                    6164 ECB             :         }
                               6165                 :     }
  262 michael                  6166 CBC        2619 :     termPQExpBuffer(&dbbuf);
  354 rhaas                    6167 GIC        2619 :     return true;
  262 michael                  6168 ECB             : 
  262 michael                  6169 GIC         444 : error_return:
  262 michael                  6170 CBC         444 :     termPQExpBuffer(&dbbuf);
  262 michael                  6171 GIC         444 :     return false;
                               6172                 : }
  354 rhaas                    6173 ECB             : 
                               6174                 : /*
 2082 tgl                      6175                 :  * \dRp
                               6176                 :  * Lists publications.
 2271 peter_e                  6177 EUB             :  *
                               6178                 :  * Takes an optional regexp to select particular publications
                               6179                 :  */
 2271 peter_e                  6180 ECB             : bool
 2271 peter_e                  6181 GIC          24 : listPublications(const char *pattern)
 2271 peter_e                  6182 ECB             : {
                               6183                 :     PQExpBufferData buf;
                               6184                 :     PGresult   *res;
 2271 peter_e                  6185 GIC          24 :     printQueryOpt myopt = pset.popt;
                               6186                 :     static const bool translate_columns[] = {false, false, false, false, false, false, false, false};
 2271 peter_e                  6187 ECB             : 
 2271 peter_e                  6188 CBC          24 :     if (pset.sversion < 100000)
                               6189                 :     {
 2271 peter_e                  6190 ECB             :         char        sverbuf[32];
 2153 bruce                    6191                 : 
 1469 peter                    6192 LBC           0 :         pg_log_error("The server (version %s) does not support publications.",
                               6193                 :                      formatPGVersionNumber(pset.sversion, false,
                               6194                 :                                            sverbuf, sizeof(sverbuf)));
 2271 peter_e                  6195 UIC           0 :         return true;
                               6196                 :     }
                               6197                 : 
 2271 peter_e                  6198 GIC          24 :     initPQExpBuffer(&buf);
                               6199                 : 
  367 tomas.vondra             6200              24 :     printfPQExpBuffer(&buf,
                               6201                 :                       "SELECT pubname AS \"%s\",\n"
  367 tomas.vondra             6202 ECB             :                       "  pg_catalog.pg_get_userbyid(pubowner) AS \"%s\",\n"
                               6203                 :                       "  puballtables AS \"%s\",\n"
                               6204                 :                       "  pubinsert AS \"%s\",\n"
                               6205                 :                       "  pubupdate AS \"%s\",\n"
                               6206                 :                       "  pubdelete AS \"%s\"",
                               6207                 :                       gettext_noop("Name"),
                               6208                 :                       gettext_noop("Owner"),
                               6209                 :                       gettext_noop("All tables"),
                               6210                 :                       gettext_noop("Inserts"),
                               6211                 :                       gettext_noop("Updates"),
                               6212                 :                       gettext_noop("Deletes"));
 1828 peter_e                  6213 GBC          24 :     if (pset.sversion >= 110000)
 1828 peter_e                  6214 GIC          24 :         appendPQExpBuffer(&buf,
                               6215                 :                           ",\n  pubtruncate AS \"%s\"",
 1828 peter_e                  6216 EUB             :                           gettext_noop("Truncates"));
 1096 peter                    6217 GIC          24 :     if (pset.sversion >= 130000)
                               6218              24 :         appendPQExpBuffer(&buf,
 1096 peter                    6219 ECB             :                           ",\n  pubviaroot AS \"%s\"",
                               6220                 :                           gettext_noop("Via root"));
 2271 peter_e                  6221                 : 
 2271 peter_e                  6222 GIC          24 :     appendPQExpBufferStr(&buf,
                               6223                 :                          "\nFROM pg_catalog.pg_publication\n");
                               6224                 : 
  354 rhaas                    6225              24 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                               6226                 :                                 NULL, "pubname", NULL,
                               6227                 :                                 NULL,
                               6228                 :                                 NULL, 1))
                               6229                 :     {
  262 michael                  6230               9 :         termPQExpBuffer(&buf);
  354 rhaas                    6231               9 :         return false;
                               6232                 :     }
                               6233                 : 
 2271 peter_e                  6234 CBC          15 :     appendPQExpBufferStr(&buf, "ORDER BY 1;");
 2271 peter_e                  6235 ECB             : 
 2271 peter_e                  6236 GIC          15 :     res = PSQLexec(buf.data);
                               6237              15 :     termPQExpBuffer(&buf);
 2271 peter_e                  6238 CBC          15 :     if (!res)
 2271 peter_e                  6239 LBC           0 :         return false;
                               6240                 : 
 2271 peter_e                  6241 GIC          15 :     myopt.nullPrint = NULL;
                               6242              15 :     myopt.title = _("List of publications");
 2271 peter_e                  6243 CBC          15 :     myopt.translate_header = true;
 2271 peter_e                  6244 GIC          15 :     myopt.translate_columns = translate_columns;
                               6245              15 :     myopt.n_translate_columns = lengthof(translate_columns);
 2271 peter_e                  6246 ECB             : 
 2271 peter_e                  6247 GIC          15 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               6248                 : 
                               6249              15 :     PQclear(res);
                               6250                 : 
 2271 peter_e                  6251 CBC          15 :     return true;
 2271 peter_e                  6252 ECB             : }
                               6253                 : 
                               6254                 : /*
  529 akapila                  6255                 :  * Add footer to publication description.
                               6256                 :  */
                               6257                 : static bool
  366 peter                    6258 CBC         282 : addFooterToPublicationDesc(PQExpBuffer buf, const char *footermsg,
  366 peter                    6259 ECB             :                            bool as_schema, printTableContent *const cont)
  529 akapila                  6260 EUB             : {
                               6261                 :     PGresult   *res;
  529 akapila                  6262 CBC         282 :     int         count = 0;
                               6263             282 :     int         i = 0;
  529 akapila                  6264 ECB             : 
  529 akapila                  6265 CBC         282 :     res = PSQLexec(buf->data);
                               6266             282 :     if (!res)
  529 akapila                  6267 UIC           0 :         return false;
  529 akapila                  6268 ECB             :     else
  529 akapila                  6269 GIC         282 :         count = PQntuples(res);
  529 akapila                  6270 ECB             : 
  529 akapila                  6271 GIC         282 :     if (count > 0)
  366 peter                    6272 CBC         150 :         printTableAddFooter(cont, footermsg);
                               6273                 : 
  529 akapila                  6274 GIC         495 :     for (i = 0; i < count; i++)
                               6275                 :     {
  379 tomas.vondra             6276             213 :         if (as_schema)
                               6277             117 :             printfPQExpBuffer(buf, "    \"%s\"", PQgetvalue(res, i, 0));
                               6278                 :         else
  411 akapila                  6279 ECB             :         {
  529 akapila                  6280 GIC          96 :             printfPQExpBuffer(buf, "    \"%s.%s\"", PQgetvalue(res, i, 0),
                               6281                 :                               PQgetvalue(res, i, 1));
                               6282                 : 
  379 tomas.vondra             6283 CBC          96 :             if (!PQgetisnull(res, i, 3))
                               6284               6 :                 appendPQExpBuffer(buf, " (%s)", PQgetvalue(res, i, 3));
                               6285                 : 
  411 akapila                  6286              96 :             if (!PQgetisnull(res, i, 2))
                               6287              27 :                 appendPQExpBuffer(buf, " WHERE %s", PQgetvalue(res, i, 2));
  411 akapila                  6288 EUB             :         }
                               6289                 : 
  529 akapila                  6290 CBC         213 :         printTableAddFooter(cont, buf->data);
                               6291                 :     }
  529 akapila                  6292 ECB             : 
  529 akapila                  6293 CBC         282 :     PQclear(res);
  529 akapila                  6294 GIC         282 :     return true;
  529 akapila                  6295 ECB             : }
                               6296                 : 
 2082 tgl                      6297                 : /*
                               6298                 :  * \dRp+
                               6299                 :  * Describes publications including the contents.
                               6300                 :  *
 2271 peter_e                  6301                 :  * Takes an optional regexp to select particular publications
                               6302                 :  */
                               6303                 : bool
 2271 peter_e                  6304 CBC         144 : describePublications(const char *pattern)
 2271 peter_e                  6305 ECB             : {
                               6306                 :     PQExpBufferData buf;
 2153 bruce                    6307                 :     int         i;
                               6308                 :     PGresult   *res;
                               6309                 :     bool        has_pubtruncate;
                               6310                 :     bool        has_pubviaroot;
 2271 peter_e                  6311                 : 
                               6312                 :     PQExpBufferData title;
                               6313                 :     printTableContent cont;
  529 akapila                  6314                 : 
 2271 peter_e                  6315 CBC         144 :     if (pset.sversion < 100000)
                               6316                 :     {
                               6317                 :         char        sverbuf[32];
                               6318                 : 
 1469 peter                    6319 UIC           0 :         pg_log_error("The server (version %s) does not support publications.",
                               6320                 :                      formatPGVersionNumber(pset.sversion, false,
                               6321                 :                                            sverbuf, sizeof(sverbuf)));
 2271 peter_e                  6322               0 :         return true;
                               6323                 :     }
                               6324                 : 
 1828 peter_e                  6325 CBC         144 :     has_pubtruncate = (pset.sversion >= 110000);
 1096 peter                    6326 GIC         144 :     has_pubviaroot = (pset.sversion >= 130000);
                               6327                 : 
 2271 peter_e                  6328             144 :     initPQExpBuffer(&buf);
                               6329                 : 
                               6330             144 :     printfPQExpBuffer(&buf,
                               6331                 :                       "SELECT oid, pubname,\n"
                               6332                 :                       "  pg_catalog.pg_get_userbyid(pubowner) AS owner,\n"
                               6333                 :                       "  puballtables, pubinsert, pubupdate, pubdelete");
 1828                          6334             144 :     if (has_pubtruncate)
 1375 drowley                  6335             144 :         appendPQExpBufferStr(&buf,
 1375 drowley                  6336 ECB             :                              ", pubtruncate");
 1096 peter                    6337 GIC         144 :     if (has_pubviaroot)
                               6338             144 :         appendPQExpBufferStr(&buf,
                               6339                 :                              ", pubviaroot");
 1375 drowley                  6340 GBC         144 :     appendPQExpBufferStr(&buf,
                               6341                 :                          "\nFROM pg_catalog.pg_publication\n");
                               6342                 : 
  354 rhaas                    6343             144 :     if (!validateSQLNamePattern(&buf, pattern, false, false,
                               6344                 :                                 NULL, "pubname", NULL,
                               6345                 :                                 NULL,
  354 rhaas                    6346 ECB             :                                 NULL, 1))
  262 michael                  6347                 :     {
  262 michael                  6348 UIC           0 :         termPQExpBuffer(&buf);
  354 rhaas                    6349 LBC           0 :         return false;
                               6350                 :     }
 2271 peter_e                  6351 ECB             : 
 2271 peter_e                  6352 GIC         144 :     appendPQExpBufferStr(&buf, "ORDER BY 2;");
                               6353                 : 
                               6354             144 :     res = PSQLexec(buf.data);
 2271 peter_e                  6355 CBC         144 :     if (!res)
 2271 peter_e                  6356 ECB             :     {
 2271 peter_e                  6357 UIC           0 :         termPQExpBuffer(&buf);
 2271 peter_e                  6358 LBC           0 :         return false;
 2271 peter_e                  6359 ECB             :     }
                               6360                 : 
 2082 tgl                      6361 CBC         144 :     if (PQntuples(res) == 0)
                               6362                 :     {
 2082 tgl                      6363 UIC           0 :         if (!pset.quiet)
 2082 tgl                      6364 ECB             :         {
 2082 tgl                      6365 UIC           0 :             if (pattern)
 1469 peter                    6366               0 :                 pg_log_error("Did not find any publication named \"%s\".",
                               6367                 :                              pattern);
                               6368                 :             else
 1469 peter                    6369 UBC           0 :                 pg_log_error("Did not find any publications.");
 2082 tgl                      6370 EUB             :         }
                               6371                 : 
 2082 tgl                      6372 UIC           0 :         termPQExpBuffer(&buf);
 2082 tgl                      6373 LBC           0 :         PQclear(res);
 2082 tgl                      6374 UIC           0 :         return false;
 2082 tgl                      6375 ECB             :     }
                               6376                 : 
 2271 peter_e                  6377 GIC         288 :     for (i = 0; i < PQntuples(res); i++)
 2271 peter_e                  6378 EUB             :     {
 2271 peter_e                  6379 GBC         144 :         const char  align = 'l';
 2081 tgl                      6380 GIC         144 :         int         ncols = 5;
 2271 peter_e                  6381             144 :         int         nrows = 1;
 2271 peter_e                  6382 CBC         144 :         char       *pubid = PQgetvalue(res, i, 0);
 2271 peter_e                  6383 GIC         144 :         char       *pubname = PQgetvalue(res, i, 1);
 2081 tgl                      6384 GBC         144 :         bool        puballtables = strcmp(PQgetvalue(res, i, 3), "t") == 0;
 2271 peter_e                  6385 GIC         144 :         printTableOpt myopt = pset.popt.topt;
 2271 peter_e                  6386 EUB             : 
 1828 peter_e                  6387 GBC         144 :         if (has_pubtruncate)
 1828 peter_e                  6388 GIC         144 :             ncols++;
 1096 peter                    6389             144 :         if (has_pubviaroot)
 1096 peter                    6390 GBC         144 :             ncols++;
                               6391                 : 
 2271 peter_e                  6392 GIC         144 :         initPQExpBuffer(&title);
 2271 peter_e                  6393 GBC         144 :         printfPQExpBuffer(&title, _("Publication %s"), pubname);
                               6394             144 :         printTableInit(&cont, &myopt, title.data, ncols, nrows);
 2271 peter_e                  6395 EUB             : 
 2081 tgl                      6396 GIC         144 :         printTableAddHeader(&cont, gettext_noop("Owner"), true, align);
 2124 peter_e                  6397             144 :         printTableAddHeader(&cont, gettext_noop("All tables"), true, align);
 2271 peter_e                  6398 CBC         144 :         printTableAddHeader(&cont, gettext_noop("Inserts"), true, align);
 2271 peter_e                  6399 GIC         144 :         printTableAddHeader(&cont, gettext_noop("Updates"), true, align);
 2271 peter_e                  6400 CBC         144 :         printTableAddHeader(&cont, gettext_noop("Deletes"), true, align);
 1828                          6401             144 :         if (has_pubtruncate)
                               6402             144 :             printTableAddHeader(&cont, gettext_noop("Truncates"), true, align);
 1096 peter                    6403             144 :         if (has_pubviaroot)
                               6404             144 :             printTableAddHeader(&cont, gettext_noop("Via root"), true, align);
 2271 peter_e                  6405 ECB             : 
  367 tomas.vondra             6406 CBC         144 :         printTableAddCell(&cont, PQgetvalue(res, i, 2), false, false);
  367 tomas.vondra             6407 GIC         144 :         printTableAddCell(&cont, PQgetvalue(res, i, 3), false, false);
  367 tomas.vondra             6408 CBC         144 :         printTableAddCell(&cont, PQgetvalue(res, i, 4), false, false);
                               6409             144 :         printTableAddCell(&cont, PQgetvalue(res, i, 5), false, false);
                               6410             144 :         printTableAddCell(&cont, PQgetvalue(res, i, 6), false, false);
 1828 peter_e                  6411             144 :         if (has_pubtruncate)
  367 tomas.vondra             6412 GIC         144 :             printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false);
 1096 peter                    6413 CBC         144 :         if (has_pubviaroot)
  367 tomas.vondra             6414             144 :             printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false);
 2271 peter_e                  6415 ECB             : 
 2124 peter_e                  6416 GIC         144 :         if (!puballtables)
 2124 peter_e                  6417 ECB             :         {
  529 akapila                  6418                 :             /* Get the tables for the specified publication */
 2271 peter_e                  6419 CBC         141 :             printfPQExpBuffer(&buf,
  411 akapila                  6420 ECB             :                               "SELECT n.nspname, c.relname");
  411 akapila                  6421 CBC         141 :             if (pset.sversion >= 150000)
  379 tomas.vondra             6422 ECB             :             {
  411 akapila                  6423 CBC         141 :                 appendPQExpBufferStr(&buf,
  411 akapila                  6424 ECB             :                                      ", pg_get_expr(pr.prqual, c.oid)");
  379 tomas.vondra             6425 CBC         141 :                 appendPQExpBufferStr(&buf,
                               6426                 :                                      ", (CASE WHEN pr.prattrs IS NOT NULL THEN\n"
  379 tomas.vondra             6427 ECB             :                                      "     pg_catalog.array_to_string("
                               6428                 :                                      "      ARRAY(SELECT attname\n"
                               6429                 :                                      "              FROM\n"
                               6430                 :                                      "                pg_catalog.generate_series(0, pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n"
                               6431                 :                                      "                pg_catalog.pg_attribute\n"
                               6432                 :                                      "        WHERE attrelid = c.oid AND attnum = prattrs[s]), ', ')\n"
                               6433                 :                                      "       ELSE NULL END)");
                               6434                 :             }
  411 akapila                  6435                 :             else
  411 akapila                  6436 UIC           0 :                 appendPQExpBufferStr(&buf,
  379 tomas.vondra             6437 ECB             :                                      ", NULL, NULL");
  411 akapila                  6438 GIC         141 :             appendPQExpBuffer(&buf,
                               6439                 :                               "\nFROM pg_catalog.pg_class c,\n"
 2271 peter_e                  6440 ECB             :                               "     pg_catalog.pg_namespace n,\n"
                               6441                 :                               "     pg_catalog.pg_publication_rel pr\n"
                               6442                 :                               "WHERE c.relnamespace = n.oid\n"
                               6443                 :                               "  AND c.oid = pr.prrelid\n"
                               6444                 :                               "  AND pr.prpubid = '%s'\n"
                               6445                 :                               "ORDER BY 1,2", pubid);
  366 peter                    6446 CBC         141 :             if (!addFooterToPublicationDesc(&buf, _("Tables:"), false, &cont))
  529 akapila                  6447 UIC           0 :                 goto error_return;
                               6448                 : 
  529 akapila                  6449 GIC         141 :             if (pset.sversion >= 150000)
                               6450                 :             {
                               6451                 :                 /* Get the schemas for the specified publication */
                               6452             141 :                 printfPQExpBuffer(&buf,
                               6453                 :                                   "SELECT n.nspname\n"
                               6454                 :                                   "FROM pg_catalog.pg_namespace n\n"
                               6455                 :                                   "     JOIN pg_catalog.pg_publication_namespace pn ON n.oid = pn.pnnspid\n"
                               6456                 :                                   "WHERE pn.pnpubid = '%s'\n"
  529 akapila                  6457 EUB             :                                   "ORDER BY 1", pubid);
  366 peter                    6458 GIC         141 :                 if (!addFooterToPublicationDesc(&buf, _("Tables from schemas:"),
  529 akapila                  6459 ECB             :                                                 true, &cont))
  529 akapila                  6460 UIC           0 :                     goto error_return;
                               6461                 :             }
                               6462                 :         }
                               6463                 : 
 2271 peter_e                  6464 GIC         144 :         printTable(&cont, pset.queryFout, false, pset.logfile);
                               6465             144 :         printTableCleanup(&cont);
                               6466                 : 
 2271 peter_e                  6467 CBC         144 :         termPQExpBuffer(&title);
 2271 peter_e                  6468 EUB             :     }
                               6469                 : 
 2271 peter_e                  6470 CBC         144 :     termPQExpBuffer(&buf);
 2271 peter_e                  6471 GIC         144 :     PQclear(res);
                               6472                 : 
 2271 peter_e                  6473 CBC         144 :     return true;
                               6474                 : 
  529 akapila                  6475 UIC           0 : error_return:
                               6476               0 :     printTableCleanup(&cont);
                               6477               0 :     PQclear(res);
                               6478               0 :     termPQExpBuffer(&buf);
  529 akapila                  6479 LBC           0 :     termPQExpBuffer(&title);
  529 akapila                  6480 UIC           0 :     return false;
 2271 peter_e                  6481 EUB             : }
                               6482                 : 
                               6483                 : /*
                               6484                 :  * \dRs
 2271 peter_e                  6485 ECB             :  * Describes subscriptions.
                               6486                 :  *
                               6487                 :  * Takes an optional regexp to select particular subscriptions
                               6488                 :  */
                               6489                 : bool
 2271 peter_e                  6490 GIC          72 : describeSubscriptions(const char *pattern, bool verbose)
 2271 peter_e                  6491 ECB             : {
                               6492                 :     PQExpBufferData buf;
                               6493                 :     PGresult   *res;
 2271 peter_e                  6494 CBC          72 :     printQueryOpt myopt = pset.popt;
                               6495                 :     static const bool translate_columns[] = {false, false, false, false,
                               6496                 :     false, false, false, false, false, false, false, false, false};
 2271 peter_e                  6497 EUB             : 
 2271 peter_e                  6498 GBC          72 :     if (pset.sversion < 100000)
 2271 peter_e                  6499 EUB             :     {
                               6500                 :         char        sverbuf[32];
 2153 bruce                    6501                 : 
 1469 peter                    6502 UIC           0 :         pg_log_error("The server (version %s) does not support subscriptions.",
                               6503                 :                      formatPGVersionNumber(pset.sversion, false,
                               6504                 :                                            sverbuf, sizeof(sverbuf)));
 2271 peter_e                  6505               0 :         return true;
                               6506                 :     }
                               6507                 : 
 2271 peter_e                  6508 GIC          72 :     initPQExpBuffer(&buf);
                               6509                 : 
                               6510              72 :     printfPQExpBuffer(&buf,
 2271 peter_e                  6511 ECB             :                       "SELECT subname AS \"%s\"\n"
                               6512                 :                       ",  pg_catalog.pg_get_userbyid(subowner) AS \"%s\"\n"
                               6513                 :                       ",  subenabled AS \"%s\"\n"
                               6514                 :                       ",  subpublications AS \"%s\"\n",
                               6515                 :                       gettext_noop("Name"),
                               6516                 :                       gettext_noop("Owner"),
                               6517                 :                       gettext_noop("Enabled"),
                               6518                 :                       gettext_noop("Publication"));
                               6519                 : 
 2271 peter_e                  6520 GIC          72 :     if (verbose)
                               6521                 :     {
                               6522                 :         /* Binary mode and streaming are only supported in v14 and higher */
  995 tgl                      6523 GBC          54 :         if (pset.sversion >= 140000)
                               6524                 :         {
  995 tgl                      6525 GIC          54 :             appendPQExpBuffer(&buf,
                               6526                 :                               ", subbinary AS \"%s\"\n",
                               6527                 :                               gettext_noop("Binary"));
                               6528                 : 
   90 akapila                  6529 GNC          54 :             if (pset.sversion >= 160000)
                               6530              54 :                 appendPQExpBuffer(&buf,
                               6531                 :                                   ", (CASE substream\n"
                               6532                 :                                   "    WHEN 'f' THEN 'off'\n"
                               6533                 :                                   "    WHEN 't' THEN 'on'\n"
                               6534                 :                                   "    WHEN 'p' THEN 'parallel'\n"
                               6535                 :                                   "   END) AS \"%s\"\n",
                               6536                 :                                   gettext_noop("Streaming"));
                               6537                 :             else
   90 akapila                  6538 UNC           0 :                 appendPQExpBuffer(&buf,
                               6539                 :                                   ", substream AS \"%s\"\n",
                               6540                 :                                   gettext_noop("Streaming"));
                               6541                 :         }
  995 tgl                      6542 ECB             : 
                               6543                 :         /* Two_phase and disable_on_error are only supported in v15 and higher */
  634 akapila                  6544 CBC          54 :         if (pset.sversion >= 150000)
  634 akapila                  6545 GIC          54 :             appendPQExpBuffer(&buf,
                               6546                 :                               ", subtwophasestate AS \"%s\"\n"
                               6547                 :                               ", subdisableonerr AS \"%s\"\n",
                               6548                 :                               gettext_noop("Two-phase commit"),
                               6549                 :                               gettext_noop("Disable on error"));
                               6550                 : 
  262 akapila                  6551 GNC          54 :         if (pset.sversion >= 160000)
                               6552              54 :             appendPQExpBuffer(&buf,
                               6553                 :                               ", suborigin AS \"%s\"\n"
                               6554                 :                               ", subrunasowner AS \"%s\"\n",
                               6555                 :                               gettext_noop("Origin"),
                               6556                 :                               gettext_noop("Run as Owner?"));
                               6557                 : 
 2271 peter_e                  6558 GIC          54 :         appendPQExpBuffer(&buf,
                               6559                 :                           ",  subsynccommit AS \"%s\"\n"
                               6560                 :                           ",  subconninfo AS \"%s\"\n",
 2186 peter_e                  6561 ECB             :                           gettext_noop("Synchronous commit"),
                               6562                 :                           gettext_noop("Conninfo"));
                               6563                 : 
  383 akapila                  6564                 :         /* Skip LSN is only supported in v15 and higher */
  383 akapila                  6565 GIC          54 :         if (pset.sversion >= 150000)
  383 akapila                  6566 CBC          54 :             appendPQExpBuffer(&buf,
                               6567                 :                               ", subskiplsn AS \"%s\"\n",
                               6568                 :                               gettext_noop("Skip LSN"));
                               6569                 :     }
 2271 peter_e                  6570 ECB             : 
 2253 heikki.linnakangas       6571                 :     /* Only display subscriptions in current database. */
 2271 peter_e                  6572 GIC          72 :     appendPQExpBufferStr(&buf,
                               6573                 :                          "FROM pg_catalog.pg_subscription\n"
                               6574                 :                          "WHERE subdbid = (SELECT oid\n"
                               6575                 :                          "                 FROM pg_catalog.pg_database\n"
                               6576                 :                          "                 WHERE datname = pg_catalog.current_database())");
                               6577                 : 
  354 rhaas                    6578              72 :     if (!validateSQLNamePattern(&buf, pattern, true, false,
  354 rhaas                    6579 EUB             :                                 NULL, "subname", NULL,
                               6580                 :                                 NULL,
                               6581                 :                                 NULL, 1))
                               6582                 :     {
  262 michael                  6583 GIC           9 :         termPQExpBuffer(&buf);
  354 rhaas                    6584               9 :         return false;
  262 michael                  6585 ECB             :     }
 2271 peter_e                  6586                 : 
 2271 peter_e                  6587 GIC          63 :     appendPQExpBufferStr(&buf, "ORDER BY 1;");
                               6588                 : 
                               6589              63 :     res = PSQLexec(buf.data);
                               6590              63 :     termPQExpBuffer(&buf);
                               6591              63 :     if (!res)
 2271 peter_e                  6592 LBC           0 :         return false;
 2271 peter_e                  6593 ECB             : 
 2271 peter_e                  6594 GIC          63 :     myopt.nullPrint = NULL;
                               6595              63 :     myopt.title = _("List of subscriptions");
                               6596              63 :     myopt.translate_header = true;
                               6597              63 :     myopt.translate_columns = translate_columns;
                               6598              63 :     myopt.n_translate_columns = lengthof(translate_columns);
 2271 peter_e                  6599 ECB             : 
 2271 peter_e                  6600 GIC          63 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               6601                 : 
                               6602              63 :     PQclear(res);
                               6603              63 :     return true;
                               6604                 : }
                               6605                 : 
 5212 tgl                      6606 ECB             : /*
                               6607                 :  * printACLColumn
                               6608                 :  *
                               6609                 :  * Helper function for consistently formatting ACL (privilege) columns.
                               6610                 :  * The proper targetlist entry is appended to buf.  Note lack of any
                               6611                 :  * whitespace or comma decoration.
                               6612                 :  */
                               6613                 : static void
 5212 tgl                      6614 GIC         132 : printACLColumn(PQExpBuffer buf, const char *colname)
                               6615                 : {
  479                          6616             132 :     appendPQExpBuffer(buf,
                               6617                 :                       "pg_catalog.array_to_string(%s, E'\\n') AS \"%s\"",
                               6618                 :                       colname, gettext_noop("Access privileges"));
 5212 tgl                      6619 CBC         132 : }
                               6620                 : 
                               6621                 : /*
                               6622                 :  * \dAc
                               6623                 :  * Lists operator classes
 1127 akorotkov                6624 ECB             :  *
  980 tgl                      6625                 :  * Takes optional regexps to filter by index access method and input data type.
                               6626                 :  */
                               6627                 : bool
 1127 akorotkov                6628 CBC          15 : listOperatorClasses(const char *access_method_pattern,
                               6629                 :                     const char *type_pattern, bool verbose)
 1127 akorotkov                6630 ECB             : {
                               6631                 :     PQExpBufferData buf;
                               6632                 :     PGresult   *res;
 1127 akorotkov                6633 GBC          15 :     printQueryOpt myopt = pset.popt;
 1127 akorotkov                6634 GIC          15 :     bool        have_where = false;
 1057 akorotkov                6635 ECB             :     static const bool translate_columns[] = {false, false, false, false, false, false, false};
 1127                          6636                 : 
 1127 akorotkov                6637 CBC          15 :     initPQExpBuffer(&buf);
 1127 akorotkov                6638 ECB             : 
 1127 akorotkov                6639 CBC          15 :     printfPQExpBuffer(&buf,
                               6640                 :                       "SELECT\n"
 1127 akorotkov                6641 ECB             :                       "  am.amname AS \"%s\",\n"
                               6642                 :                       "  pg_catalog.format_type(c.opcintype, NULL) AS \"%s\",\n"
 1002                          6643                 :                       "  CASE\n"
                               6644                 :                       "    WHEN c.opckeytype <> 0 AND c.opckeytype <> c.opcintype\n"
                               6645                 :                       "    THEN pg_catalog.format_type(c.opckeytype, NULL)\n"
                               6646                 :                       "    ELSE NULL\n"
                               6647                 :                       "  END AS \"%s\",\n"
                               6648                 :                       "  CASE\n"
                               6649                 :                       "    WHEN pg_catalog.pg_opclass_is_visible(c.oid)\n"
                               6650                 :                       "    THEN pg_catalog.format('%%I', c.opcname)\n"
                               6651                 :                       "    ELSE pg_catalog.format('%%I.%%I', n.nspname, c.opcname)\n"
                               6652                 :                       "  END AS \"%s\",\n"
                               6653                 :                       "  (CASE WHEN c.opcdefault\n"
                               6654                 :                       "    THEN '%s'\n"
 1127                          6655                 :                       "    ELSE '%s'\n"
                               6656                 :                       "  END) AS \"%s\"",
                               6657                 :                       gettext_noop("AM"),
                               6658                 :                       gettext_noop("Input type"),
                               6659                 :                       gettext_noop("Storage type"),
                               6660                 :                       gettext_noop("Operator class"),
                               6661                 :                       gettext_noop("yes"),
                               6662                 :                       gettext_noop("no"),
                               6663                 :                       gettext_noop("Default?"));
 1127 akorotkov                6664 GIC          15 :     if (verbose)
 1127 akorotkov                6665 UIC           0 :         appendPQExpBuffer(&buf,
                               6666                 :                           ",\n  CASE\n"
                               6667                 :                           "    WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
                               6668                 :                           "    THEN pg_catalog.format('%%I', of.opfname)\n"
 1002 akorotkov                6669 ECB             :                           "    ELSE pg_catalog.format('%%I.%%I', ofn.nspname, of.opfname)\n"
                               6670                 :                           "  END AS \"%s\",\n"
                               6671                 :                           " pg_catalog.pg_get_userbyid(c.opcowner) AS \"%s\"\n",
                               6672                 :                           gettext_noop("Operator family"),
                               6673                 :                           gettext_noop("Owner"));
  906 drowley                  6674 CBC          15 :     appendPQExpBufferStr(&buf,
  906 drowley                  6675 ECB             :                          "\nFROM pg_catalog.pg_opclass c\n"
                               6676                 :                          "  LEFT JOIN pg_catalog.pg_am am on am.oid = c.opcmethod\n"
                               6677                 :                          "  LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.opcnamespace\n"
                               6678                 :                          "  LEFT JOIN pg_catalog.pg_type t ON t.oid = c.opcintype\n"
                               6679                 :                          "  LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n");
 1127 akorotkov                6680 CBC          15 :     if (verbose)
  906 drowley                  6681 UIC           0 :         appendPQExpBufferStr(&buf,
                               6682                 :                              "  LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = c.opcfamily\n"
                               6683                 :                              "  LEFT JOIN pg_catalog.pg_namespace ofn ON ofn.oid = of.opfnamespace\n");
                               6684                 : 
 1127 akorotkov                6685 GIC          15 :     if (access_method_pattern)
  354 rhaas                    6686              15 :         if (!validateSQLNamePattern(&buf, access_method_pattern,
                               6687                 :                                     false, false, NULL, "am.amname", NULL, NULL,
                               6688                 :                                     &have_where, 1))
  262 michael                  6689               9 :             goto error_return;
 1127 akorotkov                6690               6 :     if (type_pattern)
                               6691                 :     {
                               6692                 :         /* Match type name pattern against either internal or external name */
  354 rhaas                    6693               3 :         if (!validateSQLNamePattern(&buf, type_pattern, have_where, false,
                               6694                 :                                     "tn.nspname", "t.typname",
                               6695                 :                                     "pg_catalog.format_type(t.oid, NULL)",
                               6696                 :                                     "pg_catalog.pg_type_is_visible(t.oid)",
                               6697                 :                                     NULL, 3))
  262 michael                  6698 UIC           0 :             goto error_return;
                               6699                 :     }
                               6700                 : 
 1127 akorotkov                6701 GIC           6 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
                               6702               6 :     res = PSQLexec(buf.data);
                               6703               6 :     termPQExpBuffer(&buf);
                               6704               6 :     if (!res)
 1127 akorotkov                6705 LBC           0 :         return false;
 1127 akorotkov                6706 EUB             : 
 1127 akorotkov                6707 GIC           6 :     myopt.nullPrint = NULL;
                               6708               6 :     myopt.title = _("List of operator classes");
                               6709               6 :     myopt.translate_header = true;
                               6710               6 :     myopt.translate_columns = translate_columns;
                               6711               6 :     myopt.n_translate_columns = lengthof(translate_columns);
                               6712                 : 
                               6713               6 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               6714                 : 
 1127 akorotkov                6715 CBC           6 :     PQclear(res);
 1127 akorotkov                6716 GIC           6 :     return true;
                               6717                 : 
  262 michael                  6718               9 : error_return:
                               6719               9 :     termPQExpBuffer(&buf);
                               6720               9 :     return false;
 1127 akorotkov                6721 ECB             : }
 1127 akorotkov                6722 EUB             : 
                               6723                 : /*
                               6724                 :  * \dAf
                               6725                 :  * Lists operator families
 1127 akorotkov                6726 ECB             :  *
  980 tgl                      6727                 :  * Takes optional regexps to filter by index access method and input data type.
                               6728                 :  */
                               6729                 : bool
 1127 akorotkov                6730 CBC          18 : listOperatorFamilies(const char *access_method_pattern,
 1127 akorotkov                6731 ECB             :                      const char *type_pattern, bool verbose)
                               6732                 : {
                               6733                 :     PQExpBufferData buf;
                               6734                 :     PGresult   *res;
 1127 akorotkov                6735 GIC          18 :     printQueryOpt myopt = pset.popt;
                               6736              18 :     bool        have_where = false;
                               6737                 :     static const bool translate_columns[] = {false, false, false, false};
                               6738                 : 
 1127 akorotkov                6739 GBC          18 :     initPQExpBuffer(&buf);
                               6740                 : 
 1127 akorotkov                6741 GIC          18 :     printfPQExpBuffer(&buf,
  979 tgl                      6742 ECB             :                       "SELECT\n"
 1127 akorotkov                6743                 :                       "  am.amname AS \"%s\",\n"
                               6744                 :                       "  CASE\n"
                               6745                 :                       "    WHEN pg_catalog.pg_opfamily_is_visible(f.oid)\n"
 1002 akorotkov                6746 EUB             :                       "    THEN pg_catalog.format('%%I', f.opfname)\n"
                               6747                 :                       "    ELSE pg_catalog.format('%%I.%%I', n.nspname, f.opfname)\n"
 1127 akorotkov                6748 ECB             :                       "  END AS \"%s\",\n"
                               6749                 :                       "  (SELECT\n"
 1002                          6750                 :                       "     pg_catalog.string_agg(pg_catalog.format_type(oc.opcintype, NULL), ', ')\n"
                               6751                 :                       "   FROM pg_catalog.pg_opclass oc\n"
 1127                          6752                 :                       "   WHERE oc.opcfamily = f.oid) \"%s\"",
                               6753                 :                       gettext_noop("AM"),
                               6754                 :                       gettext_noop("Operator family"),
                               6755                 :                       gettext_noop("Applicable types"));
 1127 akorotkov                6756 CBC          18 :     if (verbose)
 1127 akorotkov                6757 LBC           0 :         appendPQExpBuffer(&buf,
                               6758                 :                           ",\n  pg_catalog.pg_get_userbyid(f.opfowner) AS \"%s\"\n",
 1127 akorotkov                6759 ECB             :                           gettext_noop("Owner"));
  906 drowley                  6760 CBC          18 :     appendPQExpBufferStr(&buf,
  906 drowley                  6761 ECB             :                          "\nFROM pg_catalog.pg_opfamily f\n"
                               6762                 :                          "  LEFT JOIN pg_catalog.pg_am am on am.oid = f.opfmethod\n"
                               6763                 :                          "  LEFT JOIN pg_catalog.pg_namespace n ON n.oid = f.opfnamespace\n");
                               6764                 : 
 1127 akorotkov                6765 GIC          18 :     if (access_method_pattern)
  354 rhaas                    6766              18 :         if (!validateSQLNamePattern(&buf, access_method_pattern,
                               6767                 :                                     false, false, NULL, "am.amname", NULL, NULL,
                               6768                 :                                     &have_where, 1))
  262 michael                  6769               9 :             goto error_return;
 1127 akorotkov                6770               9 :     if (type_pattern)
 1127 akorotkov                6771 ECB             :     {
 1127 akorotkov                6772 GIC           3 :         appendPQExpBuffer(&buf,
                               6773                 :                           "  %s EXISTS (\n"
                               6774                 :                           "    SELECT 1\n"
                               6775                 :                           "    FROM pg_catalog.pg_type t\n"
 1002 akorotkov                6776 ECB             :                           "    JOIN pg_catalog.pg_opclass oc ON oc.opcintype = t.oid\n"
  980 tgl                      6777                 :                           "    LEFT JOIN pg_catalog.pg_namespace tn ON tn.oid = t.typnamespace\n"
                               6778                 :                           "    WHERE oc.opcfamily = f.oid\n",
 1127 akorotkov                6779 GIC           3 :                           have_where ? "AND" : "WHERE");
  980 tgl                      6780 ECB             :         /* Match type name pattern against either internal or external name */
  354 rhaas                    6781 GIC           3 :         if (!validateSQLNamePattern(&buf, type_pattern, true, false,
  354 rhaas                    6782 ECB             :                                     "tn.nspname", "t.typname",
                               6783                 :                                     "pg_catalog.format_type(t.oid, NULL)",
                               6784                 :                                     "pg_catalog.pg_type_is_visible(t.oid)",
                               6785                 :                                     NULL, 3))
  262 michael                  6786 UIC           0 :             goto error_return;
  906 drowley                  6787 GIC           3 :         appendPQExpBufferStr(&buf, "  )\n");
                               6788                 :     }
                               6789                 : 
 1127 akorotkov                6790               9 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
                               6791               9 :     res = PSQLexec(buf.data);
                               6792               9 :     termPQExpBuffer(&buf);
                               6793               9 :     if (!res)
 1127 akorotkov                6794 UIC           0 :         return false;
                               6795                 : 
 1127 akorotkov                6796 GIC           9 :     myopt.nullPrint = NULL;
 1127 akorotkov                6797 CBC           9 :     myopt.title = _("List of operator families");
 1127 akorotkov                6798 GBC           9 :     myopt.translate_header = true;
 1127 akorotkov                6799 GIC           9 :     myopt.translate_columns = translate_columns;
                               6800               9 :     myopt.n_translate_columns = lengthof(translate_columns);
 1127 akorotkov                6801 ECB             : 
 1127 akorotkov                6802 GIC           9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               6803                 : 
                               6804               9 :     PQclear(res);
                               6805               9 :     return true;
  262 michael                  6806 ECB             : 
  262 michael                  6807 CBC           9 : error_return:
  262 michael                  6808 GIC           9 :     termPQExpBuffer(&buf);
                               6809               9 :     return false;
 1127 akorotkov                6810 ECB             : }
                               6811                 : 
                               6812                 : /*
                               6813                 :  * \dAo
                               6814                 :  * Lists operators of operator families
                               6815                 :  *
                               6816                 :  * Takes optional regexps to filter by index access method and operator
                               6817                 :  * family.
                               6818                 :  */
                               6819                 : bool
 1127 akorotkov                6820 CBC          18 : listOpFamilyOperators(const char *access_method_pattern,
                               6821                 :                       const char *family_pattern, bool verbose)
 1127 akorotkov                6822 ECB             : {
                               6823                 :     PQExpBufferData buf;
                               6824                 :     PGresult   *res;
 1127 akorotkov                6825 GIC          18 :     printQueryOpt myopt = pset.popt;
                               6826              18 :     bool        have_where = false;
 1127 akorotkov                6827 EUB             : 
 1057 akorotkov                6828 ECB             :     static const bool translate_columns[] = {false, false, false, false, false, false};
                               6829                 : 
 1127 akorotkov                6830 GIC          18 :     initPQExpBuffer(&buf);
 1127 akorotkov                6831 ECB             : 
 1127 akorotkov                6832 CBC          18 :     printfPQExpBuffer(&buf,
 1127 akorotkov                6833 ECB             :                       "SELECT\n"
                               6834                 :                       "  am.amname AS \"%s\",\n"
 1127 akorotkov                6835 EUB             :                       "  CASE\n"
                               6836                 :                       "    WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
 1002 akorotkov                6837 ECB             :                       "    THEN pg_catalog.format('%%I', of.opfname)\n"
                               6838                 :                       "    ELSE pg_catalog.format('%%I.%%I', nsf.nspname, of.opfname)\n"
 1127                          6839                 :                       "  END AS \"%s\",\n"
 1002                          6840                 :                       "  o.amopopr::pg_catalog.regoperator AS \"%s\"\n,"
                               6841                 :                       "  o.amopstrategy AS \"%s\",\n"
                               6842                 :                       "  CASE o.amoppurpose\n"
                               6843                 :                       "    WHEN 'o' THEN '%s'\n"
                               6844                 :                       "    WHEN 's' THEN '%s'\n"
                               6845                 :                       "  END AS \"%s\"\n",
 1127                          6846                 :                       gettext_noop("AM"),
                               6847                 :                       gettext_noop("Operator family"),
 1002                          6848                 :                       gettext_noop("Operator"),
                               6849                 :                       gettext_noop("Strategy"),
                               6850                 :                       gettext_noop("ordering"),
                               6851                 :                       gettext_noop("search"),
                               6852                 :                       gettext_noop("Purpose"));
                               6853                 : 
 1127 akorotkov                6854 GIC          18 :     if (verbose)
                               6855               3 :         appendPQExpBuffer(&buf,
                               6856                 :                           ", ofs.opfname AS \"%s\"\n",
                               6857                 :                           gettext_noop("Sort opfamily"));
  906 drowley                  6858              18 :     appendPQExpBufferStr(&buf,
                               6859                 :                          "FROM pg_catalog.pg_amop o\n"
                               6860                 :                          "  LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = o.amopfamily\n"
  906 drowley                  6861 ECB             :                          "  LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod AND am.oid = o.amopmethod\n"
                               6862                 :                          "  LEFT JOIN pg_catalog.pg_namespace nsf ON of.opfnamespace = nsf.oid\n");
 1127 akorotkov                6863 GIC          18 :     if (verbose)
  906 drowley                  6864               3 :         appendPQExpBufferStr(&buf,
                               6865                 :                              "  LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n");
 1127 akorotkov                6866 ECB             : 
 1127 akorotkov                6867 CBC          18 :     if (access_method_pattern)
                               6868                 :     {
  354 rhaas                    6869 GIC          18 :         if (!validateSQLNamePattern(&buf, access_method_pattern,
                               6870                 :                                     false, false, NULL, "am.amname",
  354 rhaas                    6871 ECB             :                                     NULL, NULL,
                               6872                 :                                     &have_where, 1))
  262 michael                  6873 CBC           9 :             goto error_return;
                               6874                 :     }
                               6875                 : 
 1127 akorotkov                6876 GIC           9 :     if (family_pattern)
                               6877                 :     {
  354 rhaas                    6878               6 :         if (!validateSQLNamePattern(&buf, family_pattern, have_where, false,
                               6879                 :                                     "nsf.nspname", "of.opfname", NULL, NULL,
                               6880                 :                                     NULL, 3))
  262 michael                  6881 UIC           0 :             goto error_return;
                               6882                 :     }
                               6883                 : 
 1057 akorotkov                6884 GIC           9 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
                               6885                 :                          "  o.amoplefttype = o.amoprighttype DESC,\n"
                               6886                 :                          "  pg_catalog.format_type(o.amoplefttype, NULL),\n"
                               6887                 :                          "  pg_catalog.format_type(o.amoprighttype, NULL),\n"
                               6888                 :                          "  o.amopstrategy;");
                               6889                 : 
 1127                          6890               9 :     res = PSQLexec(buf.data);
                               6891               9 :     termPQExpBuffer(&buf);
                               6892               9 :     if (!res)
 1127 akorotkov                6893 UIC           0 :         return false;
                               6894                 : 
 1127 akorotkov                6895 CBC           9 :     myopt.nullPrint = NULL;
                               6896               9 :     myopt.title = _("List of operators of operator families");
 1127 akorotkov                6897 GIC           9 :     myopt.translate_header = true;
                               6898               9 :     myopt.translate_columns = translate_columns;
 1127 akorotkov                6899 CBC           9 :     myopt.n_translate_columns = lengthof(translate_columns);
                               6900                 : 
 1127 akorotkov                6901 GIC           9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               6902                 : 
                               6903               9 :     PQclear(res);
 1127 akorotkov                6904 CBC           9 :     return true;
  262 michael                  6905 ECB             : 
  262 michael                  6906 GIC           9 : error_return:
                               6907               9 :     termPQExpBuffer(&buf);
  262 michael                  6908 CBC           9 :     return false;
                               6909                 : }
 1127 akorotkov                6910 ECB             : 
                               6911                 : /*
                               6912                 :  * \dAp
                               6913                 :  * Lists support functions of operator families
                               6914                 :  *
                               6915                 :  * Takes optional regexps to filter by index access method and operator
                               6916                 :  * family.
                               6917                 :  */
                               6918                 : bool
 1039 peter                    6919 CBC          18 : listOpFamilyFunctions(const char *access_method_pattern,
                               6920                 :                       const char *family_pattern, bool verbose)
                               6921                 : {
 1127 akorotkov                6922 EUB             :     PQExpBufferData buf;
                               6923                 :     PGresult   *res;
 1127 akorotkov                6924 GIC          18 :     printQueryOpt myopt = pset.popt;
 1127 akorotkov                6925 CBC          18 :     bool        have_where = false;
                               6926                 :     static const bool translate_columns[] = {false, false, false, false, false, false};
                               6927                 : 
 1127 akorotkov                6928 GIC          18 :     initPQExpBuffer(&buf);
                               6929                 : 
                               6930              18 :     printfPQExpBuffer(&buf,
 1057 akorotkov                6931 ECB             :                       "SELECT\n"
 1127                          6932                 :                       "  am.amname AS \"%s\",\n"
                               6933                 :                       "  CASE\n"
 1127 akorotkov                6934 EUB             :                       "    WHEN pg_catalog.pg_opfamily_is_visible(of.oid)\n"
                               6935                 :                       "    THEN pg_catalog.format('%%I', of.opfname)\n"
 1002 akorotkov                6936 ECB             :                       "    ELSE pg_catalog.format('%%I.%%I', ns.nspname, of.opfname)\n"
 1127                          6937                 :                       "  END AS \"%s\",\n"
                               6938                 :                       "  pg_catalog.format_type(ap.amproclefttype, NULL) AS \"%s\",\n"
                               6939                 :                       "  pg_catalog.format_type(ap.amprocrighttype, NULL) AS \"%s\",\n"
 1002                          6940                 :                       "  ap.amprocnum AS \"%s\"\n",
                               6941                 :                       gettext_noop("AM"),
 1127                          6942                 :                       gettext_noop("Operator family"),
                               6943                 :                       gettext_noop("Registered left type"),
 1002                          6944                 :                       gettext_noop("Registered right type"),
                               6945                 :                       gettext_noop("Number"));
                               6946                 : 
 1002 akorotkov                6947 CBC          18 :     if (!verbose)
                               6948              15 :         appendPQExpBuffer(&buf,
 1002 akorotkov                6949 ECB             :                           ", p.proname AS \"%s\"\n",
                               6950                 :                           gettext_noop("Function"));
                               6951                 :     else
 1002 akorotkov                6952 GIC           3 :         appendPQExpBuffer(&buf,
                               6953                 :                           ", ap.amproc::pg_catalog.regprocedure AS \"%s\"\n",
                               6954                 :                           gettext_noop("Function"));
                               6955                 : 
  906 drowley                  6956              18 :     appendPQExpBufferStr(&buf,
                               6957                 :                          "FROM pg_catalog.pg_amproc ap\n"
                               6958                 :                          "  LEFT JOIN pg_catalog.pg_opfamily of ON of.oid = ap.amprocfamily\n"
                               6959                 :                          "  LEFT JOIN pg_catalog.pg_am am ON am.oid = of.opfmethod\n"
  906 drowley                  6960 ECB             :                          "  LEFT JOIN pg_catalog.pg_namespace ns ON of.opfnamespace = ns.oid\n"
                               6961                 :                          "  LEFT JOIN pg_catalog.pg_proc p ON ap.amproc = p.oid\n");
                               6962                 : 
 1127 akorotkov                6963 GIC          18 :     if (access_method_pattern)
                               6964                 :     {
  354 rhaas                    6965 CBC          18 :         if (!validateSQLNamePattern(&buf, access_method_pattern,
  354 rhaas                    6966 ECB             :                                     false, false, NULL, "am.amname",
                               6967                 :                                     NULL, NULL,
                               6968                 :                                     &have_where, 1))
  262 michael                  6969 CBC           9 :             goto error_return;
                               6970                 :     }
 1127 akorotkov                6971               9 :     if (family_pattern)
                               6972                 :     {
  354 rhaas                    6973 GIC           6 :         if (!validateSQLNamePattern(&buf, family_pattern, have_where, false,
                               6974                 :                                     "ns.nspname", "of.opfname", NULL, NULL,
                               6975                 :                                     NULL, 3))
  262 michael                  6976 UIC           0 :             goto error_return;
                               6977                 :     }
                               6978                 : 
 1057 akorotkov                6979 GIC           9 :     appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
                               6980                 :                          "  ap.amproclefttype = ap.amprocrighttype DESC,\n"
                               6981                 :                          "  3, 4, 5;");
                               6982                 : 
 1127                          6983               9 :     res = PSQLexec(buf.data);
                               6984               9 :     termPQExpBuffer(&buf);
                               6985               9 :     if (!res)
 1127 akorotkov                6986 UIC           0 :         return false;
                               6987                 : 
 1127 akorotkov                6988 CBC           9 :     myopt.nullPrint = NULL;
 1039 peter                    6989               9 :     myopt.title = _("List of support functions of operator families");
 1127 akorotkov                6990 GIC           9 :     myopt.translate_header = true;
                               6991               9 :     myopt.translate_columns = translate_columns;
                               6992               9 :     myopt.n_translate_columns = lengthof(translate_columns);
 1127 akorotkov                6993 ECB             : 
 1127 akorotkov                6994 GIC           9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               6995                 : 
                               6996               9 :     PQclear(res);
 1127 akorotkov                6997 CBC           9 :     return true;
                               6998                 : 
  262 michael                  6999 GIC           9 : error_return:
                               7000               9 :     termPQExpBuffer(&buf);
                               7001               9 :     return false;
                               7002                 : }
                               7003                 : 
  458 tgl                      7004 ECB             : /*
                               7005                 :  * \dl or \lo_list
                               7006                 :  * Lists large objects
                               7007                 :  */
                               7008                 : bool
  458 tgl                      7009 GIC           9 : listLargeObjects(bool verbose)
  458 tgl                      7010 ECB             : {
                               7011                 :     PQExpBufferData buf;
                               7012                 :     PGresult   *res;
  458 tgl                      7013 GIC           9 :     printQueryOpt myopt = pset.popt;
  458 tgl                      7014 ECB             : 
  458 tgl                      7015 GIC           9 :     initPQExpBuffer(&buf);
                               7016                 : 
  458 tgl                      7017 GBC           9 :     printfPQExpBuffer(&buf,
                               7018                 :                       "SELECT oid as \"%s\",\n"
                               7019                 :                       "  pg_catalog.pg_get_userbyid(lomowner) as \"%s\",\n  ",
  458 tgl                      7020 ECB             :                       gettext_noop("ID"),
                               7021                 :                       gettext_noop("Owner"));
                               7022                 : 
  458 tgl                      7023 GIC           9 :     if (verbose)
  458 tgl                      7024 ECB             :     {
  458 tgl                      7025 CBC           3 :         printACLColumn(&buf, "lomacl");
                               7026               3 :         appendPQExpBufferStr(&buf, ",\n  ");
  458 tgl                      7027 EUB             :     }
                               7028                 : 
  458 tgl                      7029 CBC           9 :     appendPQExpBuffer(&buf,
  458 tgl                      7030 ECB             :                       "pg_catalog.obj_description(oid, 'pg_largeobject') as \"%s\"\n"
                               7031                 :                       "FROM pg_catalog.pg_largeobject_metadata\n"
                               7032                 :                       "ORDER BY oid",
                               7033                 :                       gettext_noop("Description"));
                               7034                 : 
  458 tgl                      7035 CBC           9 :     res = PSQLexec(buf.data);
  458 tgl                      7036 GIC           9 :     termPQExpBuffer(&buf);
  458 tgl                      7037 CBC           9 :     if (!res)
  458 tgl                      7038 LBC           0 :         return false;
                               7039                 : 
  458 tgl                      7040 CBC           9 :     myopt.nullPrint = NULL;
                               7041               9 :     myopt.title = _("Large objects");
                               7042               9 :     myopt.translate_header = true;
                               7043                 : 
  458 tgl                      7044 GIC           9 :     printQuery(res, &myopt, pset.queryFout, false, pset.logfile);
                               7045                 : 
                               7046               9 :     PQclear(res);
                               7047               9 :     return true;
                               7048                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a