LCOV - differential code coverage report
Current view: top level - src/bin/pg_dump - pg_dump.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: 88.0 % 7568 6661 78 270 503 56 301 3690 245 2425 534 3800 16 166
Current Date: 2023-04-08 15:15:32 Functions: 97.7 % 172 168 4 165 3 4 162 6
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * pg_dump.c
       4                 :  *    pg_dump is a utility for dumping out a postgres database
       5                 :  *    into a script file.
       6                 :  *
       7                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       8                 :  * Portions Copyright (c) 1994, Regents of the University of California
       9                 :  *
      10                 :  *  pg_dump will read the system catalogs in a database and dump out a
      11                 :  *  script that reproduces the schema in terms of SQL that is understood
      12                 :  *  by PostgreSQL
      13                 :  *
      14                 :  *  Note that pg_dump runs in a transaction-snapshot mode transaction,
      15                 :  *  so it sees a consistent snapshot of the database including system
      16                 :  *  catalogs. However, it relies in part on various specialized backend
      17                 :  *  functions like pg_get_indexdef(), and those things tend to look at
      18                 :  *  the currently committed state.  So it is possible to get 'cache
      19                 :  *  lookup failed' error if someone performs DDL changes while a dump is
      20                 :  *  happening. The window for this sort of thing is from the acquisition
      21                 :  *  of the transaction snapshot to getSchemaData() (when pg_dump acquires
      22                 :  *  AccessShareLock on every table it intends to dump). It isn't very large,
      23                 :  *  but it can happen.
      24                 :  *
      25                 :  *  http://archives.postgresql.org/pgsql-bugs/2010-02/msg00187.php
      26                 :  *
      27                 :  * IDENTIFICATION
      28                 :  *    src/bin/pg_dump/pg_dump.c
      29                 :  *
      30                 :  *-------------------------------------------------------------------------
      31                 :  */
      32                 : #include "postgres_fe.h"
      33                 : 
      34                 : #include <unistd.h>
      35                 : #include <ctype.h>
      36                 : #include <limits.h>
      37                 : #ifdef HAVE_TERMIOS_H
      38                 : #include <termios.h>
      39                 : #endif
      40                 : 
      41                 : #include "access/attnum.h"
      42                 : #include "access/sysattr.h"
      43                 : #include "access/transam.h"
      44                 : #include "catalog/pg_aggregate_d.h"
      45                 : #include "catalog/pg_am_d.h"
      46                 : #include "catalog/pg_attribute_d.h"
      47                 : #include "catalog/pg_authid_d.h"
      48                 : #include "catalog/pg_cast_d.h"
      49                 : #include "catalog/pg_class_d.h"
      50                 : #include "catalog/pg_default_acl_d.h"
      51                 : #include "catalog/pg_largeobject_d.h"
      52                 : #include "catalog/pg_largeobject_metadata_d.h"
      53                 : #include "catalog/pg_proc_d.h"
      54                 : #include "catalog/pg_subscription.h"
      55                 : #include "catalog/pg_trigger_d.h"
      56                 : #include "catalog/pg_type_d.h"
      57                 : #include "common/connect.h"
      58                 : #include "common/relpath.h"
      59                 : #include "compress_io.h"
      60                 : #include "dumputils.h"
      61                 : #include "fe_utils/option_utils.h"
      62                 : #include "fe_utils/string_utils.h"
      63                 : #include "getopt_long.h"
      64                 : #include "libpq/libpq-fs.h"
      65                 : #include "parallel.h"
      66                 : #include "pg_backup_db.h"
      67                 : #include "pg_backup_utils.h"
      68                 : #include "pg_dump.h"
      69                 : #include "storage/block.h"
      70                 : 
      71                 : typedef struct
      72                 : {
      73                 :     Oid         roleoid;        /* role's OID */
      74                 :     const char *rolename;       /* role's name */
      75                 : } RoleNameItem;
      76                 : 
      77                 : typedef struct
      78                 : {
      79                 :     const char *descr;          /* comment for an object */
      80                 :     Oid         classoid;       /* object class (catalog OID) */
      81                 :     Oid         objoid;         /* object OID */
      82                 :     int         objsubid;       /* subobject (table column #) */
      83                 : } CommentItem;
      84                 : 
      85                 : typedef struct
      86                 : {
      87                 :     const char *provider;       /* label provider of this security label */
      88                 :     const char *label;          /* security label for an object */
      89                 :     Oid         classoid;       /* object class (catalog OID) */
      90                 :     Oid         objoid;         /* object OID */
      91                 :     int         objsubid;       /* subobject (table column #) */
      92                 : } SecLabelItem;
      93                 : 
      94                 : typedef enum OidOptions
      95                 : {
      96                 :     zeroIsError = 1,
      97                 :     zeroAsStar = 2,
      98                 :     zeroAsNone = 4
      99                 : } OidOptions;
     100                 : 
     101                 : /* global decls */
     102                 : static bool dosync = true;      /* Issue fsync() to make dump durable on disk. */
     103                 : 
     104                 : static Oid  g_last_builtin_oid; /* value of the last builtin oid */
     105                 : 
     106                 : /* The specified names/patterns should to match at least one entity */
     107                 : static int  strict_names = 0;
     108                 : 
     109                 : static pg_compress_algorithm compression_algorithm = PG_COMPRESSION_NONE;
     110                 : 
     111                 : /*
     112                 :  * Object inclusion/exclusion lists
     113                 :  *
     114                 :  * The string lists record the patterns given by command-line switches,
     115                 :  * which we then convert to lists of OIDs of matching objects.
     116                 :  */
     117                 : static SimpleStringList schema_include_patterns = {NULL, NULL};
     118                 : static SimpleOidList schema_include_oids = {NULL, NULL};
     119                 : static SimpleStringList schema_exclude_patterns = {NULL, NULL};
     120                 : static SimpleOidList schema_exclude_oids = {NULL, NULL};
     121                 : 
     122                 : static SimpleStringList table_include_patterns = {NULL, NULL};
     123                 : static SimpleStringList table_include_patterns_and_children = {NULL, NULL};
     124                 : static SimpleOidList table_include_oids = {NULL, NULL};
     125                 : static SimpleStringList table_exclude_patterns = {NULL, NULL};
     126                 : static SimpleStringList table_exclude_patterns_and_children = {NULL, NULL};
     127                 : static SimpleOidList table_exclude_oids = {NULL, NULL};
     128                 : static SimpleStringList tabledata_exclude_patterns = {NULL, NULL};
     129                 : static SimpleStringList tabledata_exclude_patterns_and_children = {NULL, NULL};
     130                 : static SimpleOidList tabledata_exclude_oids = {NULL, NULL};
     131                 : 
     132                 : static SimpleStringList foreign_servers_include_patterns = {NULL, NULL};
     133                 : static SimpleOidList foreign_servers_include_oids = {NULL, NULL};
     134                 : 
     135                 : static SimpleStringList extension_include_patterns = {NULL, NULL};
     136                 : static SimpleOidList extension_include_oids = {NULL, NULL};
     137                 : 
     138                 : static const CatalogId nilCatalogId = {0, 0};
     139                 : 
     140                 : /* override for standard extra_float_digits setting */
     141                 : static bool have_extra_float_digits = false;
     142                 : static int  extra_float_digits;
     143                 : 
     144                 : /* sorted table of role names */
     145                 : static RoleNameItem *rolenames = NULL;
     146                 : static int  nrolenames = 0;
     147                 : 
     148                 : /* sorted table of comments */
     149                 : static CommentItem *comments = NULL;
     150                 : static int  ncomments = 0;
     151                 : 
     152                 : /* sorted table of security labels */
     153                 : static SecLabelItem *seclabels = NULL;
     154                 : static int  nseclabels = 0;
     155                 : 
     156                 : /*
     157                 :  * The default number of rows per INSERT when
     158                 :  * --inserts is specified without --rows-per-insert
     159                 :  */
     160                 : #define DUMP_DEFAULT_ROWS_PER_INSERT 1
     161                 : 
     162                 : /*
     163                 :  * Macro for producing quoted, schema-qualified name of a dumpable object.
     164                 :  */
     165                 : #define fmtQualifiedDumpable(obj) \
     166                 :     fmtQualifiedId((obj)->dobj.namespace->dobj.name, \
     167                 :                    (obj)->dobj.name)
     168                 : 
     169                 : static void help(const char *progname);
     170                 : static void setup_connection(Archive *AH,
     171                 :                              const char *dumpencoding, const char *dumpsnapshot,
     172                 :                              char *use_role);
     173                 : static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
     174                 : static void expand_schema_name_patterns(Archive *fout,
     175                 :                                         SimpleStringList *patterns,
     176                 :                                         SimpleOidList *oids,
     177                 :                                         bool strict_names);
     178                 : static void expand_extension_name_patterns(Archive *fout,
     179                 :                                            SimpleStringList *patterns,
     180                 :                                            SimpleOidList *oids,
     181                 :                                            bool strict_names);
     182                 : static void expand_foreign_server_name_patterns(Archive *fout,
     183                 :                                                 SimpleStringList *patterns,
     184                 :                                                 SimpleOidList *oids);
     185                 : static void expand_table_name_patterns(Archive *fout,
     186                 :                                        SimpleStringList *patterns,
     187                 :                                        SimpleOidList *oids,
     188                 :                                        bool strict_names,
     189                 :                                        bool with_child_tables);
     190                 : static void prohibit_crossdb_refs(PGconn *conn, const char *dbname,
     191                 :                                   const char *pattern);
     192                 : 
     193                 : static NamespaceInfo *findNamespace(Oid nsoid);
     194                 : static void dumpTableData(Archive *fout, const TableDataInfo *tdinfo);
     195                 : static void refreshMatViewData(Archive *fout, const TableDataInfo *tdinfo);
     196                 : static const char *getRoleName(const char *roleoid_str);
     197                 : static void collectRoleNames(Archive *fout);
     198                 : static void getAdditionalACLs(Archive *fout);
     199                 : static void dumpCommentExtended(Archive *fout, const char *type,
     200                 :                                 const char *name, const char *namespace,
     201                 :                                 const char *owner, CatalogId catalogId,
     202                 :                                 int subid, DumpId dumpId,
     203                 :                                 const char *initdb_comment);
     204                 : static inline void dumpComment(Archive *fout, const char *type,
     205                 :                                const char *name, const char *namespace,
     206                 :                                const char *owner, CatalogId catalogId,
     207                 :                                int subid, DumpId dumpId);
     208                 : static int  findComments(Oid classoid, Oid objoid, CommentItem **items);
     209                 : static void collectComments(Archive *fout);
     210                 : static void dumpSecLabel(Archive *fout, const char *type, const char *name,
     211                 :                          const char *namespace, const char *owner,
     212                 :                          CatalogId catalogId, int subid, DumpId dumpId);
     213                 : static int  findSecLabels(Oid classoid, Oid objoid, SecLabelItem **items);
     214                 : static void collectSecLabels(Archive *fout);
     215                 : static void dumpDumpableObject(Archive *fout, DumpableObject *dobj);
     216                 : static void dumpNamespace(Archive *fout, const NamespaceInfo *nspinfo);
     217                 : static void dumpExtension(Archive *fout, const ExtensionInfo *extinfo);
     218                 : static void dumpType(Archive *fout, const TypeInfo *tyinfo);
     219                 : static void dumpBaseType(Archive *fout, const TypeInfo *tyinfo);
     220                 : static void dumpEnumType(Archive *fout, const TypeInfo *tyinfo);
     221                 : static void dumpRangeType(Archive *fout, const TypeInfo *tyinfo);
     222                 : static void dumpUndefinedType(Archive *fout, const TypeInfo *tyinfo);
     223                 : static void dumpDomain(Archive *fout, const TypeInfo *tyinfo);
     224                 : static void dumpCompositeType(Archive *fout, const TypeInfo *tyinfo);
     225                 : static void dumpCompositeTypeColComments(Archive *fout, const TypeInfo *tyinfo,
     226                 :                                          PGresult *res);
     227                 : static void dumpShellType(Archive *fout, const ShellTypeInfo *stinfo);
     228                 : static void dumpProcLang(Archive *fout, const ProcLangInfo *plang);
     229                 : static void dumpFunc(Archive *fout, const FuncInfo *finfo);
     230                 : static void dumpCast(Archive *fout, const CastInfo *cast);
     231                 : static void dumpTransform(Archive *fout, const TransformInfo *transform);
     232                 : static void dumpOpr(Archive *fout, const OprInfo *oprinfo);
     233                 : static void dumpAccessMethod(Archive *fout, const AccessMethodInfo *aminfo);
     234                 : static void dumpOpclass(Archive *fout, const OpclassInfo *opcinfo);
     235                 : static void dumpOpfamily(Archive *fout, const OpfamilyInfo *opfinfo);
     236                 : static void dumpCollation(Archive *fout, const CollInfo *collinfo);
     237                 : static void dumpConversion(Archive *fout, const ConvInfo *convinfo);
     238                 : static void dumpRule(Archive *fout, const RuleInfo *rinfo);
     239                 : static void dumpAgg(Archive *fout, const AggInfo *agginfo);
     240                 : static void dumpTrigger(Archive *fout, const TriggerInfo *tginfo);
     241                 : static void dumpEventTrigger(Archive *fout, const EventTriggerInfo *evtinfo);
     242                 : static void dumpTable(Archive *fout, const TableInfo *tbinfo);
     243                 : static void dumpTableSchema(Archive *fout, const TableInfo *tbinfo);
     244                 : static void dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo);
     245                 : static void dumpAttrDef(Archive *fout, const AttrDefInfo *adinfo);
     246                 : static void dumpSequence(Archive *fout, const TableInfo *tbinfo);
     247                 : static void dumpSequenceData(Archive *fout, const TableDataInfo *tdinfo);
     248                 : static void dumpIndex(Archive *fout, const IndxInfo *indxinfo);
     249                 : static void dumpIndexAttach(Archive *fout, const IndexAttachInfo *attachinfo);
     250                 : static void dumpStatisticsExt(Archive *fout, const StatsExtInfo *statsextinfo);
     251                 : static void dumpConstraint(Archive *fout, const ConstraintInfo *coninfo);
     252                 : static void dumpTableConstraintComment(Archive *fout, const ConstraintInfo *coninfo);
     253                 : static void dumpTSParser(Archive *fout, const TSParserInfo *prsinfo);
     254                 : static void dumpTSDictionary(Archive *fout, const TSDictInfo *dictinfo);
     255                 : static void dumpTSTemplate(Archive *fout, const TSTemplateInfo *tmplinfo);
     256                 : static void dumpTSConfig(Archive *fout, const TSConfigInfo *cfginfo);
     257                 : static void dumpForeignDataWrapper(Archive *fout, const FdwInfo *fdwinfo);
     258                 : static void dumpForeignServer(Archive *fout, const ForeignServerInfo *srvinfo);
     259                 : static void dumpUserMappings(Archive *fout,
     260                 :                              const char *servername, const char *namespace,
     261                 :                              const char *owner, CatalogId catalogId, DumpId dumpId);
     262                 : static void dumpDefaultACL(Archive *fout, const DefaultACLInfo *daclinfo);
     263                 : 
     264                 : static DumpId dumpACL(Archive *fout, DumpId objDumpId, DumpId altDumpId,
     265                 :                       const char *type, const char *name, const char *subname,
     266                 :                       const char *nspname, const char *owner,
     267                 :                       const DumpableAcl *dacl);
     268                 : 
     269                 : static void getDependencies(Archive *fout);
     270                 : static void BuildArchiveDependencies(Archive *fout);
     271                 : static void findDumpableDependencies(ArchiveHandle *AH, const DumpableObject *dobj,
     272                 :                                      DumpId **dependencies, int *nDeps, int *allocDeps);
     273                 : 
     274                 : static DumpableObject *createBoundaryObjects(void);
     275                 : static void addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
     276                 :                                     DumpableObject *boundaryObjs);
     277                 : 
     278                 : static void addConstrChildIdxDeps(DumpableObject *dobj, const IndxInfo *refidx);
     279                 : static void getDomainConstraints(Archive *fout, TypeInfo *tyinfo);
     280                 : static void getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, char relkind);
     281                 : static void makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo);
     282                 : static void buildMatViewRefreshDependencies(Archive *fout);
     283                 : static void getTableDataFKConstraints(void);
     284                 : static char *format_function_arguments(const FuncInfo *finfo, const char *funcargs,
     285                 :                                        bool is_agg);
     286                 : static char *format_function_signature(Archive *fout,
     287                 :                                        const FuncInfo *finfo, bool honor_quotes);
     288                 : static char *convertRegProcReference(const char *proc);
     289                 : static char *getFormattedOperatorName(const char *oproid);
     290                 : static char *convertTSFunction(Archive *fout, Oid funcOid);
     291                 : static const char *getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts);
     292                 : static void getLOs(Archive *fout);
     293                 : static void dumpLO(Archive *fout, const LoInfo *binfo);
     294                 : static int  dumpLOs(Archive *fout, const void *arg);
     295                 : static void dumpPolicy(Archive *fout, const PolicyInfo *polinfo);
     296                 : static void dumpPublication(Archive *fout, const PublicationInfo *pubinfo);
     297                 : static void dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo);
     298                 : static void dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo);
     299                 : static void dumpDatabase(Archive *fout);
     300                 : static void dumpDatabaseConfig(Archive *AH, PQExpBuffer outbuf,
     301                 :                                const char *dbname, Oid dboid);
     302                 : static void dumpEncoding(Archive *AH);
     303                 : static void dumpStdStrings(Archive *AH);
     304                 : static void dumpSearchPath(Archive *AH);
     305                 : static void binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
     306                 :                                                      PQExpBuffer upgrade_buffer,
     307                 :                                                      Oid pg_type_oid,
     308                 :                                                      bool force_array_type,
     309                 :                                                      bool include_multirange_type);
     310                 : static void binary_upgrade_set_type_oids_by_rel(Archive *fout,
     311                 :                                                 PQExpBuffer upgrade_buffer,
     312                 :                                                 const TableInfo *tbinfo);
     313                 : static void binary_upgrade_set_pg_class_oids(Archive *fout,
     314                 :                                              PQExpBuffer upgrade_buffer,
     315                 :                                              Oid pg_class_oid, bool is_index);
     316                 : static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
     317                 :                                             const DumpableObject *dobj,
     318                 :                                             const char *objtype,
     319                 :                                             const char *objname,
     320                 :                                             const char *objnamespace);
     321                 : static const char *getAttrName(int attrnum, const TableInfo *tblInfo);
     322                 : static const char *fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer);
     323                 : static bool nonemptyReloptions(const char *reloptions);
     324                 : static void appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
     325                 :                                     const char *prefix, Archive *fout);
     326                 : static char *get_synchronized_snapshot(Archive *fout);
     327                 : static void setupDumpWorker(Archive *AH);
     328                 : static TableInfo *getRootTableInfo(const TableInfo *tbinfo);
     329                 : static bool forcePartitionRootLoad(const TableInfo *tbinfo);
     330                 : 
     331                 : 
     332                 : int
     333 GIC         181 : main(int argc, char **argv)
     334                 : {
     335                 :     int         c;
     336             181 :     const char *filename = NULL;
     337             181 :     const char *format = "p";
     338                 :     TableInfo  *tblinfo;
     339                 :     int         numTables;
     340                 :     DumpableObject **dobjs;
     341                 :     int         numObjs;
     342 ECB             :     DumpableObject *boundaryObjs;
     343                 :     int         i;
     344                 :     int         optindex;
     345                 :     RestoreOptions *ropt;
     346                 :     Archive    *fout;           /* the script file */
     347 GIC         181 :     bool        g_verbose = false;
     348             181 :     const char *dumpencoding = NULL;
     349             181 :     const char *dumpsnapshot = NULL;
     350             181 :     char       *use_role = NULL;
     351             181 :     int         numWorkers = 1;
     352             181 :     int         plainText = 0;
     353             181 :     ArchiveFormat archiveFormat = archUnknown;
     354                 :     ArchiveMode archiveMode;
     355 GNC         181 :     pg_compress_specification compression_spec = {0};
     356             181 :     char       *compression_detail = NULL;
     357             181 :     char       *compression_algorithm_str = "none";
     358             181 :     char       *error_detail = NULL;
     359             181 :     bool        user_compression_defined = false;
     360 ECB             : 
     361                 :     static DumpOptions dopt;
     362                 : 
     363                 :     static struct option long_options[] = {
     364                 :         {"data-only", no_argument, NULL, 'a'},
     365                 :         {"blobs", no_argument, NULL, 'b'},
     366                 :         {"large-objects", no_argument, NULL, 'b'},
     367                 :         {"no-blobs", no_argument, NULL, 'B'},
     368                 :         {"no-large-objects", no_argument, NULL, 'B'},
     369                 :         {"clean", no_argument, NULL, 'c'},
     370                 :         {"create", no_argument, NULL, 'C'},
     371                 :         {"dbname", required_argument, NULL, 'd'},
     372                 :         {"extension", required_argument, NULL, 'e'},
     373                 :         {"file", required_argument, NULL, 'f'},
     374                 :         {"format", required_argument, NULL, 'F'},
     375                 :         {"host", required_argument, NULL, 'h'},
     376                 :         {"jobs", 1, NULL, 'j'},
     377                 :         {"no-reconnect", no_argument, NULL, 'R'},
     378                 :         {"no-owner", no_argument, NULL, 'O'},
     379                 :         {"port", required_argument, NULL, 'p'},
     380                 :         {"schema", required_argument, NULL, 'n'},
     381                 :         {"exclude-schema", required_argument, NULL, 'N'},
     382                 :         {"schema-only", no_argument, NULL, 's'},
     383                 :         {"superuser", required_argument, NULL, 'S'},
     384                 :         {"table", required_argument, NULL, 't'},
     385                 :         {"exclude-table", required_argument, NULL, 'T'},
     386                 :         {"no-password", no_argument, NULL, 'w'},
     387                 :         {"password", no_argument, NULL, 'W'},
     388                 :         {"username", required_argument, NULL, 'U'},
     389                 :         {"verbose", no_argument, NULL, 'v'},
     390                 :         {"no-privileges", no_argument, NULL, 'x'},
     391                 :         {"no-acl", no_argument, NULL, 'x'},
     392                 :         {"compress", required_argument, NULL, 'Z'},
     393                 :         {"encoding", required_argument, NULL, 'E'},
     394                 :         {"help", no_argument, NULL, '?'},
     395                 :         {"version", no_argument, NULL, 'V'},
     396                 : 
     397                 :         /*
     398                 :          * the following options don't have an equivalent short option letter
     399                 :          */
     400                 :         {"attribute-inserts", no_argument, &dopt.column_inserts, 1},
     401                 :         {"binary-upgrade", no_argument, &dopt.binary_upgrade, 1},
     402                 :         {"column-inserts", no_argument, &dopt.column_inserts, 1},
     403                 :         {"disable-dollar-quoting", no_argument, &dopt.disable_dollar_quoting, 1},
     404                 :         {"disable-triggers", no_argument, &dopt.disable_triggers, 1},
     405                 :         {"enable-row-security", no_argument, &dopt.enable_row_security, 1},
     406                 :         {"exclude-table-data", required_argument, NULL, 4},
     407                 :         {"extra-float-digits", required_argument, NULL, 8},
     408                 :         {"if-exists", no_argument, &dopt.if_exists, 1},
     409                 :         {"inserts", no_argument, NULL, 9},
     410                 :         {"lock-wait-timeout", required_argument, NULL, 2},
     411                 :         {"no-table-access-method", no_argument, &dopt.outputNoTableAm, 1},
     412                 :         {"no-tablespaces", no_argument, &dopt.outputNoTablespaces, 1},
     413                 :         {"quote-all-identifiers", no_argument, &quote_all_identifiers, 1},
     414                 :         {"load-via-partition-root", no_argument, &dopt.load_via_partition_root, 1},
     415                 :         {"role", required_argument, NULL, 3},
     416                 :         {"section", required_argument, NULL, 5},
     417                 :         {"serializable-deferrable", no_argument, &dopt.serializable_deferrable, 1},
     418                 :         {"snapshot", required_argument, NULL, 6},
     419                 :         {"strict-names", no_argument, &strict_names, 1},
     420                 :         {"use-set-session-authorization", no_argument, &dopt.use_setsessauth, 1},
     421                 :         {"no-comments", no_argument, &dopt.no_comments, 1},
     422                 :         {"no-publications", no_argument, &dopt.no_publications, 1},
     423                 :         {"no-security-labels", no_argument, &dopt.no_security_labels, 1},
     424                 :         {"no-subscriptions", no_argument, &dopt.no_subscriptions, 1},
     425                 :         {"no-toast-compression", no_argument, &dopt.no_toast_compression, 1},
     426                 :         {"no-unlogged-table-data", no_argument, &dopt.no_unlogged_table_data, 1},
     427                 :         {"no-sync", no_argument, NULL, 7},
     428                 :         {"on-conflict-do-nothing", no_argument, &dopt.do_nothing, 1},
     429                 :         {"rows-per-insert", required_argument, NULL, 10},
     430                 :         {"include-foreign-data", required_argument, NULL, 11},
     431                 :         {"table-and-children", required_argument, NULL, 12},
     432                 :         {"exclude-table-and-children", required_argument, NULL, 13},
     433                 :         {"exclude-table-data-and-children", required_argument, NULL, 14},
     434                 : 
     435                 :         {NULL, 0, NULL, 0}
     436                 :     };
     437                 : 
     438 GIC         181 :     pg_logging_init(argv[0]);
     439             181 :     pg_logging_set_level(PG_LOG_WARNING);
     440             181 :     set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
     441                 : 
     442                 :     /*
     443                 :      * Initialize what we need for parallel execution, especially for thread
     444                 :      * support on Windows.
     445                 :      */
     446             181 :     init_parallel_dump_utils();
     447                 : 
     448             181 :     progname = get_progname(argv[0]);
     449                 : 
     450             181 :     if (argc > 1)
     451                 :     {
     452             181 :         if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
     453                 :         {
     454               1 :             help(progname);
     455               1 :             exit_nicely(0);
     456 ECB             :         }
     457 CBC         180 :         if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
     458 ECB             :         {
     459 GIC          30 :             puts("pg_dump (PostgreSQL) " PG_VERSION);
     460              30 :             exit_nicely(0);
     461                 :         }
     462                 :     }
     463                 : 
     464 CBC         150 :     InitDumpOptions(&dopt);
     465                 : 
     466             627 :     while ((c = getopt_long(argc, argv, "abBcCd:e:E:f:F:h:j:n:N:Op:RsS:t:T:U:vwWxZ:",
     467 GIC         627 :                             long_options, &optindex)) != -1)
     468 ECB             :     {
     469 GIC         481 :         switch (c)
     470 ECB             :         {
     471 GIC           8 :             case 'a':           /* Dump data only */
     472 CBC           8 :                 dopt.dataOnly = true;
     473               8 :                 break;
     474                 : 
     475 GNC           1 :             case 'b':           /* Dump LOs */
     476               1 :                 dopt.outputLOs = true;
     477 CBC           1 :                 break;
     478 ECB             : 
     479 GNC           2 :             case 'B':           /* Don't dump LOs */
     480               2 :                 dopt.dontOutputLOs = true;
     481 GIC           2 :                 break;
     482 ECB             : 
     483 GIC           6 :             case 'c':           /* clean (i.e., drop) schema prior to create */
     484 CBC           6 :                 dopt.outputClean = 1;
     485               6 :                 break;
     486                 : 
     487              25 :             case 'C':           /* Create DB */
     488 GIC          25 :                 dopt.outputCreateDB = 1;
     489 CBC          25 :                 break;
     490 ECB             : 
     491 CBC           4 :             case 'd':           /* database name */
     492 GIC           4 :                 dopt.cparams.dbname = pg_strdup(optarg);
     493 CBC           4 :                 break;
     494 ECB             : 
     495 CBC           4 :             case 'e':           /* include extension(s) */
     496 GIC           4 :                 simple_string_list_append(&extension_include_patterns, optarg);
     497 CBC           4 :                 dopt.include_everything = false;
     498               4 :                 break;
     499 ECB             : 
     500 GIC           2 :             case 'E':           /* Dump encoding */
     501 CBC           2 :                 dumpencoding = pg_strdup(optarg);
     502               2 :                 break;
     503 ECB             : 
     504 GIC         110 :             case 'f':
     505 CBC         110 :                 filename = pg_strdup(optarg);
     506             110 :                 break;
     507 ECB             : 
     508 GIC          71 :             case 'F':
     509 CBC          71 :                 format = pg_strdup(optarg);
     510              71 :                 break;
     511 ECB             : 
     512 GIC           6 :             case 'h':           /* server host */
     513 CBC           6 :                 dopt.cparams.pghost = pg_strdup(optarg);
     514               6 :                 break;
     515 ECB             : 
     516 CBC          12 :             case 'j':           /* number of dump jobs */
     517 GIC          12 :                 if (!option_parse_int(optarg, "-j/--jobs", 1,
     518 ECB             :                                       PG_MAX_JOBS,
     519                 :                                       &numWorkers))
     520 CBC           1 :                     exit_nicely(1);
     521 GIC          11 :                 break;
     522 ECB             : 
     523 CBC          14 :             case 'n':           /* include schema(s) */
     524              14 :                 simple_string_list_append(&schema_include_patterns, optarg);
     525 GIC          14 :                 dopt.include_everything = false;
     526 CBC          14 :                 break;
     527 ECB             : 
     528 CBC           1 :             case 'N':           /* exclude schema(s) */
     529 GIC           1 :                 simple_string_list_append(&schema_exclude_patterns, optarg);
     530 CBC           1 :                 break;
     531 ECB             : 
     532 CBC           2 :             case 'O':           /* Don't reconnect to match owner */
     533 GIC           2 :                 dopt.outputNoOwner = 1;
     534 CBC           2 :                 break;
     535 ECB             : 
     536 GIC          15 :             case 'p':           /* server port */
     537              15 :                 dopt.cparams.pgport = pg_strdup(optarg);
     538 CBC          15 :                 break;
     539 ECB             : 
     540 GIC           2 :             case 'R':
     541 ECB             :                 /* no-op, still accepted for backwards compatibility */
     542 CBC           2 :                 break;
     543 ECB             : 
     544 CBC          12 :             case 's':           /* dump schema only */
     545 GIC          12 :                 dopt.schemaOnly = true;
     546 CBC          12 :                 break;
     547 ECB             : 
     548 CBC           1 :             case 'S':           /* Username for superuser in plain text output */
     549 GIC           1 :                 dopt.outputSuperuser = pg_strdup(optarg);
     550 CBC           1 :                 break;
     551 ECB             : 
     552 CBC           8 :             case 't':           /* include table(s) */
     553 GIC           8 :                 simple_string_list_append(&table_include_patterns, optarg);
     554 CBC           8 :                 dopt.include_everything = false;
     555               8 :                 break;
     556 ECB             : 
     557 GIC           2 :             case 'T':           /* exclude table(s) */
     558 CBC           2 :                 simple_string_list_append(&table_exclude_patterns, optarg);
     559 GIC           2 :                 break;
     560 ECB             : 
     561 GIC           7 :             case 'U':
     562 CBC           7 :                 dopt.cparams.username = pg_strdup(optarg);
     563               7 :                 break;
     564 ECB             : 
     565 GIC           6 :             case 'v':           /* verbose */
     566 CBC           6 :                 g_verbose = true;
     567               6 :                 pg_logging_increase_verbosity();
     568               6 :                 break;
     569                 : 
     570               1 :             case 'w':
     571               1 :                 dopt.cparams.promptPassword = TRI_NO;
     572               1 :                 break;
     573 ECB             : 
     574 UIC           0 :             case 'W':
     575 LBC           0 :                 dopt.cparams.promptPassword = TRI_YES;
     576               0 :                 break;
     577 ECB             : 
     578 GIC           2 :             case 'x':           /* skip ACL dump */
     579 CBC           2 :                 dopt.aclsSkip = true;
     580               2 :                 break;
     581 ECB             : 
     582 GNC          15 :             case 'Z':           /* Compression */
     583              15 :                 parse_compress_options(optarg, &compression_algorithm_str,
     584                 :                                        &compression_detail);
     585              15 :                 user_compression_defined = true;
     586 CBC          15 :                 break;
     587                 : 
     588              29 :             case 0:
     589 ECB             :                 /* This covers the long options. */
     590 CBC          29 :                 break;
     591                 : 
     592 GBC           2 :             case 2:             /* lock-wait-timeout */
     593               2 :                 dopt.lockWaitTimeout = pg_strdup(optarg);
     594               2 :                 break;
     595                 : 
     596 CBC           3 :             case 3:             /* SET ROLE */
     597               3 :                 use_role = pg_strdup(optarg);
     598               3 :                 break;
     599                 : 
     600               1 :             case 4:             /* exclude table(s) data */
     601               1 :                 simple_string_list_append(&tabledata_exclude_patterns, optarg);
     602 GIC           1 :                 break;
     603 ECB             : 
     604 CBC           6 :             case 5:             /* section */
     605 GIC           6 :                 set_dump_section(optarg, &dopt.dumpSections);
     606 CBC           6 :                 break;
     607                 : 
     608 LBC           0 :             case 6:             /* snapshot */
     609 UIC           0 :                 dumpsnapshot = pg_strdup(optarg);
     610 LBC           0 :                 break;
     611 ECB             : 
     612 CBC          88 :             case 7:             /* no-sync */
     613 GIC          88 :                 dosync = false;
     614 CBC          88 :                 break;
     615 ECB             : 
     616 CBC           1 :             case 8:
     617 GIC           1 :                 have_extra_float_digits = true;
     618 CBC           1 :                 if (!option_parse_int(optarg, "--extra-float-digits", -15, 3,
     619 ECB             :                                       &extra_float_digits))
     620 CBC           1 :                     exit_nicely(1);
     621 UIC           0 :                 break;
     622 ECB             : 
     623 CBC           2 :             case 9:             /* inserts */
     624 ECB             : 
     625                 :                 /*
     626 EUB             :                  * dump_inserts also stores --rows-per-insert, careful not to
     627                 :                  * overwrite that.
     628                 :                  */
     629 GIC           2 :                 if (dopt.dump_inserts == 0)
     630 CBC           2 :                     dopt.dump_inserts = DUMP_DEFAULT_ROWS_PER_INSERT;
     631               2 :                 break;
     632 ECB             : 
     633 GIC           2 :             case 10:            /* rows per insert */
     634 CBC           2 :                 if (!option_parse_int(optarg, "--rows-per-insert", 1, INT_MAX,
     635 ECB             :                                       &dopt.dump_inserts))
     636 CBC           1 :                     exit_nicely(1);
     637 GIC           1 :                 break;
     638 ECB             : 
     639 GBC           4 :             case 11:            /* include foreign data */
     640 GIC           4 :                 simple_string_list_append(&foreign_servers_include_patterns,
     641 ECB             :                                           optarg);
     642 GIC           4 :                 break;
     643                 : 
     644 GNC           1 :             case 12:            /* include table(s) and their children */
     645               1 :                 simple_string_list_append(&table_include_patterns_and_children,
     646                 :                                           optarg);
     647               1 :                 dopt.include_everything = false;
     648               1 :                 break;
     649                 : 
     650               1 :             case 13:            /* exclude table(s) and their children */
     651               1 :                 simple_string_list_append(&table_exclude_patterns_and_children,
     652                 :                                           optarg);
     653               1 :                 break;
     654                 : 
     655               1 :             case 14:            /* exclude data of table(s) and children */
     656               1 :                 simple_string_list_append(&tabledata_exclude_patterns_and_children,
     657                 :                                           optarg);
     658               1 :                 break;
     659                 : 
     660 GIC           1 :             default:
     661                 :                 /* getopt_long already emitted a complaint */
     662               1 :                 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
     663 CBC           1 :                 exit_nicely(1);
     664 ECB             :         }
     665                 :     }
     666                 : 
     667                 :     /*
     668                 :      * Non-option argument specifies database name as long as it wasn't
     669                 :      * already specified with -d / --dbname
     670                 :      */
     671 CBC         146 :     if (optind < argc && dopt.cparams.dbname == NULL)
     672 GIC         116 :         dopt.cparams.dbname = argv[optind++];
     673 ECB             : 
     674                 :     /* Complain if any arguments remain */
     675 GIC         146 :     if (optind < argc)
     676 ECB             :     {
     677 GIC           1 :         pg_log_error("too many command-line arguments (first is \"%s\")",
     678 ECB             :                      argv[optind]);
     679 CBC           1 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
     680 GIC           1 :         exit_nicely(1);
     681 ECB             :     }
     682                 : 
     683                 :     /* --column-inserts implies --inserts */
     684 CBC         145 :     if (dopt.column_inserts && dopt.dump_inserts == 0)
     685               1 :         dopt.dump_inserts = DUMP_DEFAULT_ROWS_PER_INSERT;
     686                 : 
     687 ECB             :     /*
     688                 :      * Binary upgrade mode implies dumping sequence data even in schema-only
     689                 :      * mode.  This is not exposed as a separate option, but kept separate
     690                 :      * internally for clarity.
     691                 :      */
     692 CBC         145 :     if (dopt.binary_upgrade)
     693 GIC           8 :         dopt.sequence_data = 1;
     694 ECB             : 
     695 GIC         145 :     if (dopt.dataOnly && dopt.schemaOnly)
     696 CBC           1 :         pg_fatal("options -s/--schema-only and -a/--data-only cannot be used together");
     697 ECB             : 
     698 GIC         144 :     if (dopt.schemaOnly && foreign_servers_include_patterns.head != NULL)
     699               1 :         pg_fatal("options -s/--schema-only and --include-foreign-data cannot be used together");
     700                 : 
     701             143 :     if (numWorkers > 1 && foreign_servers_include_patterns.head != NULL)
     702               1 :         pg_fatal("option --include-foreign-data is not supported with parallel backup");
     703                 : 
     704             142 :     if (dopt.dataOnly && dopt.outputClean)
     705 CBC           1 :         pg_fatal("options -c/--clean and -a/--data-only cannot be used together");
     706 ECB             : 
     707 GIC         141 :     if (dopt.if_exists && !dopt.outputClean)
     708               1 :         pg_fatal("option --if-exists requires option -c/--clean");
     709 ECB             : 
     710                 :     /*
     711                 :      * --inserts are already implied above if --column-inserts or
     712                 :      * --rows-per-insert were specified.
     713                 :      */
     714 CBC         140 :     if (dopt.do_nothing && dopt.dump_inserts == 0)
     715 GIC           1 :         pg_fatal("option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts");
     716                 : 
     717                 :     /* Identify archive format to emit */
     718 CBC         139 :     archiveFormat = parseArchiveFormat(format, &archiveMode);
     719 ECB             : 
     720                 :     /* archiveFormat specific setup */
     721 GIC         138 :     if (archiveFormat == archNull)
     722             112 :         plainText = 1;
     723                 : 
     724                 :     /*
     725                 :      * Compression options
     726                 :      */
     727 GNC         138 :     if (!parse_compress_algorithm(compression_algorithm_str,
     728                 :                                   &compression_algorithm))
     729               1 :         pg_fatal("unrecognized compression algorithm: \"%s\"",
     730                 :                  compression_algorithm_str);
     731                 : 
     732             137 :     parse_compress_specification(compression_algorithm, compression_detail,
     733                 :                                  &compression_spec);
     734             137 :     error_detail = validate_compress_specification(&compression_spec);
     735             137 :     if (error_detail != NULL)
     736               3 :         pg_fatal("invalid compression specification: %s",
     737                 :                  error_detail);
     738                 : 
     739             134 :     error_detail = supports_compression(compression_spec);
     740             134 :     if (error_detail != NULL)
     741 UNC           0 :         pg_fatal("%s", error_detail);
     742                 : 
     743                 :     /*
     744                 :      * Disable support for zstd workers for now - these are based on threading,
     745                 :      * and it's unclear how it interacts with parallel dumps on platforms where
     746                 :      * that relies on threads too (e.g. Windows).
     747                 :      */
     748 GNC         134 :     if (compression_spec.options & PG_COMPRESSION_OPTION_WORKERS)
     749 UNC           0 :         pg_log_warning("compression option \"%s\" is not currently supported by pg_dump",
     750                 :                        "workers");
     751                 : 
     752                 :     /*
     753                 :      * Custom and directory formats are compressed by default with gzip when
     754                 :      * available, not the others.
     755                 :      */
     756 GNC         134 :     if ((archiveFormat == archCustom || archiveFormat == archDirectory) &&
     757              23 :         !user_compression_defined)
     758 ECB             :     {
     759                 : #ifdef HAVE_LIBZ
     760 GNC          16 :         parse_compress_specification(PG_COMPRESSION_GZIP, NULL,
     761                 :                                      &compression_spec);
     762                 : #else
     763                 :         /* Nothing to do in the default case */
     764                 : #endif
     765 ECB             :     }
     766                 : 
     767                 :     /*
     768                 :      * If emitting an archive format, we always want to emit a DATABASE item,
     769                 :      * in case --create is specified at pg_restore time.
     770                 :      */
     771 GIC         134 :     if (!plainText)
     772              26 :         dopt.outputCreateDB = 1;
     773                 : 
     774 ECB             :     /* Parallel backup only in the directory archive format so far */
     775 CBC         134 :     if (archiveFormat != archDirectory && numWorkers > 1)
     776 GIC           1 :         pg_fatal("parallel backup only supported by the directory format");
     777                 : 
     778 ECB             :     /* Open the output file */
     779 GNC         133 :     fout = CreateArchive(filename, archiveFormat, compression_spec,
     780                 :                          dosync, archiveMode, setupDumpWorker);
     781 ECB             : 
     782                 :     /* Make dump options accessible right away */
     783 GIC         132 :     SetArchiveOptions(fout, &dopt, NULL);
     784                 : 
     785                 :     /* Register the cleanup hook */
     786             132 :     on_exit_close_archive(fout);
     787 ECB             : 
     788                 :     /* Let the archiver know how noisy to be */
     789 CBC         132 :     fout->verbose = g_verbose;
     790                 : 
     791                 : 
     792 ECB             :     /*
     793                 :      * We allow the server to be back to 9.2, and up to any minor release of
     794                 :      * our own major version.  (See also version check in pg_dumpall.c.)
     795                 :      */
     796 CBC         132 :     fout->minRemoteVersion = 90200;
     797 GIC         132 :     fout->maxRemoteVersion = (PG_VERSION_NUM / 100) * 100 + 99;
     798                 : 
     799 CBC         132 :     fout->numWorkers = numWorkers;
     800 ECB             : 
     801 EUB             :     /*
     802                 :      * Open the database using the Archiver, so it knows about it. Errors mean
     803                 :      * death.
     804                 :      */
     805 GIC         132 :     ConnectDatabase(fout, &dopt.cparams, false);
     806             131 :     setup_connection(fout, dumpencoding, dumpsnapshot, use_role);
     807                 : 
     808 ECB             :     /*
     809 EUB             :      * On hot standbys, never try to dump unlogged table data, since it will
     810                 :      * just throw an error.
     811                 :      */
     812 GIC         131 :     if (fout->isStandby)
     813               3 :         dopt.no_unlogged_table_data = true;
     814                 : 
     815                 :     /*
     816 ECB             :      * Find the last built-in OID, if needed (prior to 8.1)
     817                 :      *
     818                 :      * With 8.1 and above, we can just use FirstNormalObjectId - 1.
     819                 :      */
     820 CBC         131 :     g_last_builtin_oid = FirstNormalObjectId - 1;
     821                 : 
     822 GIC         131 :     pg_log_info("last built-in OID is %u", g_last_builtin_oid);
     823                 : 
     824                 :     /* Expand schema selection patterns into OID lists */
     825             131 :     if (schema_include_patterns.head != NULL)
     826                 :     {
     827              14 :         expand_schema_name_patterns(fout, &schema_include_patterns,
     828                 :                                     &schema_include_oids,
     829                 :                                     strict_names);
     830               8 :         if (schema_include_oids.head == NULL)
     831 CBC           1 :             pg_fatal("no matching schemas were found");
     832 ECB             :     }
     833 GIC         124 :     expand_schema_name_patterns(fout, &schema_exclude_patterns,
     834                 :                                 &schema_exclude_oids,
     835 ECB             :                                 false);
     836                 :     /* non-matching exclusion patterns aren't an error */
     837                 : 
     838                 :     /* Expand table selection patterns into OID lists */
     839 GNC         124 :     expand_table_name_patterns(fout, &table_include_patterns,
     840                 :                                &table_include_oids,
     841                 :                                strict_names, false);
     842             120 :     expand_table_name_patterns(fout, &table_include_patterns_and_children,
     843                 :                                &table_include_oids,
     844                 :                                strict_names, true);
     845             120 :     if ((table_include_patterns.head != NULL ||
     846             117 :          table_include_patterns_and_children.head != NULL) &&
     847               4 :         table_include_oids.head == NULL)
     848               1 :         pg_fatal("no matching tables were found");
     849                 : 
     850 GIC         119 :     expand_table_name_patterns(fout, &table_exclude_patterns,
     851                 :                                &table_exclude_oids,
     852                 :                                false, false);
     853 GNC         119 :     expand_table_name_patterns(fout, &table_exclude_patterns_and_children,
     854                 :                                &table_exclude_oids,
     855                 :                                false, true);
     856                 : 
     857 GIC         119 :     expand_table_name_patterns(fout, &tabledata_exclude_patterns,
     858                 :                                &tabledata_exclude_oids,
     859                 :                                false, false);
     860 GNC         119 :     expand_table_name_patterns(fout, &tabledata_exclude_patterns_and_children,
     861                 :                                &tabledata_exclude_oids,
     862                 :                                false, true);
     863                 : 
     864 GIC         119 :     expand_foreign_server_name_patterns(fout, &foreign_servers_include_patterns,
     865 ECB             :                                         &foreign_servers_include_oids);
     866                 : 
     867                 :     /* non-matching exclusion patterns aren't an error */
     868                 : 
     869                 :     /* Expand extension selection patterns into OID lists */
     870 GIC         119 :     if (extension_include_patterns.head != NULL)
     871                 :     {
     872               4 :         expand_extension_name_patterns(fout, &extension_include_patterns,
     873                 :                                        &extension_include_oids,
     874 ECB             :                                        strict_names);
     875 CBC           4 :         if (extension_include_oids.head == NULL)
     876 UIC           0 :             pg_fatal("no matching extensions were found");
     877                 :     }
     878                 : 
     879                 :     /*
     880                 :      * Dumping LOs is the default for dumps where an inclusion switch is not
     881                 :      * used (an "include everything" dump).  -B can be used to exclude LOs
     882                 :      * from those dumps.  -b can be used to include LOs even when an
     883                 :      * inclusion switch is used.
     884                 :      *
     885                 :      * -s means "schema only" and LOs are data, not schema, so we never
     886                 :      * include LOs when -s is used.
     887                 :      */
     888 GNC         119 :     if (dopt.include_everything && !dopt.schemaOnly && !dopt.dontOutputLOs)
     889              96 :         dopt.outputLOs = true;
     890                 : 
     891 ECB             :     /*
     892                 :      * Collect role names so we can map object owner OIDs to names.
     893                 :      */
     894 CBC         119 :     collectRoleNames(fout);
     895                 : 
     896 ECB             :     /*
     897                 :      * Now scan the database and create DumpableObject structs for all the
     898                 :      * objects we intend to dump.
     899                 :      */
     900 CBC         119 :     tblinfo = getSchemaData(fout, &numTables);
     901                 : 
     902             118 :     if (!dopt.schemaOnly)
     903                 :     {
     904 GIC         108 :         getTableData(&dopt, tblinfo, numTables, 0);
     905             108 :         buildMatViewRefreshDependencies(fout);
     906             108 :         if (dopt.dataOnly)
     907               6 :             getTableDataFKConstraints();
     908 ECB             :     }
     909                 : 
     910 GIC         118 :     if (dopt.schemaOnly && dopt.sequence_data)
     911 CBC           8 :         getTableData(&dopt, tblinfo, numTables, RELKIND_SEQUENCE);
     912                 : 
     913                 :     /*
     914                 :      * In binary-upgrade mode, we do not have to worry about the actual LO
     915 ECB             :      * data or the associated metadata that resides in the pg_largeobject and
     916                 :      * pg_largeobject_metadata tables, respectively.
     917                 :      *
     918                 :      * However, we do need to collect LO information as there may be
     919                 :      * comments or other information on LOs that we do need to dump out.
     920                 :      */
     921 GNC         118 :     if (dopt.outputLOs || dopt.binary_upgrade)
     922             104 :         getLOs(fout);
     923                 : 
     924                 :     /*
     925                 :      * Collect dependency data to assist in ordering the objects.
     926 ECB             :      */
     927 GIC         118 :     getDependencies(fout);
     928                 : 
     929 ECB             :     /*
     930                 :      * Collect ACLs, comments, and security labels, if wanted.
     931                 :      */
     932 GIC         118 :     if (!dopt.aclsSkip)
     933 CBC         116 :         getAdditionalACLs(fout);
     934 GIC         118 :     if (!dopt.no_comments)
     935             118 :         collectComments(fout);
     936             118 :     if (!dopt.no_security_labels)
     937             118 :         collectSecLabels(fout);
     938                 : 
     939 ECB             :     /* Lastly, create dummy objects to represent the section boundaries */
     940 GIC         118 :     boundaryObjs = createBoundaryObjects();
     941 ECB             : 
     942                 :     /* Get pointers to all the known DumpableObjects */
     943 GIC         118 :     getDumpableObjects(&dobjs, &numObjs);
     944 ECB             : 
     945 EUB             :     /*
     946                 :      * Add dummy dependencies to enforce the dump section ordering.
     947                 :      */
     948 GIC         118 :     addBoundaryDependencies(dobjs, numObjs, boundaryObjs);
     949                 : 
     950                 :     /*
     951                 :      * Sort the objects into a safe dump order (no forward references).
     952                 :      *
     953                 :      * We rely on dependency information to help us determine a safe order, so
     954                 :      * the initial sort is mostly for cosmetic purposes: we sort by name to
     955                 :      * ensure that logically identical schemas will dump identically.
     956                 :      */
     957 CBC         118 :     sortDumpableObjectsByTypeName(dobjs, numObjs);
     958 ECB             : 
     959 GIC         118 :     sortDumpableObjects(dobjs, numObjs,
     960             118 :                         boundaryObjs[0].dumpId, boundaryObjs[1].dumpId);
     961                 : 
     962                 :     /*
     963 ECB             :      * Create archive TOC entries for all the objects to be dumped, in a safe
     964                 :      * order.
     965                 :      */
     966                 : 
     967                 :     /*
     968                 :      * First the special entries for ENCODING, STDSTRINGS, and SEARCHPATH.
     969                 :      */
     970 GIC         118 :     dumpEncoding(fout);
     971 CBC         118 :     dumpStdStrings(fout);
     972 GIC         118 :     dumpSearchPath(fout);
     973 ECB             : 
     974                 :     /* The database items are always next, unless we don't want them at all */
     975 CBC         118 :     if (dopt.outputCreateDB)
     976              50 :         dumpDatabase(fout);
     977                 : 
     978                 :     /* Now the rearrangeable objects. */
     979          510138 :     for (i = 0; i < numObjs; i++)
     980          510020 :         dumpDumpableObject(fout, dobjs[i]);
     981                 : 
     982                 :     /*
     983                 :      * Set up options info to ensure we dump what we want.
     984                 :      */
     985 GIC         118 :     ropt = NewRestoreOptions();
     986             118 :     ropt->filename = filename;
     987                 : 
     988                 :     /* if you change this list, see dumpOptionsFromRestoreOptions */
     989             118 :     ropt->cparams.dbname = dopt.cparams.dbname ? pg_strdup(dopt.cparams.dbname) : NULL;
     990 CBC         118 :     ropt->cparams.pgport = dopt.cparams.pgport ? pg_strdup(dopt.cparams.pgport) : NULL;
     991             118 :     ropt->cparams.pghost = dopt.cparams.pghost ? pg_strdup(dopt.cparams.pghost) : NULL;
     992 GIC         118 :     ropt->cparams.username = dopt.cparams.username ? pg_strdup(dopt.cparams.username) : NULL;
     993             118 :     ropt->cparams.promptPassword = dopt.cparams.promptPassword;
     994             118 :     ropt->dropSchema = dopt.outputClean;
     995             118 :     ropt->dataOnly = dopt.dataOnly;
     996 CBC         118 :     ropt->schemaOnly = dopt.schemaOnly;
     997 GIC         118 :     ropt->if_exists = dopt.if_exists;
     998             118 :     ropt->column_inserts = dopt.column_inserts;
     999             118 :     ropt->dumpSections = dopt.dumpSections;
    1000             118 :     ropt->aclsSkip = dopt.aclsSkip;
    1001 CBC         118 :     ropt->superuser = dopt.outputSuperuser;
    1002             118 :     ropt->createDB = dopt.outputCreateDB;
    1003             118 :     ropt->noOwner = dopt.outputNoOwner;
    1004             118 :     ropt->noTableAm = dopt.outputNoTableAm;
    1005             118 :     ropt->noTablespace = dopt.outputNoTablespaces;
    1006             118 :     ropt->disable_triggers = dopt.disable_triggers;
    1007 GIC         118 :     ropt->use_setsessauth = dopt.use_setsessauth;
    1008             118 :     ropt->disable_dollar_quoting = dopt.disable_dollar_quoting;
    1009 CBC         118 :     ropt->dump_inserts = dopt.dump_inserts;
    1010 GIC         118 :     ropt->no_comments = dopt.no_comments;
    1011             118 :     ropt->no_publications = dopt.no_publications;
    1012 CBC         118 :     ropt->no_security_labels = dopt.no_security_labels;
    1013 GIC         118 :     ropt->no_subscriptions = dopt.no_subscriptions;
    1014             118 :     ropt->lockWaitTimeout = dopt.lockWaitTimeout;
    1015             118 :     ropt->include_everything = dopt.include_everything;
    1016             118 :     ropt->enable_row_security = dopt.enable_row_security;
    1017 CBC         118 :     ropt->sequence_data = dopt.sequence_data;
    1018 GIC         118 :     ropt->binary_upgrade = dopt.binary_upgrade;
    1019                 : 
    1020 GNC         118 :     ropt->compression_spec = compression_spec;
    1021                 : 
    1022 GIC         118 :     ropt->suppressDumpWarnings = true;   /* We've already shown them */
    1023 ECB             : 
    1024 GIC         118 :     SetArchiveOptions(fout, &dopt, ropt);
    1025 ECB             : 
    1026                 :     /* Mark which entries should be output */
    1027 GIC         118 :     ProcessArchiveRestoreOptions(fout);
    1028                 : 
    1029                 :     /*
    1030                 :      * The archive's TOC entries are now marked as to which ones will actually
    1031                 :      * be output, so we can set up their dependency lists properly. This isn't
    1032                 :      * necessary for plain-text output, though.
    1033                 :      */
    1034             118 :     if (!plainText)
    1035              25 :         BuildArchiveDependencies(fout);
    1036 ECB             : 
    1037                 :     /*
    1038                 :      * And finally we can do the actual output.
    1039                 :      *
    1040                 :      * Note: for non-plain-text output formats, the output file is written
    1041                 :      * inside CloseArchive().  This is, um, bizarre; but not worth changing
    1042                 :      * right now.
    1043                 :      */
    1044 GIC         118 :     if (plainText)
    1045 CBC          93 :         RestoreArchive(fout);
    1046 ECB             : 
    1047 GIC         117 :     CloseArchive(fout);
    1048                 : 
    1049             117 :     exit_nicely(0);
    1050                 : }
    1051 ECB             : 
    1052                 : 
    1053                 : static void
    1054 GIC           1 : help(const char *progname)
    1055 ECB             : {
    1056 CBC           1 :     printf(_("%s dumps a database as a text file or to other formats.\n\n"), progname);
    1057               1 :     printf(_("Usage:\n"));
    1058               1 :     printf(_("  %s [OPTION]... [DBNAME]\n"), progname);
    1059 ECB             : 
    1060 CBC           1 :     printf(_("\nGeneral options:\n"));
    1061               1 :     printf(_("  -f, --file=FILENAME          output file or directory name\n"));
    1062               1 :     printf(_("  -F, --format=c|d|t|p         output file format (custom, directory, tar,\n"
    1063 ECB             :              "                               plain text (default))\n"));
    1064 CBC           1 :     printf(_("  -j, --jobs=NUM               use this many parallel jobs to dump\n"));
    1065               1 :     printf(_("  -v, --verbose                verbose mode\n"));
    1066               1 :     printf(_("  -V, --version                output version information, then exit\n"));
    1067 GNC           1 :     printf(_("  -Z, --compress=METHOD[:LEVEL]\n"
    1068                 :              "                               compress as specified\n"));
    1069 CBC           1 :     printf(_("  --lock-wait-timeout=TIMEOUT  fail after waiting TIMEOUT for a table lock\n"));
    1070               1 :     printf(_("  --no-sync                    do not wait for changes to be written safely to disk\n"));
    1071               1 :     printf(_("  -?, --help                   show this help, then exit\n"));
    1072 ECB             : 
    1073 CBC           1 :     printf(_("\nOptions controlling the output content:\n"));
    1074               1 :     printf(_("  -a, --data-only              dump only the data, not the schema\n"));
    1075 GNC           1 :     printf(_("  -b, --large-objects          include large objects in dump\n"
    1076                 :              "  --blobs                      (same as --large-objects, deprecated)\n"));
    1077               1 :     printf(_("  -B, --no-large-objects       exclude large objects in dump\n"
    1078                 :              "  --no-blobs                   (same as --no-large-objects, deprecated)\n"));
    1079 CBC           1 :     printf(_("  -c, --clean                  clean (drop) database objects before recreating\n"));
    1080               1 :     printf(_("  -C, --create                 include commands to create database in dump\n"));
    1081               1 :     printf(_("  -e, --extension=PATTERN      dump the specified extension(s) only\n"));
    1082               1 :     printf(_("  -E, --encoding=ENCODING      dump the data in encoding ENCODING\n"));
    1083               1 :     printf(_("  -n, --schema=PATTERN         dump the specified schema(s) only\n"));
    1084               1 :     printf(_("  -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n"));
    1085               1 :     printf(_("  -O, --no-owner               skip restoration of object ownership in\n"
    1086 ECB             :              "                               plain-text format\n"));
    1087 CBC           1 :     printf(_("  -s, --schema-only            dump only the schema, no data\n"));
    1088 GIC           1 :     printf(_("  -S, --superuser=NAME         superuser user name to use in plain-text format\n"));
    1089 GNC           1 :     printf(_("  -t, --table=PATTERN          dump only the specified table(s)\n"));
    1090 GIC           1 :     printf(_("  -T, --exclude-table=PATTERN  do NOT dump the specified table(s)\n"));
    1091 CBC           1 :     printf(_("  -x, --no-privileges          do not dump privileges (grant/revoke)\n"));
    1092 GIC           1 :     printf(_("  --binary-upgrade             for use by upgrade utilities only\n"));
    1093 CBC           1 :     printf(_("  --column-inserts             dump data as INSERT commands with column names\n"));
    1094 GIC           1 :     printf(_("  --disable-dollar-quoting     disable dollar quoting, use SQL standard quoting\n"));
    1095               1 :     printf(_("  --disable-triggers           disable triggers during data-only restore\n"));
    1096 CBC           1 :     printf(_("  --enable-row-security        enable row security (dump only content user has\n"
    1097                 :              "                               access to)\n"));
    1098 GNC           1 :     printf(_("  --exclude-table-and-children=PATTERN\n"
    1099                 :              "                               do NOT dump the specified table(s),\n"
    1100                 :              "                               including child and partition tables\n"));
    1101 GIC           1 :     printf(_("  --exclude-table-data=PATTERN do NOT dump data for the specified table(s)\n"));
    1102 GNC           1 :     printf(_("  --exclude-table-data-and-children=PATTERN\n"
    1103                 :              "                               do NOT dump data for the specified table(s),\n"
    1104                 :              "                               including child and partition tables\n"));
    1105 GIC           1 :     printf(_("  --extra-float-digits=NUM     override default setting for extra_float_digits\n"));
    1106               1 :     printf(_("  --if-exists                  use IF EXISTS when dropping objects\n"));
    1107               1 :     printf(_("  --include-foreign-data=PATTERN\n"
    1108                 :              "                               include data of foreign tables on foreign\n"
    1109 ECB             :              "                               servers matching PATTERN\n"));
    1110 CBC           1 :     printf(_("  --inserts                    dump data as INSERT commands, rather than COPY\n"));
    1111 GIC           1 :     printf(_("  --load-via-partition-root    load partitions via the root table\n"));
    1112               1 :     printf(_("  --no-comments                do not dump comments\n"));
    1113               1 :     printf(_("  --no-publications            do not dump publications\n"));
    1114               1 :     printf(_("  --no-security-labels         do not dump security label assignments\n"));
    1115               1 :     printf(_("  --no-subscriptions           do not dump subscriptions\n"));
    1116               1 :     printf(_("  --no-table-access-method     do not dump table access methods\n"));
    1117               1 :     printf(_("  --no-tablespaces             do not dump tablespace assignments\n"));
    1118               1 :     printf(_("  --no-toast-compression       do not dump TOAST compression methods\n"));
    1119 CBC           1 :     printf(_("  --no-unlogged-table-data     do not dump unlogged table data\n"));
    1120               1 :     printf(_("  --on-conflict-do-nothing     add ON CONFLICT DO NOTHING to INSERT commands\n"));
    1121 GIC           1 :     printf(_("  --quote-all-identifiers      quote all identifiers, even if not key words\n"));
    1122 CBC           1 :     printf(_("  --rows-per-insert=NROWS      number of rows per INSERT; implies --inserts\n"));
    1123 GIC           1 :     printf(_("  --section=SECTION            dump named section (pre-data, data, or post-data)\n"));
    1124 CBC           1 :     printf(_("  --serializable-deferrable    wait until the dump can run without anomalies\n"));
    1125 GIC           1 :     printf(_("  --snapshot=SNAPSHOT          use given snapshot for the dump\n"));
    1126               1 :     printf(_("  --strict-names               require table and/or schema include patterns to\n"
    1127                 :              "                               match at least one entity each\n"));
    1128 GNC           1 :     printf(_("  --table-and-children=PATTERN dump only the specified table(s),\n"
    1129                 :              "                               including child and partition tables\n"));
    1130 GIC           1 :     printf(_("  --use-set-session-authorization\n"
    1131 ECB             :              "                               use SET SESSION AUTHORIZATION commands instead of\n"
    1132                 :              "                               ALTER OWNER commands to set ownership\n"));
    1133                 : 
    1134 CBC           1 :     printf(_("\nConnection options:\n"));
    1135               1 :     printf(_("  -d, --dbname=DBNAME      database to dump\n"));
    1136 GIC           1 :     printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
    1137 CBC           1 :     printf(_("  -p, --port=PORT          database server port number\n"));
    1138               1 :     printf(_("  -U, --username=NAME      connect as specified database user\n"));
    1139               1 :     printf(_("  -w, --no-password        never prompt for password\n"));
    1140 GIC           1 :     printf(_("  -W, --password           force password prompt (should happen automatically)\n"));
    1141 CBC           1 :     printf(_("  --role=ROLENAME          do SET ROLE before dump\n"));
    1142 ECB             : 
    1143 CBC           1 :     printf(_("\nIf no database name is supplied, then the PGDATABASE environment\n"
    1144 ECB             :              "variable value is used.\n\n"));
    1145 GIC           1 :     printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
    1146 CBC           1 :     printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
    1147               1 : }
    1148 ECB             : 
    1149                 : static void
    1150 CBC         149 : setup_connection(Archive *AH, const char *dumpencoding,
    1151 ECB             :                  const char *dumpsnapshot, char *use_role)
    1152                 : {
    1153 GIC         149 :     DumpOptions *dopt = AH->dopt;
    1154 CBC         149 :     PGconn     *conn = GetConnection(AH);
    1155                 :     const char *std_strings;
    1156 ECB             : 
    1157 CBC         149 :     PQclear(ExecuteSqlQueryForSingleRow(AH, ALWAYS_SECURE_SEARCH_PATH_SQL));
    1158 ECB             : 
    1159                 :     /*
    1160                 :      * Set the client encoding if requested.
    1161                 :      */
    1162 CBC         149 :     if (dumpencoding)
    1163                 :     {
    1164              20 :         if (PQsetClientEncoding(conn, dumpencoding) < 0)
    1165 LBC           0 :             pg_fatal("invalid client encoding \"%s\" specified",
    1166 ECB             :                      dumpencoding);
    1167                 :     }
    1168                 : 
    1169                 :     /*
    1170                 :      * Get the active encoding and the standard_conforming_strings setting, so
    1171                 :      * we know how to escape strings.
    1172                 :      */
    1173 CBC         149 :     AH->encoding = PQclientEncoding(conn);
    1174                 : 
    1175             149 :     std_strings = PQparameterStatus(conn, "standard_conforming_strings");
    1176 GIC         149 :     AH->std_strings = (std_strings && strcmp(std_strings, "on") == 0);
    1177                 : 
    1178 ECB             :     /*
    1179                 :      * Set the role if requested.  In a parallel dump worker, we'll be passed
    1180                 :      * use_role == NULL, but AH->use_role is already set (if user specified it
    1181                 :      * originally) and we should use that.
    1182                 :      */
    1183 CBC         149 :     if (!use_role && AH->use_role)
    1184               2 :         use_role = AH->use_role;
    1185                 : 
    1186                 :     /* Set the role if requested */
    1187             149 :     if (use_role)
    1188 ECB             :     {
    1189 CBC           5 :         PQExpBuffer query = createPQExpBuffer();
    1190 ECB             : 
    1191 CBC           5 :         appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
    1192               5 :         ExecuteSqlStatement(AH, query->data);
    1193               5 :         destroyPQExpBuffer(query);
    1194 ECB             : 
    1195                 :         /* save it for possible later use by parallel workers */
    1196 CBC           5 :         if (!AH->use_role)
    1197               3 :             AH->use_role = pg_strdup(use_role);
    1198 ECB             :     }
    1199                 : 
    1200                 :     /* Set the datestyle to ISO to ensure the dump's portability */
    1201 CBC         149 :     ExecuteSqlStatement(AH, "SET DATESTYLE = ISO");
    1202 ECB             : 
    1203                 :     /* Likewise, avoid using sql_standard intervalstyle */
    1204 GIC         149 :     ExecuteSqlStatement(AH, "SET INTERVALSTYLE = POSTGRES");
    1205 ECB             : 
    1206                 :     /*
    1207                 :      * Use an explicitly specified extra_float_digits if it has been provided.
    1208                 :      * Otherwise, set extra_float_digits so that we can dump float data
    1209                 :      * exactly (given correctly implemented float I/O code, anyway).
    1210                 :      */
    1211 CBC         149 :     if (have_extra_float_digits)
    1212 ECB             :     {
    1213 LBC           0 :         PQExpBuffer q = createPQExpBuffer();
    1214 ECB             : 
    1215 LBC           0 :         appendPQExpBuffer(q, "SET extra_float_digits TO %d",
    1216 ECB             :                           extra_float_digits);
    1217 LBC           0 :         ExecuteSqlStatement(AH, q->data);
    1218               0 :         destroyPQExpBuffer(q);
    1219                 :     }
    1220 ECB             :     else
    1221 GIC         149 :         ExecuteSqlStatement(AH, "SET extra_float_digits TO 3");
    1222 ECB             : 
    1223                 :     /*
    1224                 :      * Disable synchronized scanning, to prevent unpredictable changes in row
    1225                 :      * ordering across a dump and reload.
    1226                 :      */
    1227 CBC         149 :     ExecuteSqlStatement(AH, "SET synchronize_seqscans TO off");
    1228                 : 
    1229                 :     /*
    1230 ECB             :      * Disable timeouts if supported.
    1231                 :      */
    1232 GIC         149 :     ExecuteSqlStatement(AH, "SET statement_timeout = 0");
    1233             149 :     if (AH->remoteVersion >= 90300)
    1234 CBC         149 :         ExecuteSqlStatement(AH, "SET lock_timeout = 0");
    1235 GIC         149 :     if (AH->remoteVersion >= 90600)
    1236             149 :         ExecuteSqlStatement(AH, "SET idle_in_transaction_session_timeout = 0");
    1237                 : 
    1238                 :     /*
    1239 ECB             :      * Quote all identifiers, if requested.
    1240                 :      */
    1241 CBC         149 :     if (quote_all_identifiers)
    1242 GBC           6 :         ExecuteSqlStatement(AH, "SET quote_all_identifiers = true");
    1243                 : 
    1244                 :     /*
    1245                 :      * Adjust row-security mode, if supported.
    1246                 :      */
    1247 GIC         149 :     if (AH->remoteVersion >= 90500)
    1248                 :     {
    1249             149 :         if (dopt->enable_row_security)
    1250 LBC           0 :             ExecuteSqlStatement(AH, "SET row_security = on");
    1251                 :         else
    1252 CBC         149 :             ExecuteSqlStatement(AH, "SET row_security = off");
    1253 ECB             :     }
    1254                 : 
    1255                 :     /*
    1256                 :      * Initialize prepared-query state to "nothing prepared".  We do this here
    1257                 :      * so that a parallel dump worker will have its own state.
    1258                 :      */
    1259 GIC         149 :     AH->is_prepared = (bool *) pg_malloc0(NUM_PREP_QUERIES * sizeof(bool));
    1260 ECB             : 
    1261                 :     /*
    1262                 :      * Start transaction-snapshot mode transaction to dump consistent data.
    1263                 :      */
    1264 CBC         149 :     ExecuteSqlStatement(AH, "BEGIN");
    1265                 : 
    1266 ECB             :     /*
    1267                 :      * To support the combination of serializable_deferrable with the jobs
    1268                 :      * option we use REPEATABLE READ for the worker connections that are
    1269                 :      * passed a snapshot.  As long as the snapshot is acquired in a
    1270                 :      * SERIALIZABLE, READ ONLY, DEFERRABLE transaction, its use within a
    1271                 :      * REPEATABLE READ transaction provides the appropriate integrity
    1272                 :      * guarantees.  This is a kluge, but safe for back-patching.
    1273                 :      */
    1274 CBC         149 :     if (dopt->serializable_deferrable && AH->sync_snapshot_id == NULL)
    1275 UIC           0 :         ExecuteSqlStatement(AH,
    1276                 :                             "SET TRANSACTION ISOLATION LEVEL "
    1277                 :                             "SERIALIZABLE, READ ONLY, DEFERRABLE");
    1278 ECB             :     else
    1279 GIC         149 :         ExecuteSqlStatement(AH,
    1280                 :                             "SET TRANSACTION ISOLATION LEVEL "
    1281 ECB             :                             "REPEATABLE READ, READ ONLY");
    1282                 : 
    1283                 :     /*
    1284                 :      * If user specified a snapshot to use, select that.  In a parallel dump
    1285                 :      * worker, we'll be passed dumpsnapshot == NULL, but AH->sync_snapshot_id
    1286                 :      * is already set (if the server can handle it) and we should use that.
    1287                 :      */
    1288 CBC         149 :     if (dumpsnapshot)
    1289 UIC           0 :         AH->sync_snapshot_id = pg_strdup(dumpsnapshot);
    1290 EUB             : 
    1291 GIC         149 :     if (AH->sync_snapshot_id)
    1292 EUB             :     {
    1293 GIC          18 :         PQExpBuffer query = createPQExpBuffer();
    1294 EUB             : 
    1295 GBC          18 :         appendPQExpBufferStr(query, "SET TRANSACTION SNAPSHOT ");
    1296 GIC          18 :         appendStringLiteralConn(query, AH->sync_snapshot_id, conn);
    1297              18 :         ExecuteSqlStatement(AH, query->data);
    1298 CBC          18 :         destroyPQExpBuffer(query);
    1299                 :     }
    1300 GIC         131 :     else if (AH->numWorkers > 1)
    1301                 :     {
    1302               9 :         if (AH->isStandby && AH->remoteVersion < 100000)
    1303 UIC           0 :             pg_fatal("parallel dumps from standby servers are not supported by this server version");
    1304 CBC           9 :         AH->sync_snapshot_id = get_synchronized_snapshot(AH);
    1305                 :     }
    1306 GIC         149 : }
    1307                 : 
    1308                 : /* Set up connection for a parallel worker process */
    1309 ECB             : static void
    1310 CBC          18 : setupDumpWorker(Archive *AH)
    1311 ECB             : {
    1312                 :     /*
    1313                 :      * We want to re-select all the same values the leader connection is
    1314                 :      * using.  We'll have inherited directly-usable values in
    1315                 :      * AH->sync_snapshot_id and AH->use_role, but we need to translate the
    1316                 :      * inherited encoding value back to a string to pass to setup_connection.
    1317                 :      */
    1318 CBC          18 :     setup_connection(AH,
    1319 ECB             :                      pg_encoding_to_char(AH->encoding),
    1320                 :                      NULL,
    1321                 :                      NULL);
    1322 GIC          18 : }
    1323                 : 
    1324 ECB             : static char *
    1325 GIC           9 : get_synchronized_snapshot(Archive *fout)
    1326 ECB             : {
    1327 GBC           9 :     char       *query = "SELECT pg_catalog.pg_export_snapshot()";
    1328                 :     char       *result;
    1329 ECB             :     PGresult   *res;
    1330                 : 
    1331 GIC           9 :     res = ExecuteSqlQueryForSingleRow(fout, query);
    1332               9 :     result = pg_strdup(PQgetvalue(res, 0, 0));
    1333               9 :     PQclear(res);
    1334                 : 
    1335               9 :     return result;
    1336 ECB             : }
    1337                 : 
    1338                 : static ArchiveFormat
    1339 GIC         139 : parseArchiveFormat(const char *format, ArchiveMode *mode)
    1340                 : {
    1341 ECB             :     ArchiveFormat archiveFormat;
    1342                 : 
    1343 GIC         139 :     *mode = archModeWrite;
    1344                 : 
    1345             139 :     if (pg_strcasecmp(format, "a") == 0 || pg_strcasecmp(format, "append") == 0)
    1346                 :     {
    1347                 :         /* This is used by pg_dumpall, and is not documented */
    1348              34 :         archiveFormat = archNull;
    1349              34 :         *mode = archModeAppend;
    1350                 :     }
    1351 CBC         105 :     else if (pg_strcasecmp(format, "c") == 0)
    1352 GBC           2 :         archiveFormat = archCustom;
    1353 GIC         103 :     else if (pg_strcasecmp(format, "custom") == 0)
    1354              10 :         archiveFormat = archCustom;
    1355              93 :     else if (pg_strcasecmp(format, "d") == 0)
    1356 CBC           7 :         archiveFormat = archDirectory;
    1357 GIC          86 :     else if (pg_strcasecmp(format, "directory") == 0)
    1358               4 :         archiveFormat = archDirectory;
    1359              82 :     else if (pg_strcasecmp(format, "p") == 0)
    1360              74 :         archiveFormat = archNull;
    1361               8 :     else if (pg_strcasecmp(format, "plain") == 0)
    1362               4 :         archiveFormat = archNull;
    1363               4 :     else if (pg_strcasecmp(format, "t") == 0)
    1364               2 :         archiveFormat = archTar;
    1365 CBC           2 :     else if (pg_strcasecmp(format, "tar") == 0)
    1366 GBC           1 :         archiveFormat = archTar;
    1367                 :     else
    1368 CBC           1 :         pg_fatal("invalid output format \"%s\" specified", format);
    1369 GIC         138 :     return archiveFormat;
    1370 ECB             : }
    1371                 : 
    1372                 : /*
    1373                 :  * Find the OIDs of all schemas matching the given list of patterns,
    1374                 :  * and append them to the given OID list.
    1375                 :  */
    1376                 : static void
    1377 CBC         138 : expand_schema_name_patterns(Archive *fout,
    1378                 :                             SimpleStringList *patterns,
    1379 ECB             :                             SimpleOidList *oids,
    1380 EUB             :                             bool strict_names)
    1381 ECB             : {
    1382                 :     PQExpBuffer query;
    1383                 :     PGresult   *res;
    1384                 :     SimpleStringListCell *cell;
    1385                 :     int         i;
    1386                 : 
    1387 CBC         138 :     if (patterns->head == NULL)
    1388 GIC         123 :         return;                 /* nothing to do */
    1389                 : 
    1390              15 :     query = createPQExpBuffer();
    1391                 : 
    1392                 :     /*
    1393                 :      * The loop below runs multiple SELECTs might sometimes result in
    1394                 :      * duplicate entries in the OID list, but we don't care.
    1395 ECB             :      */
    1396                 : 
    1397 GIC          24 :     for (cell = patterns->head; cell; cell = cell->next)
    1398                 :     {
    1399 ECB             :         PQExpBufferData dbbuf;
    1400                 :         int         dotcnt;
    1401                 : 
    1402 CBC          15 :         appendPQExpBufferStr(query,
    1403                 :                              "SELECT oid FROM pg_catalog.pg_namespace n\n");
    1404              15 :         initPQExpBuffer(&dbbuf);
    1405 GIC          15 :         processSQLNamePattern(GetConnection(fout), query, cell->val, false,
    1406                 :                               false, NULL, "n.nspname", NULL, NULL, &dbbuf,
    1407                 :                               &dotcnt);
    1408 CBC          15 :         if (dotcnt > 1)
    1409               2 :             pg_fatal("improper qualified name (too many dotted names): %s",
    1410 ECB             :                      cell->val);
    1411 GIC          13 :         else if (dotcnt == 1)
    1412 CBC           3 :             prohibit_crossdb_refs(GetConnection(fout), dbbuf.data, cell->val);
    1413 GIC          10 :         termPQExpBuffer(&dbbuf);
    1414                 : 
    1415              10 :         res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    1416 CBC          10 :         if (strict_names && PQntuples(res) == 0)
    1417 GIC           1 :             pg_fatal("no matching schemas were found for pattern \"%s\"", cell->val);
    1418                 : 
    1419              17 :         for (i = 0; i < PQntuples(res); i++)
    1420 ECB             :         {
    1421 GIC           8 :             simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
    1422 ECB             :         }
    1423                 : 
    1424 GIC           9 :         PQclear(res);
    1425 CBC           9 :         resetPQExpBuffer(query);
    1426 ECB             :     }
    1427                 : 
    1428 CBC           9 :     destroyPQExpBuffer(query);
    1429 ECB             : }
    1430                 : 
    1431                 : /*
    1432                 :  * Find the OIDs of all extensions matching the given list of patterns,
    1433                 :  * and append them to the given OID list.
    1434                 :  */
    1435                 : static void
    1436 CBC           4 : expand_extension_name_patterns(Archive *fout,
    1437 ECB             :                                SimpleStringList *patterns,
    1438                 :                                SimpleOidList *oids,
    1439                 :                                bool strict_names)
    1440                 : {
    1441                 :     PQExpBuffer query;
    1442                 :     PGresult   *res;
    1443                 :     SimpleStringListCell *cell;
    1444                 :     int         i;
    1445                 : 
    1446 CBC           4 :     if (patterns->head == NULL)
    1447 UIC           0 :         return;                 /* nothing to do */
    1448                 : 
    1449 GIC           4 :     query = createPQExpBuffer();
    1450                 : 
    1451                 :     /*
    1452                 :      * The loop below runs multiple SELECTs might sometimes result in
    1453                 :      * duplicate entries in the OID list, but we don't care.
    1454 ECB             :      */
    1455 GIC           8 :     for (cell = patterns->head; cell; cell = cell->next)
    1456                 :     {
    1457                 :         int         dotcnt;
    1458                 : 
    1459               4 :         appendPQExpBufferStr(query,
    1460                 :                              "SELECT oid FROM pg_catalog.pg_extension e\n");
    1461               4 :         processSQLNamePattern(GetConnection(fout), query, cell->val, false,
    1462                 :                               false, NULL, "e.extname", NULL, NULL, NULL,
    1463                 :                               &dotcnt);
    1464 CBC           4 :         if (dotcnt > 0)
    1465 LBC           0 :             pg_fatal("improper qualified name (too many dotted names): %s",
    1466                 :                      cell->val);
    1467 ECB             : 
    1468 GIC           4 :         res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    1469               4 :         if (strict_names && PQntuples(res) == 0)
    1470 UIC           0 :             pg_fatal("no matching extensions were found for pattern \"%s\"", cell->val);
    1471                 : 
    1472 GIC           8 :         for (i = 0; i < PQntuples(res); i++)
    1473                 :         {
    1474 CBC           4 :             simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
    1475                 :         }
    1476                 : 
    1477 GIC           4 :         PQclear(res);
    1478               4 :         resetPQExpBuffer(query);
    1479 ECB             :     }
    1480                 : 
    1481 CBC           4 :     destroyPQExpBuffer(query);
    1482 ECB             : }
    1483                 : 
    1484                 : /*
    1485                 :  * Find the OIDs of all foreign servers matching the given list of patterns,
    1486                 :  * and append them to the given OID list.
    1487                 :  */
    1488                 : static void
    1489 CBC         119 : expand_foreign_server_name_patterns(Archive *fout,
    1490 ECB             :                                     SimpleStringList *patterns,
    1491                 :                                     SimpleOidList *oids)
    1492                 : {
    1493                 :     PQExpBuffer query;
    1494                 :     PGresult   *res;
    1495                 :     SimpleStringListCell *cell;
    1496                 :     int         i;
    1497                 : 
    1498 CBC         119 :     if (patterns->head == NULL)
    1499 GIC         117 :         return;                 /* nothing to do */
    1500                 : 
    1501 CBC           2 :     query = createPQExpBuffer();
    1502 ECB             : 
    1503                 :     /*
    1504                 :      * The loop below runs multiple SELECTs might sometimes result in
    1505                 :      * duplicate entries in the OID list, but we don't care.
    1506                 :      */
    1507                 : 
    1508 GIC           4 :     for (cell = patterns->head; cell; cell = cell->next)
    1509                 :     {
    1510                 :         int         dotcnt;
    1511                 : 
    1512               2 :         appendPQExpBufferStr(query,
    1513 ECB             :                              "SELECT oid FROM pg_catalog.pg_foreign_server s\n");
    1514 GIC           2 :         processSQLNamePattern(GetConnection(fout), query, cell->val, false,
    1515                 :                               false, NULL, "s.srvname", NULL, NULL, NULL,
    1516                 :                               &dotcnt);
    1517               2 :         if (dotcnt > 0)
    1518 UIC           0 :             pg_fatal("improper qualified name (too many dotted names): %s",
    1519                 :                      cell->val);
    1520                 : 
    1521 GIC           2 :         res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    1522               2 :         if (PQntuples(res) == 0)
    1523 LBC           0 :             pg_fatal("no matching foreign servers were found for pattern \"%s\"", cell->val);
    1524 EUB             : 
    1525 GIC           4 :         for (i = 0; i < PQntuples(res); i++)
    1526 CBC           2 :             simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
    1527                 : 
    1528 GIC           2 :         PQclear(res);
    1529               2 :         resetPQExpBuffer(query);
    1530                 :     }
    1531                 : 
    1532 CBC           2 :     destroyPQExpBuffer(query);
    1533                 : }
    1534                 : 
    1535                 : /*
    1536 ECB             :  * Find the OIDs of all tables matching the given list of patterns,
    1537                 :  * and append them to the given OID list. See also expand_dbname_patterns()
    1538                 :  * in pg_dumpall.c
    1539                 :  */
    1540                 : static void
    1541 CBC         720 : expand_table_name_patterns(Archive *fout,
    1542 EUB             :                            SimpleStringList *patterns, SimpleOidList *oids,
    1543                 :                            bool strict_names, bool with_child_tables)
    1544                 : {
    1545 ECB             :     PQExpBuffer query;
    1546                 :     PGresult   *res;
    1547 EUB             :     SimpleStringListCell *cell;
    1548                 :     int         i;
    1549 ECB             : 
    1550 GIC         720 :     if (patterns->head == NULL)
    1551 CBC         707 :         return;                 /* nothing to do */
    1552                 : 
    1553 GIC          13 :     query = createPQExpBuffer();
    1554 ECB             : 
    1555                 :     /*
    1556                 :      * this might sometimes result in duplicate entries in the OID list, but
    1557                 :      * we don't care.
    1558                 :      */
    1559                 : 
    1560 GIC          23 :     for (cell = patterns->head; cell; cell = cell->next)
    1561                 :     {
    1562                 :         PQExpBufferData dbbuf;
    1563                 :         int         dotcnt;
    1564                 : 
    1565                 :         /*
    1566 ECB             :          * Query must remain ABSOLUTELY devoid of unqualified names.  This
    1567                 :          * would be unnecessary given a pg_table_is_visible() variant taking a
    1568                 :          * search_path argument.
    1569                 :          *
    1570                 :          * For with_child_tables, we start with the basic query's results and
    1571                 :          * recursively search the inheritance tree to add child tables.
    1572                 :          */
    1573 GNC          14 :         if (with_child_tables)
    1574                 :         {
    1575               3 :             appendPQExpBuffer(query, "WITH RECURSIVE partition_tree (relid) AS (\n");
    1576                 :         }
    1577                 : 
    1578 GIC          14 :         appendPQExpBuffer(query,
    1579                 :                           "SELECT c.oid"
    1580                 :                           "\nFROM pg_catalog.pg_class c"
    1581                 :                           "\n     LEFT JOIN pg_catalog.pg_namespace n"
    1582                 :                           "\n     ON n.oid OPERATOR(pg_catalog.=) c.relnamespace"
    1583 ECB             :                           "\nWHERE c.relkind OPERATOR(pg_catalog.=) ANY"
    1584                 :                           "\n    (array['%c', '%c', '%c', '%c', '%c', '%c'])\n",
    1585                 :                           RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW,
    1586                 :                           RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE,
    1587                 :                           RELKIND_PARTITIONED_TABLE);
    1588 GIC          14 :         initPQExpBuffer(&dbbuf);
    1589              14 :         processSQLNamePattern(GetConnection(fout), query, cell->val, true,
    1590                 :                               false, "n.nspname", "c.relname", NULL,
    1591                 :                               "pg_catalog.pg_table_is_visible(c.oid)", &dbbuf,
    1592                 :                               &dotcnt);
    1593 CBC          14 :         if (dotcnt > 2)
    1594 GIC           1 :             pg_fatal("improper relation name (too many dotted names): %s",
    1595                 :                      cell->val);
    1596              13 :         else if (dotcnt == 2)
    1597 CBC           2 :             prohibit_crossdb_refs(GetConnection(fout), dbbuf.data, cell->val);
    1598 GIC          11 :         termPQExpBuffer(&dbbuf);
    1599 ECB             : 
    1600 GNC          11 :         if (with_child_tables)
    1601                 :         {
    1602               3 :             appendPQExpBuffer(query, "UNION"
    1603                 :                               "\nSELECT i.inhrelid"
    1604                 :                               "\nFROM partition_tree p"
    1605                 :                               "\n     JOIN pg_catalog.pg_inherits i"
    1606                 :                               "\n     ON p.relid OPERATOR(pg_catalog.=) i.inhparent"
    1607                 :                               "\n)"
    1608                 :                               "\nSELECT relid FROM partition_tree");
    1609                 :         }
    1610                 : 
    1611 GIC          11 :         ExecuteSqlStatement(fout, "RESET search_path");
    1612              11 :         res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    1613 CBC          11 :         PQclear(ExecuteSqlQueryForSingleRow(fout,
    1614 EUB             :                                             ALWAYS_SECURE_SEARCH_PATH_SQL));
    1615 GIC          11 :         if (strict_names && PQntuples(res) == 0)
    1616               1 :             pg_fatal("no matching tables were found for pattern \"%s\"", cell->val);
    1617 ECB             : 
    1618 CBC          31 :         for (i = 0; i < PQntuples(res); i++)
    1619 EUB             :         {
    1620 GIC          21 :             simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
    1621 ECB             :         }
    1622                 : 
    1623 GIC          10 :         PQclear(res);
    1624 CBC          10 :         resetPQExpBuffer(query);
    1625 ECB             :     }
    1626                 : 
    1627 GIC           9 :     destroyPQExpBuffer(query);
    1628 ECB             : }
    1629                 : 
    1630                 : /*
    1631                 :  * Verifies that the connected database name matches the given database name,
    1632                 :  * and if not, dies with an error about the given pattern.
    1633                 :  *
    1634                 :  * The 'dbname' argument should be a literal name parsed from 'pattern'.
    1635                 :  */
    1636                 : static void
    1637 CBC           5 : prohibit_crossdb_refs(PGconn *conn, const char *dbname, const char *pattern)
    1638                 : {
    1639                 :     const char *db;
    1640                 : 
    1641 GIC           5 :     db = PQdb(conn);
    1642               5 :     if (db == NULL)
    1643 UIC           0 :         pg_fatal("You are currently not connected to a database.");
    1644                 : 
    1645 GIC           5 :     if (strcmp(db, dbname) != 0)
    1646 CBC           5 :         pg_fatal("cross-database references are not implemented: %s",
    1647 ECB             :                  pattern);
    1648 UIC           0 : }
    1649 ECB             : 
    1650                 : /*
    1651                 :  * checkExtensionMembership
    1652                 :  *      Determine whether object is an extension member, and if so,
    1653                 :  *      record an appropriate dependency and set the object's dump flag.
    1654                 :  *
    1655                 :  * It's important to call this for each object that could be an extension
    1656                 :  * member.  Generally, we integrate this with determining the object's
    1657                 :  * to-be-dumped-ness, since extension membership overrides other rules for that.
    1658                 :  *
    1659                 :  * Returns true if object is an extension member, else false.
    1660                 :  */
    1661                 : static bool
    1662 GIC      445511 : checkExtensionMembership(DumpableObject *dobj, Archive *fout)
    1663                 : {
    1664          445511 :     ExtensionInfo *ext = findOwningExtension(dobj->catId);
    1665                 : 
    1666          445511 :     if (ext == NULL)
    1667          445039 :         return false;
    1668                 : 
    1669 CBC         472 :     dobj->ext_member = true;
    1670                 : 
    1671 ECB             :     /* Record dependency so that getDependencies needn't deal with that */
    1672 GIC         472 :     addObjectDependency(dobj, ext->dobj.dumpId);
    1673                 : 
    1674 ECB             :     /*
    1675                 :      * In 9.6 and above, mark the member object to have any non-initial ACL,
    1676                 :      * policies, and security labels dumped.
    1677                 :      *
    1678                 :      * Note that any initial ACLs (see pg_init_privs) will be removed when we
    1679                 :      * extract the information about the object.  We don't provide support for
    1680                 :      * initial policies and security labels and it seems unlikely for those to
    1681                 :      * ever exist, but we may have to revisit this later.
    1682                 :      *
    1683                 :      * Prior to 9.6, we do not include any extension member components.
    1684                 :      *
    1685                 :      * In binary upgrades, we still dump all components of the members
    1686                 :      * individually, since the idea is to exactly reproduce the database
    1687                 :      * contents rather than replace the extension contents with something
    1688                 :      * different.
    1689                 :      */
    1690 CBC         472 :     if (fout->dopt->binary_upgrade)
    1691 GIC          47 :         dobj->dump = ext->dobj.dump;
    1692 ECB             :     else
    1693                 :     {
    1694 CBC         425 :         if (fout->remoteVersion < 90600)
    1695 UIC           0 :             dobj->dump = DUMP_COMPONENT_NONE;
    1696 ECB             :         else
    1697 GIC         425 :             dobj->dump = ext->dobj.dump_contains & (DUMP_COMPONENT_ACL |
    1698 ECB             :                                                     DUMP_COMPONENT_SECLABEL |
    1699                 :                                                     DUMP_COMPONENT_POLICY);
    1700                 :     }
    1701                 : 
    1702 GIC         472 :     return true;
    1703                 : }
    1704                 : 
    1705                 : /*
    1706                 :  * selectDumpableNamespace: policy-setting subroutine
    1707 ECB             :  *      Mark a namespace as to be dumped or not
    1708                 :  */
    1709                 : static void
    1710 GIC         783 : selectDumpableNamespace(NamespaceInfo *nsinfo, Archive *fout)
    1711 ECB             : {
    1712                 :     /*
    1713                 :      * DUMP_COMPONENT_DEFINITION typically implies a CREATE SCHEMA statement
    1714                 :      * and (for --clean) a DROP SCHEMA statement.  (In the absence of
    1715                 :      * DUMP_COMPONENT_DEFINITION, this value is irrelevant.)
    1716                 :      */
    1717 GIC         783 :     nsinfo->create = true;
    1718                 : 
    1719 ECB             :     /*
    1720                 :      * If specific tables are being dumped, do not dump any complete
    1721                 :      * namespaces. If specific namespaces are being dumped, dump just those
    1722                 :      * namespaces. Otherwise, dump all non-system namespaces.
    1723                 :      */
    1724 GIC         783 :     if (table_include_oids.head != NULL)
    1725              18 :         nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_NONE;
    1726             765 :     else if (schema_include_oids.head != NULL)
    1727              39 :         nsinfo->dobj.dump_contains = nsinfo->dobj.dump =
    1728              39 :             simple_oid_list_member(&schema_include_oids,
    1729                 :                                    nsinfo->dobj.catId.oid) ?
    1730              39 :             DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
    1731             726 :     else if (fout->remoteVersion >= 90600 &&
    1732             726 :              strcmp(nsinfo->dobj.name, "pg_catalog") == 0)
    1733 ECB             :     {
    1734                 :         /*
    1735                 :          * In 9.6 and above, we dump out any ACLs defined in pg_catalog, if
    1736                 :          * they are interesting (and not the original ACLs which were set at
    1737                 :          * initdb time, see pg_init_privs).
    1738                 :          */
    1739 GBC         109 :         nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_ACL;
    1740                 :     }
    1741 CBC         617 :     else if (strncmp(nsinfo->dobj.name, "pg_", 3) == 0 ||
    1742             356 :              strcmp(nsinfo->dobj.name, "information_schema") == 0)
    1743                 :     {
    1744 EUB             :         /* Other system schemas don't get dumped */
    1745 GIC         370 :         nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_NONE;
    1746                 :     }
    1747             247 :     else if (strcmp(nsinfo->dobj.name, "public") == 0)
    1748                 :     {
    1749                 :         /*
    1750                 :          * The public schema is a strange beast that sits in a sort of
    1751                 :          * no-mans-land between being a system object and a user object.
    1752                 :          * CREATE SCHEMA would fail, so its DUMP_COMPONENT_DEFINITION is just
    1753                 :          * a comment and an indication of ownership.  If the owner is the
    1754                 :          * default, omit that superfluous DUMP_COMPONENT_DEFINITION.  Before
    1755                 :          * v15, the default owner was BOOTSTRAP_SUPERUSERID.
    1756                 :          */
    1757             105 :         nsinfo->create = false;
    1758 CBC         105 :         nsinfo->dobj.dump = DUMP_COMPONENT_ALL;
    1759 GIC         105 :         if (nsinfo->nspowner == ROLE_PG_DATABASE_OWNER)
    1760 CBC          62 :             nsinfo->dobj.dump &= ~DUMP_COMPONENT_DEFINITION;
    1761 GIC         105 :         nsinfo->dobj.dump_contains = DUMP_COMPONENT_ALL;
    1762 ECB             : 
    1763                 :         /*
    1764                 :          * Also, make like it has a comment even if it doesn't; this is so
    1765                 :          * that we'll emit a command to drop the comment, if appropriate.
    1766                 :          * (Without this, we'd not call dumpCommentExtended for it.)
    1767                 :          */
    1768 CBC         105 :         nsinfo->dobj.components |= DUMP_COMPONENT_COMMENT;
    1769                 :     }
    1770                 :     else
    1771 GIC         142 :         nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_ALL;
    1772                 : 
    1773                 :     /*
    1774                 :      * In any case, a namespace can be excluded by an exclusion switch
    1775                 :      */
    1776            1146 :     if (nsinfo->dobj.dump_contains &&
    1777             363 :         simple_oid_list_member(&schema_exclude_oids,
    1778                 :                                nsinfo->dobj.catId.oid))
    1779               1 :         nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_NONE;
    1780                 : 
    1781                 :     /*
    1782                 :      * If the schema belongs to an extension, allow extension membership to
    1783                 :      * override the dump decision for the schema itself.  However, this does
    1784                 :      * not change dump_contains, so this won't change what we do with objects
    1785                 :      * within the schema.  (If they belong to the extension, they'll get
    1786 ECB             :      * suppressed by it, otherwise not.)
    1787                 :      */
    1788 GIC         783 :     (void) checkExtensionMembership(&nsinfo->dobj, fout);
    1789             783 : }
    1790 ECB             : 
    1791 EUB             : /*
    1792                 :  * selectDumpableTable: policy-setting subroutine
    1793 ECB             :  *      Mark a table as to be dumped or not
    1794                 :  */
    1795                 : static void
    1796 GIC       30467 : selectDumpableTable(TableInfo *tbinfo, Archive *fout)
    1797                 : {
    1798 CBC       30467 :     if (checkExtensionMembership(&tbinfo->dobj, fout))
    1799 GIC         198 :         return;                 /* extension membership overrides all else */
    1800                 : 
    1801                 :     /*
    1802                 :      * If specific tables are being dumped, dump just those tables; else, dump
    1803                 :      * according to the parent namespace's dump flag.
    1804                 :      */
    1805           30269 :     if (table_include_oids.head != NULL)
    1806 CBC        1488 :         tbinfo->dobj.dump = simple_oid_list_member(&table_include_oids,
    1807                 :                                                    tbinfo->dobj.catId.oid) ?
    1808 GIC         744 :             DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
    1809                 :     else
    1810           29525 :         tbinfo->dobj.dump = tbinfo->dobj.namespace->dobj.dump_contains;
    1811                 : 
    1812                 :     /*
    1813 ECB             :      * In any case, a table can be excluded by an exclusion switch
    1814                 :      */
    1815 GIC       50701 :     if (tbinfo->dobj.dump &&
    1816           20432 :         simple_oid_list_member(&table_exclude_oids,
    1817                 :                                tbinfo->dobj.catId.oid))
    1818               6 :         tbinfo->dobj.dump = DUMP_COMPONENT_NONE;
    1819                 : }
    1820 ECB             : 
    1821                 : /*
    1822                 :  * selectDumpableType: policy-setting subroutine
    1823                 :  *      Mark a type as to be dumped or not
    1824                 :  *
    1825                 :  * If it's a table's rowtype or an autogenerated array type, we also apply a
    1826                 :  * special type code to facilitate sorting into the desired order.  (We don't
    1827                 :  * want to consider those to be ordinary types because that would bring tables
    1828                 :  * up into the datatype part of the dump order.)  We still set the object's
    1829                 :  * dump flag; that's not going to cause the dummy type to be dumped, but we
    1830                 :  * need it so that casts involving such types will be dumped correctly -- see
    1831                 :  * dumpCast.  This means the flag should be set the same as for the underlying
    1832                 :  * object (the table or base type).
    1833                 :  */
    1834                 : static void
    1835 CBC       83866 : selectDumpableType(TypeInfo *tyinfo, Archive *fout)
    1836                 : {
    1837 ECB             :     /* skip complex types, except for standalone composite types */
    1838 CBC       83866 :     if (OidIsValid(tyinfo->typrelid) &&
    1839 GIC       29911 :         tyinfo->typrelkind != RELKIND_COMPOSITE_TYPE)
    1840                 :     {
    1841 CBC       29774 :         TableInfo  *tytable = findTableByOid(tyinfo->typrelid);
    1842                 : 
    1843           29774 :         tyinfo->dobj.objType = DO_DUMMY_TYPE;
    1844 GIC       29774 :         if (tytable != NULL)
    1845           29774 :             tyinfo->dobj.dump = tytable->dobj.dump;
    1846                 :         else
    1847 UIC           0 :             tyinfo->dobj.dump = DUMP_COMPONENT_NONE;
    1848 GIC       29774 :         return;
    1849                 :     }
    1850                 : 
    1851                 :     /* skip auto-generated array types */
    1852           54092 :     if (tyinfo->isArray || tyinfo->isMultirange)
    1853 ECB             :     {
    1854 CBC       41015 :         tyinfo->dobj.objType = DO_DUMMY_TYPE;
    1855 ECB             : 
    1856                 :         /*
    1857                 :          * Fall through to set the dump flag; we assume that the subsequent
    1858                 :          * rules will do the same thing as they would for the array's base
    1859                 :          * type.  (We cannot reliably look up the base type here, since
    1860                 :          * getTypes may not have processed it yet.)
    1861                 :          */
    1862                 :     }
    1863                 : 
    1864 CBC       54092 :     if (checkExtensionMembership(&tyinfo->dobj, fout))
    1865 GIC          22 :         return;                 /* extension membership overrides all else */
    1866                 : 
    1867 ECB             :     /* Dump based on if the contents of the namespace are being dumped */
    1868 GIC       54070 :     tyinfo->dobj.dump = tyinfo->dobj.namespace->dobj.dump_contains;
    1869                 : }
    1870                 : 
    1871                 : /*
    1872 ECB             :  * selectDumpableDefaultACL: policy-setting subroutine
    1873                 :  *      Mark a default ACL as to be dumped or not
    1874                 :  *
    1875                 :  * For per-schema default ACLs, dump if the schema is to be dumped.
    1876                 :  * Otherwise dump if we are dumping "everything".  Note that dataOnly
    1877                 :  * and aclsSkip are checked separately.
    1878                 :  */
    1879                 : static void
    1880 GIC         180 : selectDumpableDefaultACL(DefaultACLInfo *dinfo, DumpOptions *dopt)
    1881                 : {
    1882                 :     /* Default ACLs can't be extension members */
    1883                 : 
    1884 CBC         180 :     if (dinfo->dobj.namespace)
    1885 ECB             :         /* default ACLs are considered part of the namespace */
    1886 GIC          90 :         dinfo->dobj.dump = dinfo->dobj.namespace->dobj.dump_contains;
    1887                 :     else
    1888              90 :         dinfo->dobj.dump = dopt->include_everything ?
    1889              90 :             DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
    1890             180 : }
    1891                 : 
    1892 ECB             : /*
    1893                 :  * selectDumpableCast: policy-setting subroutine
    1894                 :  *      Mark a cast as to be dumped or not
    1895                 :  *
    1896                 :  * Casts do not belong to any particular namespace (since they haven't got
    1897                 :  * names), nor do they have identifiable owners.  To distinguish user-defined
    1898                 :  * casts from built-in ones, we must resort to checking whether the cast's
    1899                 :  * OID is in the range reserved for initdb.
    1900                 :  */
    1901                 : static void
    1902 CBC       26389 : selectDumpableCast(CastInfo *cast, Archive *fout)
    1903                 : {
    1904           26389 :     if (checkExtensionMembership(&cast->dobj, fout))
    1905 UIC           0 :         return;                 /* extension membership overrides all else */
    1906 ECB             : 
    1907                 :     /*
    1908                 :      * This would be DUMP_COMPONENT_ACL for from-initdb casts, but they do not
    1909                 :      * support ACLs currently.
    1910                 :      */
    1911 CBC       26389 :     if (cast->dobj.catId.oid <= (Oid) g_last_builtin_oid)
    1912           26314 :         cast->dobj.dump = DUMP_COMPONENT_NONE;
    1913                 :     else
    1914              75 :         cast->dobj.dump = fout->dopt->include_everything ?
    1915 GIC          75 :             DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
    1916                 : }
    1917                 : 
    1918                 : /*
    1919                 :  * selectDumpableProcLang: policy-setting subroutine
    1920                 :  *      Mark a procedural language as to be dumped or not
    1921                 :  *
    1922                 :  * Procedural languages do not belong to any particular namespace.  To
    1923                 :  * identify built-in languages, we must resort to checking whether the
    1924                 :  * language's OID is in the range reserved for initdb.
    1925                 :  */
    1926                 : static void
    1927             163 : selectDumpableProcLang(ProcLangInfo *plang, Archive *fout)
    1928                 : {
    1929             163 :     if (checkExtensionMembership(&plang->dobj, fout))
    1930             118 :         return;                 /* extension membership overrides all else */
    1931 ECB             : 
    1932                 :     /*
    1933                 :      * Only include procedural languages when we are dumping everything.
    1934                 :      *
    1935                 :      * For from-initdb procedural languages, only include ACLs, as we do for
    1936                 :      * the pg_catalog namespace.  We need this because procedural languages do
    1937                 :      * not live in any namespace.
    1938                 :      */
    1939 CBC          45 :     if (!fout->dopt->include_everything)
    1940               7 :         plang->dobj.dump = DUMP_COMPONENT_NONE;
    1941 ECB             :     else
    1942                 :     {
    1943 GBC          38 :         if (plang->dobj.catId.oid <= (Oid) g_last_builtin_oid)
    1944 LBC           0 :             plang->dobj.dump = fout->remoteVersion < 90600 ?
    1945 UIC           0 :                 DUMP_COMPONENT_NONE : DUMP_COMPONENT_ACL;
    1946                 :         else
    1947 GIC          38 :             plang->dobj.dump = DUMP_COMPONENT_ALL;
    1948 ECB             :     }
    1949                 : }
    1950                 : 
    1951                 : /*
    1952                 :  * selectDumpableAccessMethod: policy-setting subroutine
    1953                 :  *      Mark an access method as to be dumped or not
    1954                 :  *
    1955                 :  * Access methods do not belong to any particular namespace.  To identify
    1956                 :  * built-in access methods, we must resort to checking whether the
    1957                 :  * method's OID is in the range reserved for initdb.
    1958                 :  */
    1959                 : static void
    1960 CBC         943 : selectDumpableAccessMethod(AccessMethodInfo *method, Archive *fout)
    1961 ECB             : {
    1962 GIC         943 :     if (checkExtensionMembership(&method->dobj, fout))
    1963              22 :         return;                 /* extension membership overrides all else */
    1964 ECB             : 
    1965                 :     /*
    1966                 :      * This would be DUMP_COMPONENT_ACL for from-initdb access methods, but
    1967                 :      * they do not support ACLs currently.
    1968                 :      */
    1969 GIC         921 :     if (method->dobj.catId.oid <= (Oid) g_last_builtin_oid)
    1970             826 :         method->dobj.dump = DUMP_COMPONENT_NONE;
    1971                 :     else
    1972              95 :         method->dobj.dump = fout->dopt->include_everything ?
    1973              95 :             DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
    1974                 : }
    1975                 : 
    1976 ECB             : /*
    1977                 :  * selectDumpableExtension: policy-setting subroutine
    1978                 :  *      Mark an extension as to be dumped or not
    1979                 :  *
    1980                 :  * Built-in extensions should be skipped except for checking ACLs, since we
    1981                 :  * assume those will already be installed in the target database.  We identify
    1982                 :  * such extensions by their having OIDs in the range reserved for initdb.
    1983                 :  * We dump all user-added extensions by default.  No extensions are dumped
    1984                 :  * if include_everything is false (i.e., a --schema or --table switch was
    1985                 :  * given), except if --extension specifies a list of extensions to dump.
    1986                 :  */
    1987                 : static void
    1988 GIC         141 : selectDumpableExtension(ExtensionInfo *extinfo, DumpOptions *dopt)
    1989                 : {
    1990                 :     /*
    1991                 :      * Use DUMP_COMPONENT_ACL for built-in extensions, to allow users to
    1992                 :      * change permissions on their member objects, if they wish to, and have
    1993                 :      * those changes preserved.
    1994                 :      */
    1995             141 :     if (extinfo->dobj.catId.oid <= (Oid) g_last_builtin_oid)
    1996             119 :         extinfo->dobj.dump = extinfo->dobj.dump_contains = DUMP_COMPONENT_ACL;
    1997                 :     else
    1998 ECB             :     {
    1999                 :         /* check if there is a list of extensions to dump */
    2000 CBC          22 :         if (extension_include_oids.head != NULL)
    2001 GBC           4 :             extinfo->dobj.dump = extinfo->dobj.dump_contains =
    2002 GIC           4 :                 simple_oid_list_member(&extension_include_oids,
    2003                 :                                        extinfo->dobj.catId.oid) ?
    2004               4 :                 DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
    2005                 :         else
    2006              18 :             extinfo->dobj.dump = extinfo->dobj.dump_contains =
    2007 CBC          18 :                 dopt->include_everything ?
    2008              18 :                 DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
    2009                 :     }
    2010             141 : }
    2011 ECB             : 
    2012                 : /*
    2013                 :  * selectDumpablePublicationObject: policy-setting subroutine
    2014                 :  *      Mark a publication object as to be dumped or not
    2015                 :  *
    2016                 :  * A publication can have schemas and tables which have schemas, but those are
    2017                 :  * ignored in decision making, because publications are only dumped when we are
    2018                 :  * dumping everything.
    2019                 :  */
    2020                 : static void
    2021 GIC         353 : selectDumpablePublicationObject(DumpableObject *dobj, Archive *fout)
    2022                 : {
    2023 CBC         353 :     if (checkExtensionMembership(dobj, fout))
    2024 UIC           0 :         return;                 /* extension membership overrides all else */
    2025 ECB             : 
    2026 CBC         353 :     dobj->dump = fout->dopt->include_everything ?
    2027 GIC         353 :         DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
    2028                 : }
    2029                 : 
    2030                 : /*
    2031                 :  * selectDumpableObject: policy-setting subroutine
    2032                 :  *      Mark a generic dumpable object as to be dumped or not
    2033                 :  *
    2034                 :  * Use this only for object types without a special-case routine above.
    2035 ECB             :  */
    2036                 : static void
    2037 GIC      332321 : selectDumpableObject(DumpableObject *dobj, Archive *fout)
    2038                 : {
    2039 CBC      332321 :     if (checkExtensionMembership(dobj, fout))
    2040 GBC          90 :         return;                 /* extension membership overrides all else */
    2041 EUB             : 
    2042                 :     /*
    2043 ECB             :      * Default policy is to dump if parent namespace is dumpable, or for
    2044                 :      * non-namespace-associated items, dump if we're dumping "everything".
    2045                 :      */
    2046 GIC      332231 :     if (dobj->namespace)
    2047          331719 :         dobj->dump = dobj->namespace->dobj.dump_contains;
    2048                 :     else
    2049             512 :         dobj->dump = fout->dopt->include_everything ?
    2050             512 :             DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
    2051                 : }
    2052                 : 
    2053                 : /*
    2054                 :  *  Dump a table's contents for loading using the COPY command
    2055                 :  *  - this routine is called by the Archiver when it wants the table
    2056 ECB             :  *    to be dumped.
    2057                 :  */
    2058                 : static int
    2059 CBC        2982 : dumpTableData_copy(Archive *fout, const void *dcontext)
    2060                 : {
    2061 GIC        2982 :     TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
    2062            2982 :     TableInfo  *tbinfo = tdinfo->tdtable;
    2063            2982 :     const char *classname = tbinfo->dobj.name;
    2064            2982 :     PQExpBuffer q = createPQExpBuffer();
    2065 ECB             : 
    2066                 :     /*
    2067                 :      * Note: can't use getThreadLocalPQExpBuffer() here, we're calling fmtId
    2068                 :      * which uses it already.
    2069                 :      */
    2070 GIC        2982 :     PQExpBuffer clistBuf = createPQExpBuffer();
    2071            2982 :     PGconn     *conn = GetConnection(fout);
    2072                 :     PGresult   *res;
    2073                 :     int         ret;
    2074                 :     char       *copybuf;
    2075                 :     const char *column_list;
    2076                 : 
    2077            2982 :     pg_log_info("dumping contents of table \"%s.%s\"",
    2078                 :                 tbinfo->dobj.namespace->dobj.name, classname);
    2079                 : 
    2080                 :     /*
    2081                 :      * Specify the column list explicitly so that we have no possibility of
    2082                 :      * retrieving data in the wrong column order.  (The default column
    2083                 :      * ordering of COPY will not be what we want in certain corner cases
    2084 ECB             :      * involving ADD COLUMN and inheritance.)
    2085                 :      */
    2086 GIC        2982 :     column_list = fmtCopyColumnList(tbinfo, clistBuf);
    2087                 : 
    2088                 :     /*
    2089                 :      * Use COPY (SELECT ...) TO when dumping a foreign table's data, and when
    2090                 :      * a filter condition was specified.  For other cases a simple COPY
    2091 ECB             :      * suffices.
    2092                 :      */
    2093 GIC        2982 :     if (tdinfo->filtercond || tbinfo->relkind == RELKIND_FOREIGN_TABLE)
    2094                 :     {
    2095               1 :         appendPQExpBufferStr(q, "COPY (SELECT ");
    2096 ECB             :         /* klugery to get rid of parens in column list */
    2097 CBC           1 :         if (strlen(column_list) > 2)
    2098 ECB             :         {
    2099 GIC           1 :             appendPQExpBufferStr(q, column_list + 1);
    2100 CBC           1 :             q->data[q->len - 1] = ' ';
    2101                 :         }
    2102 ECB             :         else
    2103 LBC           0 :             appendPQExpBufferStr(q, "* ");
    2104 ECB             : 
    2105 GIC           2 :         appendPQExpBuffer(q, "FROM %s %s) TO stdout;",
    2106 CBC           1 :                           fmtQualifiedDumpable(tbinfo),
    2107 GIC           1 :                           tdinfo->filtercond ? tdinfo->filtercond : "");
    2108                 :     }
    2109                 :     else
    2110                 :     {
    2111            2981 :         appendPQExpBuffer(q, "COPY %s %s TO stdout;",
    2112            2981 :                           fmtQualifiedDumpable(tbinfo),
    2113                 :                           column_list);
    2114                 :     }
    2115            2982 :     res = ExecuteSqlQuery(fout, q->data, PGRES_COPY_OUT);
    2116            2981 :     PQclear(res);
    2117 CBC        2981 :     destroyPQExpBuffer(clistBuf);
    2118                 : 
    2119 ECB             :     for (;;)
    2120 EUB             :     {
    2121 GIC     1694713 :         ret = PQgetCopyData(conn, &copybuf, 0);
    2122 ECB             : 
    2123 CBC     1694713 :         if (ret < 0)
    2124 GIC        2981 :             break;              /* done or error */
    2125                 : 
    2126         1691732 :         if (copybuf)
    2127                 :         {
    2128         1691732 :             WriteData(fout, copybuf, ret);
    2129         1691732 :             PQfreemem(copybuf);
    2130                 :         }
    2131                 : 
    2132                 :         /* ----------
    2133 ECB             :          * THROTTLE:
    2134                 :          *
    2135                 :          * There was considerable discussion in late July, 2000 regarding
    2136                 :          * slowing down pg_dump when backing up large tables. Users with both
    2137                 :          * slow & fast (multi-processor) machines experienced performance
    2138                 :          * degradation when doing a backup.
    2139                 :          *
    2140                 :          * Initial attempts based on sleeping for a number of ms for each ms
    2141                 :          * of work were deemed too complex, then a simple 'sleep in each loop'
    2142                 :          * implementation was suggested. The latter failed because the loop
    2143                 :          * was too tight. Finally, the following was implemented:
    2144                 :          *
    2145                 :          * If throttle is non-zero, then
    2146                 :          *      See how long since the last sleep.
    2147                 :          *      Work out how long to sleep (based on ratio).
    2148                 :          *      If sleep is more than 100ms, then
    2149                 :          *          sleep
    2150                 :          *          reset timer
    2151                 :          *      EndIf
    2152                 :          * EndIf
    2153                 :          *
    2154                 :          * where the throttle value was the number of ms to sleep per ms of
    2155                 :          * work. The calculation was done in each loop.
    2156                 :          *
    2157                 :          * Most of the hard work is done in the backend, and this solution
    2158                 :          * still did not work particularly well: on slow machines, the ratio
    2159                 :          * was 50:1, and on medium paced machines, 1:1, and on fast
    2160                 :          * multi-processor machines, it had little or no effect, for reasons
    2161                 :          * that were unclear.
    2162                 :          *
    2163                 :          * Further discussion ensued, and the proposal was dropped.
    2164                 :          *
    2165                 :          * For those people who want this feature, it can be implemented using
    2166                 :          * gettimeofday in each loop, calculating the time since last sleep,
    2167                 :          * multiplying that by the sleep ratio, then if the result is more
    2168                 :          * than a preset 'minimum sleep time' (say 100ms), call the 'select'
    2169                 :          * function to sleep for a subsecond period ie.
    2170                 :          *
    2171                 :          * select(0, NULL, NULL, NULL, &tvi);
    2172                 :          *
    2173                 :          * This will return after the interval specified in the structure tvi.
    2174                 :          * Finally, call gettimeofday again to save the 'last sleep time'.
    2175                 :          * ----------
    2176                 :          */
    2177                 :     }
    2178 GIC        2981 :     archprintf(fout, "\\.\n\n\n");
    2179                 : 
    2180            2981 :     if (ret == -2)
    2181                 :     {
    2182 ECB             :         /* copy data transfer failed */
    2183 UIC           0 :         pg_log_error("Dumping the contents of table \"%s\" failed: PQgetCopyData() failed.", classname);
    2184               0 :         pg_log_error_detail("Error message from server: %s", PQerrorMessage(conn));
    2185               0 :         pg_log_error_detail("Command was: %s", q->data);
    2186               0 :         exit_nicely(1);
    2187                 :     }
    2188                 : 
    2189 ECB             :     /* Check command status and return to normal libpq state */
    2190 GIC        2981 :     res = PQgetResult(conn);
    2191 CBC        2981 :     if (PQresultStatus(res) != PGRES_COMMAND_OK)
    2192                 :     {
    2193 LBC           0 :         pg_log_error("Dumping the contents of table \"%s\" failed: PQgetResult() failed.", classname);
    2194 UIC           0 :         pg_log_error_detail("Error message from server: %s", PQerrorMessage(conn));
    2195 LBC           0 :         pg_log_error_detail("Command was: %s", q->data);
    2196               0 :         exit_nicely(1);
    2197                 :     }
    2198 GIC        2981 :     PQclear(res);
    2199 EUB             : 
    2200                 :     /* Do this to ensure we've pumped libpq back to idle state */
    2201 CBC        2981 :     if (PQgetResult(conn) != NULL)
    2202 LBC           0 :         pg_log_warning("unexpected extra results during COPY of table \"%s\"",
    2203 ECB             :                        classname);
    2204                 : 
    2205 GIC        2981 :     destroyPQExpBuffer(q);
    2206            2981 :     return 1;
    2207 ECB             : }
    2208                 : 
    2209                 : /*
    2210                 :  * Dump table data using INSERT commands.
    2211                 :  *
    2212                 :  * Caution: when we restore from an archive file direct to database, the
    2213                 :  * INSERT commands emitted by this function have to be parsed by
    2214                 :  * pg_backup_db.c's ExecuteSimpleCommands(), which will not handle comments,
    2215                 :  * E'' strings, or dollar-quoted strings.  So don't emit anything like that.
    2216                 :  */
    2217                 : static int
    2218 GIC          57 : dumpTableData_insert(Archive *fout, const void *dcontext)
    2219 ECB             : {
    2220 CBC          57 :     TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
    2221 GIC          57 :     TableInfo  *tbinfo = tdinfo->tdtable;
    2222 CBC          57 :     DumpOptions *dopt = fout->dopt;
    2223 GIC          57 :     PQExpBuffer q = createPQExpBuffer();
    2224 CBC          57 :     PQExpBuffer insertStmt = NULL;
    2225 ECB             :     char       *attgenerated;
    2226                 :     PGresult   *res;
    2227                 :     int         nfields,
    2228                 :                 i;
    2229 GIC          57 :     int         rows_per_statement = dopt->dump_inserts;
    2230              57 :     int         rows_this_statement = 0;
    2231                 : 
    2232                 :     /*
    2233                 :      * If we're going to emit INSERTs with column names, the most efficient
    2234                 :      * way to deal with generated columns is to exclude them entirely.  For
    2235                 :      * INSERTs without column names, we have to emit DEFAULT rather than the
    2236                 :      * actual column value --- but we can save a few cycles by fetching nulls
    2237                 :      * rather than the uninteresting-to-us value.
    2238                 :      */
    2239              57 :     attgenerated = (char *) pg_malloc(tbinfo->numatts * sizeof(char));
    2240              57 :     appendPQExpBufferStr(q, "DECLARE _pg_dump_cursor CURSOR FOR SELECT ");
    2241              57 :     nfields = 0;
    2242             191 :     for (i = 0; i < tbinfo->numatts; i++)
    2243                 :     {
    2244             134 :         if (tbinfo->attisdropped[i])
    2245               2 :             continue;
    2246             132 :         if (tbinfo->attgenerated[i] && dopt->column_inserts)
    2247               5 :             continue;
    2248             127 :         if (nfields > 0)
    2249              77 :             appendPQExpBufferStr(q, ", ");
    2250             127 :         if (tbinfo->attgenerated[i])
    2251               5 :             appendPQExpBufferStr(q, "NULL");
    2252                 :         else
    2253             122 :             appendPQExpBufferStr(q, fmtId(tbinfo->attnames[i]));
    2254             127 :         attgenerated[nfields] = tbinfo->attgenerated[i];
    2255             127 :         nfields++;
    2256                 :     }
    2257                 :     /* Servers before 9.4 will complain about zero-column SELECT */
    2258              57 :     if (nfields == 0)
    2259               7 :         appendPQExpBufferStr(q, "NULL");
    2260              57 :     appendPQExpBuffer(q, " FROM ONLY %s",
    2261              57 :                       fmtQualifiedDumpable(tbinfo));
    2262              57 :     if (tdinfo->filtercond)
    2263 UIC           0 :         appendPQExpBuffer(q, " %s", tdinfo->filtercond);
    2264                 : 
    2265 GIC          57 :     ExecuteSqlStatement(fout, q->data);
    2266                 : 
    2267                 :     while (1)
    2268                 :     {
    2269             105 :         res = ExecuteSqlQuery(fout, "FETCH 100 FROM _pg_dump_cursor",
    2270                 :                               PGRES_TUPLES_OK);
    2271                 : 
    2272                 :         /* cross-check field count, allowing for dummy NULL if any */
    2273             105 :         if (nfields != PQnfields(res) &&
    2274 CBC          10 :             !(nfields == 0 && PQnfields(res) == 1))
    2275 UIC           0 :             pg_fatal("wrong number of fields retrieved from table \"%s\"",
    2276 ECB             :                      tbinfo->dobj.name);
    2277                 : 
    2278                 :         /*
    2279 EUB             :          * First time through, we build as much of the INSERT statement as
    2280                 :          * possible in "insertStmt", which we can then just print for each
    2281                 :          * statement. If the table happens to have zero dumpable columns then
    2282                 :          * this will be a complete statement, otherwise it will end in
    2283                 :          * "VALUES" and be ready to have the row's column values printed.
    2284                 :          */
    2285 GIC         105 :         if (insertStmt == NULL)
    2286 ECB             :         {
    2287                 :             TableInfo  *targettab;
    2288                 : 
    2289 GBC          57 :             insertStmt = createPQExpBuffer();
    2290 EUB             : 
    2291                 :             /*
    2292                 :              * When load-via-partition-root is set or forced, get the root
    2293                 :              * table name for the partition table, so that we can reload data
    2294 ECB             :              * through the root table.
    2295                 :              */
    2296 GIC          57 :             if (tbinfo->ispartition &&
    2297 CBC          32 :                 (dopt->load_via_partition_root ||
    2298 GBC          16 :                  forcePartitionRootLoad(tbinfo)))
    2299 GIC           3 :                 targettab = getRootTableInfo(tbinfo);
    2300                 :             else
    2301 CBC          54 :                 targettab = tbinfo;
    2302 ECB             : 
    2303 GIC          57 :             appendPQExpBuffer(insertStmt, "INSERT INTO %s ",
    2304              57 :                               fmtQualifiedDumpable(targettab));
    2305                 : 
    2306                 :             /* corner case for zero-column table */
    2307              57 :             if (nfields == 0)
    2308                 :             {
    2309               7 :                 appendPQExpBufferStr(insertStmt, "DEFAULT VALUES;\n");
    2310                 :             }
    2311                 :             else
    2312                 :             {
    2313                 :                 /* append the list of column names if required */
    2314 CBC          50 :                 if (dopt->column_inserts)
    2315                 :                 {
    2316              21 :                     appendPQExpBufferChar(insertStmt, '(');
    2317              73 :                     for (int field = 0; field < nfields; field++)
    2318 ECB             :                     {
    2319 CBC          52 :                         if (field > 0)
    2320              31 :                             appendPQExpBufferStr(insertStmt, ", ");
    2321 GIC          52 :                         appendPQExpBufferStr(insertStmt,
    2322              52 :                                              fmtId(PQfname(res, field)));
    2323                 :                     }
    2324              21 :                     appendPQExpBufferStr(insertStmt, ") ");
    2325 ECB             :                 }
    2326                 : 
    2327 GIC          50 :                 if (tbinfo->needs_override)
    2328               2 :                     appendPQExpBufferStr(insertStmt, "OVERRIDING SYSTEM VALUE ");
    2329                 : 
    2330              50 :                 appendPQExpBufferStr(insertStmt, "VALUES");
    2331                 :             }
    2332                 :         }
    2333                 : 
    2334            3174 :         for (int tuple = 0; tuple < PQntuples(res); tuple++)
    2335 ECB             :         {
    2336                 :             /* Write the INSERT if not in the middle of a multi-row INSERT. */
    2337 CBC        3069 :             if (rows_this_statement == 0)
    2338            3063 :                 archputs(insertStmt->data, fout);
    2339                 : 
    2340 ECB             :             /*
    2341                 :              * If it is zero-column table then we've already written the
    2342                 :              * complete statement, which will mean we've disobeyed
    2343                 :              * --rows-per-insert when it's set greater than 1.  We do support
    2344                 :              * a way to make this multi-row with: SELECT UNION ALL SELECT
    2345                 :              * UNION ALL ... but that's non-standard so we should avoid it
    2346                 :              * given that using INSERTs is mostly only ever needed for
    2347                 :              * cross-database exports.
    2348                 :              */
    2349 CBC        3069 :             if (nfields == 0)
    2350               6 :                 continue;
    2351 ECB             : 
    2352                 :             /* Emit a row heading */
    2353 GIC        3063 :             if (rows_per_statement == 1)
    2354 CBC        3054 :                 archputs(" (", fout);
    2355               9 :             else if (rows_this_statement > 0)
    2356               6 :                 archputs(",\n\t(", fout);
    2357 ECB             :             else
    2358 CBC           3 :                 archputs("\n\t(", fout);
    2359 EUB             : 
    2360 GIC        9245 :             for (int field = 0; field < nfields; field++)
    2361 ECB             :             {
    2362 GIC        6182 :                 if (field > 0)
    2363            3119 :                     archputs(", ", fout);
    2364            6182 :                 if (attgenerated[field])
    2365 ECB             :                 {
    2366 GIC           2 :                     archputs("DEFAULT", fout);
    2367               2 :                     continue;
    2368                 :                 }
    2369 CBC        6180 :                 if (PQgetisnull(res, tuple, field))
    2370 ECB             :                 {
    2371 GBC          83 :                     archputs("NULL", fout);
    2372 GIC          83 :                     continue;
    2373                 :                 }
    2374                 : 
    2375                 :                 /* XXX This code is partially duplicated in ruleutils.c */
    2376            6097 :                 switch (PQftype(res, field))
    2377                 :                 {
    2378            4069 :                     case INT2OID:
    2379                 :                     case INT4OID:
    2380                 :                     case INT8OID:
    2381 ECB             :                     case OIDOID:
    2382                 :                     case FLOAT4OID:
    2383                 :                     case FLOAT8OID:
    2384                 :                     case NUMERICOID:
    2385                 :                         {
    2386                 :                             /*
    2387                 :                              * These types are printed without quotes unless
    2388                 :                              * they contain values that aren't accepted by the
    2389                 :                              * scanner unquoted (e.g., 'NaN').  Note that
    2390                 :                              * strtod() and friends might accept NaN, so we
    2391                 :                              * can't use that to test.
    2392                 :                              *
    2393                 :                              * In reality we only need to defend against
    2394                 :                              * infinity and NaN, so we need not get too crazy
    2395                 :                              * about pattern matching here.
    2396                 :                              */
    2397 CBC        4069 :                             const char *s = PQgetvalue(res, tuple, field);
    2398                 : 
    2399            4069 :                             if (strspn(s, "0123456789 +-eE.") == strlen(s))
    2400            4067 :                                 archputs(s, fout);
    2401                 :                             else
    2402 GIC           2 :                                 archprintf(fout, "'%s'", s);
    2403 ECB             :                         }
    2404 GIC        4069 :                         break;
    2405 ECB             : 
    2406 GIC           2 :                     case BITOID:
    2407                 :                     case VARBITOID:
    2408               2 :                         archprintf(fout, "B'%s'",
    2409                 :                                    PQgetvalue(res, tuple, field));
    2410 CBC           2 :                         break;
    2411                 : 
    2412               4 :                     case BOOLOID:
    2413               4 :                         if (strcmp(PQgetvalue(res, tuple, field), "t") == 0)
    2414 GIC           2 :                             archputs("true", fout);
    2415 ECB             :                         else
    2416 CBC           2 :                             archputs("false", fout);
    2417               4 :                         break;
    2418 ECB             : 
    2419 GIC        2022 :                     default:
    2420 ECB             :                         /* All other types are printed as string literals. */
    2421 GIC        2022 :                         resetPQExpBuffer(q);
    2422            2022 :                         appendStringLiteralAH(q,
    2423 ECB             :                                               PQgetvalue(res, tuple, field),
    2424                 :                                               fout);
    2425 GIC        2022 :                         archputs(q->data, fout);
    2426 CBC        2022 :                         break;
    2427                 :                 }
    2428                 :             }
    2429                 : 
    2430 ECB             :             /* Terminate the row ... */
    2431 GIC        3063 :             archputs(")", fout);
    2432                 : 
    2433 ECB             :             /* ... and the statement, if the target no. of rows is reached */
    2434 CBC        3063 :             if (++rows_this_statement >= rows_per_statement)
    2435                 :             {
    2436 GIC        3056 :                 if (dopt->do_nothing)
    2437 UIC           0 :                     archputs(" ON CONFLICT DO NOTHING;\n", fout);
    2438                 :                 else
    2439 GIC        3056 :                     archputs(";\n", fout);
    2440                 :                 /* Reset the row counter */
    2441            3056 :                 rows_this_statement = 0;
    2442                 :             }
    2443                 :         }
    2444                 : 
    2445 CBC         105 :         if (PQntuples(res) <= 0)
    2446 ECB             :         {
    2447 GIC          57 :             PQclear(res);
    2448              57 :             break;
    2449 ECB             :         }
    2450 CBC          48 :         PQclear(res);
    2451 ECB             :     }
    2452                 : 
    2453                 :     /* Terminate any statements that didn't make the row count. */
    2454 CBC          57 :     if (rows_this_statement > 0)
    2455                 :     {
    2456               1 :         if (dopt->do_nothing)
    2457 UIC           0 :             archputs(" ON CONFLICT DO NOTHING;\n", fout);
    2458 ECB             :         else
    2459 CBC           1 :             archputs(";\n", fout);
    2460 ECB             :     }
    2461                 : 
    2462 CBC          57 :     archputs("\n\n", fout);
    2463 ECB             : 
    2464 GIC          57 :     ExecuteSqlStatement(fout, "CLOSE _pg_dump_cursor");
    2465 ECB             : 
    2466 GIC          57 :     destroyPQExpBuffer(q);
    2467 CBC          57 :     if (insertStmt != NULL)
    2468              57 :         destroyPQExpBuffer(insertStmt);
    2469 GIC          57 :     free(attgenerated);
    2470                 : 
    2471              57 :     return 1;
    2472 ECB             : }
    2473                 : 
    2474                 : /*
    2475                 :  * getRootTableInfo:
    2476                 :  *     get the root TableInfo for the given partition table.
    2477                 :  */
    2478                 : static TableInfo *
    2479 GIC           9 : getRootTableInfo(const TableInfo *tbinfo)
    2480                 : {
    2481                 :     TableInfo  *parentTbinfo;
    2482                 : 
    2483               9 :     Assert(tbinfo->ispartition);
    2484               9 :     Assert(tbinfo->numParents == 1);
    2485                 : 
    2486               9 :     parentTbinfo = tbinfo->parents[0];
    2487               9 :     while (parentTbinfo->ispartition)
    2488                 :     {
    2489 UIC           0 :         Assert(parentTbinfo->numParents == 1);
    2490               0 :         parentTbinfo = parentTbinfo->parents[0];
    2491                 :     }
    2492                 : 
    2493 CBC           9 :     return parentTbinfo;
    2494                 : }
    2495 ECB             : 
    2496                 : /*
    2497                 :  * forcePartitionRootLoad
    2498                 :  *     Check if we must force load_via_partition_root for this partition.
    2499                 :  *
    2500                 :  * This is required if any level of ancestral partitioned table has an
    2501                 :  * unsafe partitioning scheme.
    2502                 :  */
    2503                 : static bool
    2504 CBC         865 : forcePartitionRootLoad(const TableInfo *tbinfo)
    2505                 : {
    2506 ECB             :     TableInfo  *parentTbinfo;
    2507                 : 
    2508 CBC         865 :     Assert(tbinfo->ispartition);
    2509             865 :     Assert(tbinfo->numParents == 1);
    2510 ECB             : 
    2511 GIC         865 :     parentTbinfo = tbinfo->parents[0];
    2512 CBC         865 :     if (parentTbinfo->unsafe_partitions)
    2513               9 :         return true;
    2514 GIC        1072 :     while (parentTbinfo->ispartition)
    2515 ECB             :     {
    2516 GIC         216 :         Assert(parentTbinfo->numParents == 1);
    2517 CBC         216 :         parentTbinfo = parentTbinfo->parents[0];
    2518             216 :         if (parentTbinfo->unsafe_partitions)
    2519 UIC           0 :             return true;
    2520                 :     }
    2521 ECB             : 
    2522 CBC         856 :     return false;
    2523                 : }
    2524                 : 
    2525                 : /*
    2526                 :  * dumpTableData -
    2527 ECB             :  *    dump the contents of a single table
    2528                 :  *
    2529                 :  * Actually, this just makes an ArchiveEntry for the table contents.
    2530                 :  */
    2531                 : static void
    2532 CBC        3095 : dumpTableData(Archive *fout, const TableDataInfo *tdinfo)
    2533 EUB             : {
    2534 GIC        3095 :     DumpOptions *dopt = fout->dopt;
    2535 CBC        3095 :     TableInfo  *tbinfo = tdinfo->tdtable;
    2536 GIC        3095 :     PQExpBuffer copyBuf = createPQExpBuffer();
    2537 CBC        3095 :     PQExpBuffer clistBuf = createPQExpBuffer();
    2538                 :     DataDumperPtr dumpFn;
    2539 GIC        3095 :     char       *tdDefn = NULL;
    2540                 :     char       *copyStmt;
    2541 ECB             :     const char *copyFrom;
    2542                 : 
    2543                 :     /* We had better have loaded per-column details about this table */
    2544 CBC        3095 :     Assert(tbinfo->interesting);
    2545                 : 
    2546 ECB             :     /*
    2547                 :      * When load-via-partition-root is set or forced, get the root table name
    2548                 :      * for the partition table, so that we can reload data through the root
    2549                 :      * table.  Then construct a comment to be inserted into the TOC entry's
    2550                 :      * defn field, so that such cases can be identified reliably.
    2551                 :      */
    2552 CBC        3095 :     if (tbinfo->ispartition &&
    2553 GBC        1698 :         (dopt->load_via_partition_root ||
    2554 GIC         849 :          forcePartitionRootLoad(tbinfo)))
    2555 CBC           6 :     {
    2556                 :         TableInfo  *parentTbinfo;
    2557                 : 
    2558               6 :         parentTbinfo = getRootTableInfo(tbinfo);
    2559 GIC           6 :         copyFrom = fmtQualifiedDumpable(parentTbinfo);
    2560 CBC           6 :         printfPQExpBuffer(copyBuf, "-- load via partition root %s",
    2561                 :                           copyFrom);
    2562               6 :         tdDefn = pg_strdup(copyBuf->data);
    2563 ECB             :     }
    2564                 :     else
    2565 CBC        3089 :         copyFrom = fmtQualifiedDumpable(tbinfo);
    2566                 : 
    2567            3095 :     if (dopt->dump_inserts == 0)
    2568                 :     {
    2569                 :         /* Dump/restore using COPY */
    2570 GIC        3038 :         dumpFn = dumpTableData_copy;
    2571                 :         /* must use 2 steps here 'cause fmtId is nonreentrant */
    2572            3038 :         printfPQExpBuffer(copyBuf, "COPY %s ",
    2573                 :                           copyFrom);
    2574            3038 :         appendPQExpBuffer(copyBuf, "%s FROM stdin;\n",
    2575 ECB             :                           fmtCopyColumnList(tbinfo, clistBuf));
    2576 GIC        3038 :         copyStmt = copyBuf->data;
    2577                 :     }
    2578                 :     else
    2579 ECB             :     {
    2580                 :         /* Restore using INSERT */
    2581 GIC          57 :         dumpFn = dumpTableData_insert;
    2582 CBC          57 :         copyStmt = NULL;
    2583 ECB             :     }
    2584                 : 
    2585 EUB             :     /*
    2586                 :      * Note: although the TableDataInfo is a full DumpableObject, we treat its
    2587                 :      * dependency on its table as "special" and pass it to ArchiveEntry now.
    2588                 :      * See comments for BuildArchiveDependencies.
    2589 ECB             :      */
    2590 GIC        3095 :     if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA)
    2591                 :     {
    2592                 :         TocEntry   *te;
    2593                 : 
    2594            3095 :         te = ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
    2595            3095 :                           ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
    2596                 :                                        .namespace = tbinfo->dobj.namespace->dobj.name,
    2597                 :                                        .owner = tbinfo->rolname,
    2598                 :                                        .description = "TABLE DATA",
    2599                 :                                        .section = SECTION_DATA,
    2600 ECB             :                                        .createStmt = tdDefn,
    2601                 :                                        .copyStmt = copyStmt,
    2602                 :                                        .deps = &(tbinfo->dobj.dumpId),
    2603                 :                                        .nDeps = 1,
    2604                 :                                        .dumpFn = dumpFn,
    2605                 :                                        .dumpArg = tdinfo));
    2606                 : 
    2607                 :         /*
    2608                 :          * Set the TocEntry's dataLength in case we are doing a parallel dump
    2609                 :          * and want to order dump jobs by table size.  We choose to measure
    2610                 :          * dataLength in table pages (including TOAST pages) during dump, so
    2611                 :          * no scaling is needed.
    2612                 :          *
    2613                 :          * However, relpages is declared as "integer" in pg_class, and hence
    2614                 :          * also in TableInfo, but it's really BlockNumber a/k/a unsigned int.
    2615 EUB             :          * Cast so that we get the right interpretation of table sizes
    2616                 :          * exceeding INT_MAX pages.
    2617                 :          */
    2618 CBC        3095 :         te->dataLength = (BlockNumber) tbinfo->relpages;
    2619 GIC        3095 :         te->dataLength += (BlockNumber) tbinfo->toastpages;
    2620                 : 
    2621                 :         /*
    2622                 :          * If pgoff_t is only 32 bits wide, the above refinement is useless,
    2623                 :          * and instead we'd better worry about integer overflow.  Clamp to
    2624                 :          * INT_MAX if the correct result exceeds that.
    2625                 :          */
    2626                 :         if (sizeof(te->dataLength) == 4 &&
    2627                 :             (tbinfo->relpages < 0 || tbinfo->toastpages < 0 ||
    2628 ECB             :              te->dataLength < 0))
    2629                 :             te->dataLength = INT_MAX;
    2630                 :     }
    2631                 : 
    2632 CBC        3095 :     destroyPQExpBuffer(copyBuf);
    2633            3095 :     destroyPQExpBuffer(clistBuf);
    2634 GIC        3095 : }
    2635 ECB             : 
    2636                 : /*
    2637                 :  * refreshMatViewData -
    2638                 :  *    load or refresh the contents of a single materialized view
    2639                 :  *
    2640                 :  * Actually, this just makes an ArchiveEntry for the REFRESH MATERIALIZED VIEW
    2641                 :  * statement.
    2642                 :  */
    2643                 : static void
    2644 GIC         328 : refreshMatViewData(Archive *fout, const TableDataInfo *tdinfo)
    2645                 : {
    2646             328 :     TableInfo  *tbinfo = tdinfo->tdtable;
    2647                 :     PQExpBuffer q;
    2648 ECB             : 
    2649                 :     /* If the materialized view is not flagged as populated, skip this. */
    2650 CBC         328 :     if (!tbinfo->relispopulated)
    2651              74 :         return;
    2652                 : 
    2653 GIC         254 :     q = createPQExpBuffer();
    2654 ECB             : 
    2655 CBC         254 :     appendPQExpBuffer(q, "REFRESH MATERIALIZED VIEW %s;\n",
    2656             254 :                       fmtQualifiedDumpable(tbinfo));
    2657                 : 
    2658             254 :     if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA)
    2659 GIC         254 :         ArchiveEntry(fout,
    2660                 :                      tdinfo->dobj.catId, /* catalog ID */
    2661 CBC         254 :                      tdinfo->dobj.dumpId,    /* dump ID */
    2662 GIC         254 :                      ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
    2663 ECB             :                                   .namespace = tbinfo->dobj.namespace->dobj.name,
    2664                 :                                   .owner = tbinfo->rolname,
    2665                 :                                   .description = "MATERIALIZED VIEW DATA",
    2666                 :                                   .section = SECTION_POST_DATA,
    2667                 :                                   .createStmt = q->data,
    2668                 :                                   .deps = tdinfo->dobj.dependencies,
    2669                 :                                   .nDeps = tdinfo->dobj.nDeps));
    2670                 : 
    2671 GIC         254 :     destroyPQExpBuffer(q);
    2672 ECB             : }
    2673                 : 
    2674                 : /*
    2675                 :  * getTableData -
    2676                 :  *    set up dumpable objects representing the contents of tables
    2677                 :  */
    2678                 : static void
    2679 GIC         116 : getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, char relkind)
    2680                 : {
    2681                 :     int         i;
    2682                 : 
    2683           30002 :     for (i = 0; i < numTables; i++)
    2684                 :     {
    2685           29886 :         if (tblinfo[i].dobj.dump & DUMP_COMPONENT_DATA &&
    2686 CBC         757 :             (!relkind || tblinfo[i].relkind == relkind))
    2687 GIC        4389 :             makeTableDataInfo(dopt, &(tblinfo[i]));
    2688                 :     }
    2689             116 : }
    2690 ECB             : 
    2691                 : /*
    2692                 :  * Make a dumpable object for the data of this specific table
    2693                 :  *
    2694                 :  * Note: we make a TableDataInfo if and only if we are going to dump the
    2695                 :  * table data; the "dump" field in such objects isn't very interesting.
    2696                 :  */
    2697                 : static void
    2698 GIC        4426 : makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo)
    2699                 : {
    2700                 :     TableDataInfo *tdinfo;
    2701                 : 
    2702                 :     /*
    2703                 :      * Nothing to do if we already decided to dump the table.  This will
    2704                 :      * happen for "config" tables.
    2705                 :      */
    2706            4426 :     if (tbinfo->dataObj != NULL)
    2707               1 :         return;
    2708                 : 
    2709                 :     /* Skip VIEWs (no data to dump) */
    2710            4425 :     if (tbinfo->relkind == RELKIND_VIEW)
    2711             225 :         return;
    2712                 :     /* Skip FOREIGN TABLEs (no data to dump) unless requested explicitly */
    2713            4200 :     if (tbinfo->relkind == RELKIND_FOREIGN_TABLE &&
    2714 CBC          41 :         (foreign_servers_include_oids.head == NULL ||
    2715               4 :          !simple_oid_list_member(&foreign_servers_include_oids,
    2716                 :                                  tbinfo->foreign_server)))
    2717 GIC          40 :         return;
    2718                 :     /* Skip partitioned tables (data in partitions) */
    2719            4160 :     if (tbinfo->relkind == RELKIND_PARTITIONED_TABLE)
    2720             390 :         return;
    2721                 : 
    2722                 :     /* Don't dump data in unlogged tables, if so requested */
    2723            3770 :     if (tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED &&
    2724               9 :         dopt->no_unlogged_table_data)
    2725               4 :         return;
    2726                 : 
    2727                 :     /* Check that the data is not explicitly excluded */
    2728 CBC        3766 :     if (simple_oid_list_member(&tabledata_exclude_oids,
    2729 ECB             :                                tbinfo->dobj.catId.oid))
    2730 CBC           5 :         return;
    2731                 : 
    2732                 :     /* OK, let's dump it */
    2733 GIC        3761 :     tdinfo = (TableDataInfo *) pg_malloc(sizeof(TableDataInfo));
    2734                 : 
    2735            3761 :     if (tbinfo->relkind == RELKIND_MATVIEW)
    2736             328 :         tdinfo->dobj.objType = DO_REFRESH_MATVIEW;
    2737            3433 :     else if (tbinfo->relkind == RELKIND_SEQUENCE)
    2738             338 :         tdinfo->dobj.objType = DO_SEQUENCE_SET;
    2739                 :     else
    2740 CBC        3095 :         tdinfo->dobj.objType = DO_TABLE_DATA;
    2741                 : 
    2742 ECB             :     /*
    2743                 :      * Note: use tableoid 0 so that this object won't be mistaken for
    2744                 :      * something that pg_depend entries apply to.
    2745                 :      */
    2746 CBC        3761 :     tdinfo->dobj.catId.tableoid = 0;
    2747            3761 :     tdinfo->dobj.catId.oid = tbinfo->dobj.catId.oid;
    2748 GIC        3761 :     AssignDumpId(&tdinfo->dobj);
    2749 CBC        3761 :     tdinfo->dobj.name = tbinfo->dobj.name;
    2750 GIC        3761 :     tdinfo->dobj.namespace = tbinfo->dobj.namespace;
    2751 CBC        3761 :     tdinfo->tdtable = tbinfo;
    2752            3761 :     tdinfo->filtercond = NULL;   /* might get set later */
    2753 GIC        3761 :     addObjectDependency(&tdinfo->dobj, tbinfo->dobj.dumpId);
    2754 ECB             : 
    2755                 :     /* A TableDataInfo contains data, of course */
    2756 GIC        3761 :     tdinfo->dobj.components |= DUMP_COMPONENT_DATA;
    2757 ECB             : 
    2758 CBC        3761 :     tbinfo->dataObj = tdinfo;
    2759                 : 
    2760                 :     /* Make sure that we'll collect per-column info for this table. */
    2761 GIC        3761 :     tbinfo->interesting = true;
    2762                 : }
    2763                 : 
    2764                 : /*
    2765                 :  * The refresh for a materialized view must be dependent on the refresh for
    2766                 :  * any materialized view that this one is dependent on.
    2767 ECB             :  *
    2768                 :  * This must be called after all the objects are created, but before they are
    2769                 :  * sorted.
    2770                 :  */
    2771                 : static void
    2772 GIC         108 : buildMatViewRefreshDependencies(Archive *fout)
    2773                 : {
    2774                 :     PQExpBuffer query;
    2775 ECB             :     PGresult   *res;
    2776                 :     int         ntups,
    2777                 :                 i;
    2778                 :     int         i_classid,
    2779                 :                 i_objid,
    2780                 :                 i_refobjid;
    2781                 : 
    2782                 :     /* No Mat Views before 9.3. */
    2783 CBC         108 :     if (fout->remoteVersion < 90300)
    2784 UIC           0 :         return;
    2785 ECB             : 
    2786 GIC         108 :     query = createPQExpBuffer();
    2787                 : 
    2788             108 :     appendPQExpBufferStr(query, "WITH RECURSIVE w AS "
    2789                 :                          "( "
    2790                 :                          "SELECT d1.objid, d2.refobjid, c2.relkind AS refrelkind "
    2791                 :                          "FROM pg_depend d1 "
    2792                 :                          "JOIN pg_class c1 ON c1.oid = d1.objid "
    2793                 :                          "AND c1.relkind = " CppAsString2(RELKIND_MATVIEW)
    2794 ECB             :                          " JOIN pg_rewrite r1 ON r1.ev_class = d1.objid "
    2795                 :                          "JOIN pg_depend d2 ON d2.classid = 'pg_rewrite'::regclass "
    2796                 :                          "AND d2.objid = r1.oid "
    2797                 :                          "AND d2.refobjid <> d1.objid "
    2798                 :                          "JOIN pg_class c2 ON c2.oid = d2.refobjid "
    2799                 :                          "AND c2.relkind IN (" CppAsString2(RELKIND_MATVIEW) ","
    2800                 :                          CppAsString2(RELKIND_VIEW) ") "
    2801                 :                          "WHERE d1.classid = 'pg_class'::regclass "
    2802                 :                          "UNION "
    2803                 :                          "SELECT w.objid, d3.refobjid, c3.relkind "
    2804                 :                          "FROM w "
    2805                 :                          "JOIN pg_rewrite r3 ON r3.ev_class = w.refobjid "
    2806                 :                          "JOIN pg_depend d3 ON d3.classid = 'pg_rewrite'::regclass "
    2807                 :                          "AND d3.objid = r3.oid "
    2808                 :                          "AND d3.refobjid <> w.refobjid "
    2809                 :                          "JOIN pg_class c3 ON c3.oid = d3.refobjid "
    2810                 :                          "AND c3.relkind IN (" CppAsString2(RELKIND_MATVIEW) ","
    2811                 :                          CppAsString2(RELKIND_VIEW) ") "
    2812                 :                          ") "
    2813                 :                          "SELECT 'pg_class'::regclass::oid AS classid, objid, refobjid "
    2814                 :                          "FROM w "
    2815                 :                          "WHERE refrelkind = " CppAsString2(RELKIND_MATVIEW));
    2816                 : 
    2817 GIC         108 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    2818                 : 
    2819 CBC         108 :     ntups = PQntuples(res);
    2820 ECB             : 
    2821 CBC         108 :     i_classid = PQfnumber(res, "classid");
    2822 GIC         108 :     i_objid = PQfnumber(res, "objid");
    2823             108 :     i_refobjid = PQfnumber(res, "refobjid");
    2824 ECB             : 
    2825 GIC         378 :     for (i = 0; i < ntups; i++)
    2826 ECB             :     {
    2827                 :         CatalogId   objId;
    2828                 :         CatalogId   refobjId;
    2829                 :         DumpableObject *dobj;
    2830                 :         DumpableObject *refdobj;
    2831                 :         TableInfo  *tbinfo;
    2832                 :         TableInfo  *reftbinfo;
    2833                 : 
    2834 CBC         270 :         objId.tableoid = atooid(PQgetvalue(res, i, i_classid));
    2835 GIC         270 :         objId.oid = atooid(PQgetvalue(res, i, i_objid));
    2836 CBC         270 :         refobjId.tableoid = objId.tableoid;
    2837 GIC         270 :         refobjId.oid = atooid(PQgetvalue(res, i, i_refobjid));
    2838                 : 
    2839             270 :         dobj = findObjectByCatalogId(objId);
    2840             270 :         if (dobj == NULL)
    2841              36 :             continue;
    2842 ECB             : 
    2843 CBC         270 :         Assert(dobj->objType == DO_TABLE);
    2844             270 :         tbinfo = (TableInfo *) dobj;
    2845             270 :         Assert(tbinfo->relkind == RELKIND_MATVIEW);
    2846             270 :         dobj = (DumpableObject *) tbinfo->dataObj;
    2847             270 :         if (dobj == NULL)
    2848              36 :             continue;
    2849             234 :         Assert(dobj->objType == DO_REFRESH_MATVIEW);
    2850                 : 
    2851 GIC         234 :         refdobj = findObjectByCatalogId(refobjId);
    2852 CBC         234 :         if (refdobj == NULL)
    2853 UIC           0 :             continue;
    2854 ECB             : 
    2855 GIC         234 :         Assert(refdobj->objType == DO_TABLE);
    2856             234 :         reftbinfo = (TableInfo *) refdobj;
    2857 CBC         234 :         Assert(reftbinfo->relkind == RELKIND_MATVIEW);
    2858 GIC         234 :         refdobj = (DumpableObject *) reftbinfo->dataObj;
    2859             234 :         if (refdobj == NULL)
    2860 UIC           0 :             continue;
    2861 GIC         234 :         Assert(refdobj->objType == DO_REFRESH_MATVIEW);
    2862                 : 
    2863             234 :         addObjectDependency(dobj, refdobj->dumpId);
    2864                 : 
    2865             234 :         if (!reftbinfo->relispopulated)
    2866              37 :             tbinfo->relispopulated = false;
    2867                 :     }
    2868 ECB             : 
    2869 GIC         108 :     PQclear(res);
    2870                 : 
    2871             108 :     destroyPQExpBuffer(query);
    2872                 : }
    2873                 : 
    2874                 : /*
    2875                 :  * getTableDataFKConstraints -
    2876                 :  *    add dump-order dependencies reflecting foreign key constraints
    2877                 :  *
    2878                 :  * This code is executed only in a data-only dump --- in schema+data dumps
    2879 ECB             :  * we handle foreign key issues by not creating the FK constraints until
    2880 EUB             :  * after the data is loaded.  In a data-only dump, however, we want to
    2881                 :  * order the table data objects in such a way that a table's referenced
    2882 ECB             :  * tables are restored first.  (In the presence of circular references or
    2883                 :  * self-references this may be impossible; we'll detect and complain about
    2884                 :  * that during the dependency sorting step.)
    2885                 :  */
    2886                 : static void
    2887 GIC           6 : getTableDataFKConstraints(void)
    2888                 : {
    2889                 :     DumpableObject **dobjs;
    2890                 :     int         numObjs;
    2891                 :     int         i;
    2892                 : 
    2893                 :     /* Search through all the dumpable objects for FK constraints */
    2894               6 :     getDumpableObjects(&dobjs, &numObjs);
    2895           25177 :     for (i = 0; i < numObjs; i++)
    2896                 :     {
    2897           25171 :         if (dobjs[i]->objType == DO_FK_CONSTRAINT)
    2898                 :         {
    2899               6 :             ConstraintInfo *cinfo = (ConstraintInfo *) dobjs[i];
    2900                 :             TableInfo  *ftable;
    2901                 : 
    2902                 :             /* Not interesting unless both tables are to be dumped */
    2903               6 :             if (cinfo->contable == NULL ||
    2904               6 :                 cinfo->contable->dataObj == NULL)
    2905               3 :                 continue;
    2906               3 :             ftable = findTableByOid(cinfo->confrelid);
    2907               3 :             if (ftable == NULL ||
    2908               3 :                 ftable->dataObj == NULL)
    2909 UIC           0 :                 continue;
    2910                 : 
    2911                 :             /*
    2912                 :              * Okay, make referencing table's TABLE_DATA object depend on the
    2913 ECB             :              * referenced table's TABLE_DATA object.
    2914                 :              */
    2915 CBC           3 :             addObjectDependency(&cinfo->contable->dataObj->dobj,
    2916 GIC           3 :                                 ftable->dataObj->dobj.dumpId);
    2917 ECB             :         }
    2918                 :     }
    2919 CBC           6 :     free(dobjs);
    2920 GIC           6 : }
    2921 ECB             : 
    2922                 : 
    2923                 : /*
    2924                 :  * dumpDatabase:
    2925                 :  *  dump the database definition
    2926                 :  */
    2927                 : static void
    2928 GIC          50 : dumpDatabase(Archive *fout)
    2929                 : {
    2930 CBC          50 :     DumpOptions *dopt = fout->dopt;
    2931              50 :     PQExpBuffer dbQry = createPQExpBuffer();
    2932              50 :     PQExpBuffer delQry = createPQExpBuffer();
    2933              50 :     PQExpBuffer creaQry = createPQExpBuffer();
    2934 GIC          50 :     PQExpBuffer labelq = createPQExpBuffer();
    2935 CBC          50 :     PGconn     *conn = GetConnection(fout);
    2936 ECB             :     PGresult   *res;
    2937                 :     int         i_tableoid,
    2938                 :                 i_oid,
    2939                 :                 i_datname,
    2940                 :                 i_datdba,
    2941                 :                 i_encoding,
    2942                 :                 i_datlocprovider,
    2943                 :                 i_collate,
    2944                 :                 i_ctype,
    2945                 :                 i_daticulocale,
    2946                 :                 i_daticurules,
    2947                 :                 i_frozenxid,
    2948                 :                 i_minmxid,
    2949                 :                 i_datacl,
    2950 EUB             :                 i_acldefault,
    2951                 :                 i_datistemplate,
    2952 ECB             :                 i_datconnlimit,
    2953                 :                 i_datcollversion,
    2954                 :                 i_tablespace;
    2955                 :     CatalogId   dbCatId;
    2956                 :     DumpId      dbDumpId;
    2957 EUB             :     DumpableAcl dbdacl;
    2958 ECB             :     const char *datname,
    2959                 :                *dba,
    2960                 :                *encoding,
    2961                 :                *datlocprovider,
    2962                 :                *collate,
    2963                 :                *ctype,
    2964                 :                *iculocale,
    2965                 :                *icurules,
    2966                 :                *datistemplate,
    2967                 :                *datconnlimit,
    2968                 :                *tablespace;
    2969                 :     uint32      frozenxid,
    2970                 :                 minmxid;
    2971                 :     char       *qdatname;
    2972                 : 
    2973 GIC          50 :     pg_log_info("saving database definition");
    2974                 : 
    2975                 :     /*
    2976                 :      * Fetch the database-level properties for this database.
    2977                 :      */
    2978 GNC          50 :     appendPQExpBufferStr(dbQry, "SELECT tableoid, oid, datname, "
    2979                 :                          "datdba, "
    2980                 :                          "pg_encoding_to_char(encoding) AS encoding, "
    2981                 :                          "datcollate, datctype, datfrozenxid, "
    2982                 :                          "datacl, acldefault('d', datdba) AS acldefault, "
    2983                 :                          "datistemplate, datconnlimit, ");
    2984 GIC          50 :     if (fout->remoteVersion >= 90300)
    2985 GNC          50 :         appendPQExpBufferStr(dbQry, "datminmxid, ");
    2986                 :     else
    2987 UNC           0 :         appendPQExpBufferStr(dbQry, "0 AS datminmxid, ");
    2988 GIC          50 :     if (fout->remoteVersion >= 150000)
    2989 GNC          50 :         appendPQExpBufferStr(dbQry, "datlocprovider, daticulocale, datcollversion, ");
    2990                 :     else
    2991 UNC           0 :         appendPQExpBufferStr(dbQry, "'c' AS datlocprovider, NULL AS daticulocale, NULL AS datcollversion, ");
    2992 GNC          50 :     if (fout->remoteVersion >= 160000)
    2993              50 :         appendPQExpBufferStr(dbQry, "daticurules, ");
    2994                 :     else
    2995 UNC           0 :         appendPQExpBufferStr(dbQry, "NULL AS daticurules, ");
    2996 GNC          50 :     appendPQExpBufferStr(dbQry,
    2997                 :                          "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
    2998                 :                          "shobj_description(oid, 'pg_database') AS description "
    2999                 :                          "FROM pg_database "
    3000                 :                          "WHERE datname = current_database()");
    3001 ECB             : 
    3002 GIC          50 :     res = ExecuteSqlQueryForSingleRow(fout, dbQry->data);
    3003                 : 
    3004              50 :     i_tableoid = PQfnumber(res, "tableoid");
    3005 CBC          50 :     i_oid = PQfnumber(res, "oid");
    3006              50 :     i_datname = PQfnumber(res, "datname");
    3007              50 :     i_datdba = PQfnumber(res, "datdba");
    3008              50 :     i_encoding = PQfnumber(res, "encoding");
    3009              50 :     i_datlocprovider = PQfnumber(res, "datlocprovider");
    3010              50 :     i_collate = PQfnumber(res, "datcollate");
    3011 GBC          50 :     i_ctype = PQfnumber(res, "datctype");
    3012 GIC          50 :     i_daticulocale = PQfnumber(res, "daticulocale");
    3013 GNC          50 :     i_daticurules = PQfnumber(res, "daticurules");
    3014 GIC          50 :     i_frozenxid = PQfnumber(res, "datfrozenxid");
    3015              50 :     i_minmxid = PQfnumber(res, "datminmxid");
    3016              50 :     i_datacl = PQfnumber(res, "datacl");
    3017              50 :     i_acldefault = PQfnumber(res, "acldefault");
    3018 CBC          50 :     i_datistemplate = PQfnumber(res, "datistemplate");
    3019              50 :     i_datconnlimit = PQfnumber(res, "datconnlimit");
    3020 GIC          50 :     i_datcollversion = PQfnumber(res, "datcollversion");
    3021              50 :     i_tablespace = PQfnumber(res, "tablespace");
    3022 ECB             : 
    3023 CBC          50 :     dbCatId.tableoid = atooid(PQgetvalue(res, 0, i_tableoid));
    3024 GIC          50 :     dbCatId.oid = atooid(PQgetvalue(res, 0, i_oid));
    3025              50 :     datname = PQgetvalue(res, 0, i_datname);
    3026              50 :     dba = getRoleName(PQgetvalue(res, 0, i_datdba));
    3027              50 :     encoding = PQgetvalue(res, 0, i_encoding);
    3028              50 :     datlocprovider = PQgetvalue(res, 0, i_datlocprovider);
    3029              50 :     collate = PQgetvalue(res, 0, i_collate);
    3030              50 :     ctype = PQgetvalue(res, 0, i_ctype);
    3031 CBC          50 :     if (!PQgetisnull(res, 0, i_daticulocale))
    3032 GIC          50 :         iculocale = PQgetvalue(res, 0, i_daticulocale);
    3033 ECB             :     else
    3034 LBC           0 :         iculocale = NULL;
    3035 GNC          50 :     if (!PQgetisnull(res, 0, i_daticurules))
    3036 UNC           0 :         icurules = PQgetvalue(res, 0, i_daticurules);
    3037                 :     else
    3038 GNC          50 :         icurules = NULL;
    3039 CBC          50 :     frozenxid = atooid(PQgetvalue(res, 0, i_frozenxid));
    3040              50 :     minmxid = atooid(PQgetvalue(res, 0, i_minmxid));
    3041              50 :     dbdacl.acl = PQgetvalue(res, 0, i_datacl);
    3042              50 :     dbdacl.acldefault = PQgetvalue(res, 0, i_acldefault);
    3043 GIC          50 :     datistemplate = PQgetvalue(res, 0, i_datistemplate);
    3044              50 :     datconnlimit = PQgetvalue(res, 0, i_datconnlimit);
    3045              50 :     tablespace = PQgetvalue(res, 0, i_tablespace);
    3046                 : 
    3047              50 :     qdatname = pg_strdup(fmtId(datname));
    3048                 : 
    3049                 :     /*
    3050                 :      * Prepare the CREATE DATABASE command.  We must specify OID (if we want
    3051                 :      * to preserve that), as well as the encoding, locale, and tablespace
    3052                 :      * since those can't be altered later.  Other DB properties are left to
    3053                 :      * the DATABASE PROPERTIES entry, so that they can be applied after
    3054                 :      * reconnecting to the target DB.
    3055                 :      */
    3056              50 :     if (dopt->binary_upgrade)
    3057                 :     {
    3058               7 :         appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0 OID = %u",
    3059                 :                           qdatname, dbCatId.oid);
    3060                 :     }
    3061                 :     else
    3062                 :     {
    3063              43 :         appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0",
    3064                 :                           qdatname);
    3065                 :     }
    3066              50 :     if (strlen(encoding) > 0)
    3067                 :     {
    3068              50 :         appendPQExpBufferStr(creaQry, " ENCODING = ");
    3069              50 :         appendStringLiteralAH(creaQry, encoding, fout);
    3070                 :     }
    3071                 : 
    3072              50 :     appendPQExpBufferStr(creaQry, " LOCALE_PROVIDER = ");
    3073              50 :     if (datlocprovider[0] == 'c')
    3074 UIC           0 :         appendPQExpBufferStr(creaQry, "libc");
    3075 GIC          50 :     else if (datlocprovider[0] == 'i')
    3076              50 :         appendPQExpBufferStr(creaQry, "icu");
    3077                 :     else
    3078 UIC           0 :         pg_fatal("unrecognized locale provider: %s",
    3079                 :                  datlocprovider);
    3080 ECB             : 
    3081 GIC          50 :     if (strlen(collate) > 0 && strcmp(collate, ctype) == 0)
    3082                 :     {
    3083              50 :         appendPQExpBufferStr(creaQry, " LOCALE = ");
    3084              50 :         appendStringLiteralAH(creaQry, collate, fout);
    3085 ECB             :     }
    3086                 :     else
    3087                 :     {
    3088 UIC           0 :         if (strlen(collate) > 0)
    3089                 :         {
    3090               0 :             appendPQExpBufferStr(creaQry, " LC_COLLATE = ");
    3091 LBC           0 :             appendStringLiteralAH(creaQry, collate, fout);
    3092 ECB             :         }
    3093 UIC           0 :         if (strlen(ctype) > 0)
    3094 EUB             :         {
    3095 LBC           0 :             appendPQExpBufferStr(creaQry, " LC_CTYPE = ");
    3096               0 :             appendStringLiteralAH(creaQry, ctype, fout);
    3097                 :         }
    3098 EUB             :     }
    3099 CBC          50 :     if (iculocale)
    3100 ECB             :     {
    3101 GIC          50 :         appendPQExpBufferStr(creaQry, " ICU_LOCALE = ");
    3102 GBC          50 :         appendStringLiteralAH(creaQry, iculocale, fout);
    3103 ECB             :     }
    3104 GNC          50 :     if (icurules)
    3105                 :     {
    3106 UNC           0 :         appendPQExpBufferStr(creaQry, " ICU_RULES = ");
    3107               0 :         appendStringLiteralAH(creaQry, icurules, fout);
    3108                 :     }
    3109                 : 
    3110                 :     /*
    3111                 :      * For binary upgrade, carry over the collation version.  For normal
    3112                 :      * dump/restore, omit the version, so that it is computed upon restore.
    3113                 :      */
    3114 CBC          50 :     if (dopt->binary_upgrade)
    3115                 :     {
    3116               7 :         if (!PQgetisnull(res, 0, i_datcollversion))
    3117 ECB             :         {
    3118 CBC           7 :             appendPQExpBufferStr(creaQry, " COLLATION_VERSION = ");
    3119               7 :             appendStringLiteralAH(creaQry,
    3120 ECB             :                                   PQgetvalue(res, 0, i_datcollversion),
    3121                 :                                   fout);
    3122                 :         }
    3123                 :     }
    3124                 : 
    3125                 :     /*
    3126                 :      * Note: looking at dopt->outputNoTablespaces here is completely the wrong
    3127                 :      * thing; the decision whether to specify a tablespace should be left till
    3128                 :      * pg_restore, so that pg_restore --no-tablespaces applies.  Ideally we'd
    3129                 :      * label the DATABASE entry with the tablespace and let the normal
    3130                 :      * tablespace selection logic work ... but CREATE DATABASE doesn't pay
    3131                 :      * attention to default_tablespace, so that won't work.
    3132                 :      */
    3133 CBC          50 :     if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0 &&
    3134 UIC           0 :         !dopt->outputNoTablespaces)
    3135 LBC           0 :         appendPQExpBuffer(creaQry, " TABLESPACE = %s",
    3136 ECB             :                           fmtId(tablespace));
    3137 CBC          50 :     appendPQExpBufferStr(creaQry, ";\n");
    3138 ECB             : 
    3139 CBC          50 :     appendPQExpBuffer(delQry, "DROP DATABASE %s;\n",
    3140 ECB             :                       qdatname);
    3141                 : 
    3142 CBC          50 :     dbDumpId = createDumpId();
    3143 ECB             : 
    3144 CBC          50 :     ArchiveEntry(fout,
    3145                 :                  dbCatId,       /* catalog ID */
    3146 EUB             :                  dbDumpId,      /* dump ID */
    3147 CBC          50 :                  ARCHIVE_OPTS(.tag = datname,
    3148 EUB             :                               .owner = dba,
    3149                 :                               .description = "DATABASE",
    3150 ECB             :                               .section = SECTION_PRE_DATA,
    3151                 :                               .createStmt = creaQry->data,
    3152                 :                               .dropStmt = delQry->data));
    3153                 : 
    3154                 :     /* Compute correct tag for archive entry */
    3155 CBC          50 :     appendPQExpBuffer(labelq, "DATABASE %s", qdatname);
    3156 ECB             : 
    3157                 :     /* Dump DB comment if any */
    3158                 :     {
    3159                 :         /*
    3160                 :          * 8.2 and up keep comments on shared objects in a shared table, so we
    3161                 :          * cannot use the dumpComment() code used for other database objects.
    3162                 :          * Be careful that the ArchiveEntry parameters match that function.
    3163                 :          */
    3164 GIC          50 :         char       *comment = PQgetvalue(res, 0, PQfnumber(res, "description"));
    3165                 : 
    3166              50 :         if (comment && *comment && !dopt->no_comments)
    3167                 :         {
    3168 CBC          20 :             resetPQExpBuffer(dbQry);
    3169                 : 
    3170 ECB             :             /*
    3171                 :              * Generates warning when loaded into a differently-named
    3172                 :              * database.
    3173                 :              */
    3174 GIC          20 :             appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", qdatname);
    3175 CBC          20 :             appendStringLiteralAH(dbQry, comment, fout);
    3176 GIC          20 :             appendPQExpBufferStr(dbQry, ";\n");
    3177                 : 
    3178 CBC          20 :             ArchiveEntry(fout, nilCatalogId, createDumpId(),
    3179 GIC          20 :                          ARCHIVE_OPTS(.tag = labelq->data,
    3180 ECB             :                                       .owner = dba,
    3181                 :                                       .description = "COMMENT",
    3182                 :                                       .section = SECTION_NONE,
    3183                 :                                       .createStmt = dbQry->data,
    3184                 :                                       .deps = &dbDumpId,
    3185                 :                                       .nDeps = 1));
    3186 EUB             :         }
    3187 ECB             :     }
    3188                 : 
    3189                 :     /* Dump DB security label, if enabled */
    3190 GBC          50 :     if (!dopt->no_security_labels)
    3191                 :     {
    3192                 :         PGresult   *shres;
    3193 ECB             :         PQExpBuffer seclabelQry;
    3194                 : 
    3195 CBC          50 :         seclabelQry = createPQExpBuffer();
    3196 ECB             : 
    3197 GIC          50 :         buildShSecLabelQuery("pg_database", dbCatId.oid, seclabelQry);
    3198              50 :         shres = ExecuteSqlQuery(fout, seclabelQry->data, PGRES_TUPLES_OK);
    3199              50 :         resetPQExpBuffer(seclabelQry);
    3200 GBC          50 :         emitShSecLabels(conn, shres, seclabelQry, "DATABASE", datname);
    3201 GIC          50 :         if (seclabelQry->len > 0)
    3202 UBC           0 :             ArchiveEntry(fout, nilCatalogId, createDumpId(),
    3203               0 :                          ARCHIVE_OPTS(.tag = labelq->data,
    3204                 :                                       .owner = dba,
    3205 EUB             :                                       .description = "SECURITY LABEL",
    3206                 :                                       .section = SECTION_NONE,
    3207                 :                                       .createStmt = seclabelQry->data,
    3208                 :                                       .deps = &dbDumpId,
    3209                 :                                       .nDeps = 1));
    3210 GIC          50 :         destroyPQExpBuffer(seclabelQry);
    3211 CBC          50 :         PQclear(shres);
    3212                 :     }
    3213 ECB             : 
    3214                 :     /*
    3215                 :      * Dump ACL if any.  Note that we do not support initial privileges
    3216                 :      * (pg_init_privs) on databases.
    3217                 :      */
    3218 GBC          50 :     dbdacl.privtype = 0;
    3219              50 :     dbdacl.initprivs = NULL;
    3220                 : 
    3221 GIC          50 :     dumpACL(fout, dbDumpId, InvalidDumpId, "DATABASE",
    3222                 :             qdatname, NULL, NULL,
    3223                 :             dba, &dbdacl);
    3224                 : 
    3225                 :     /*
    3226 ECB             :      * Now construct a DATABASE PROPERTIES archive entry to restore any
    3227                 :      * non-default database-level properties.  (The reason this must be
    3228                 :      * separate is that we cannot put any additional commands into the TOC
    3229                 :      * entry that has CREATE DATABASE.  pg_restore would execute such a group
    3230                 :      * in an implicit transaction block, and the backend won't allow CREATE
    3231                 :      * DATABASE in that context.)
    3232                 :      */
    3233 GIC          50 :     resetPQExpBuffer(creaQry);
    3234              50 :     resetPQExpBuffer(delQry);
    3235                 : 
    3236              50 :     if (strlen(datconnlimit) > 0 && strcmp(datconnlimit, "-1") != 0)
    3237 UIC           0 :         appendPQExpBuffer(creaQry, "ALTER DATABASE %s CONNECTION LIMIT = %s;\n",
    3238                 :                           qdatname, datconnlimit);
    3239                 : 
    3240 GIC          50 :     if (strcmp(datistemplate, "t") == 0)
    3241                 :     {
    3242               1 :         appendPQExpBuffer(creaQry, "ALTER DATABASE %s IS_TEMPLATE = true;\n",
    3243                 :                           qdatname);
    3244                 : 
    3245 ECB             :         /*
    3246 EUB             :          * The backend won't accept DROP DATABASE on a template database.  We
    3247                 :          * can deal with that by removing the template marking before the DROP
    3248                 :          * gets issued.  We'd prefer to use ALTER DATABASE IF EXISTS here, but
    3249 ECB             :          * since no such command is currently supported, fake it with a direct
    3250                 :          * UPDATE on pg_database.
    3251                 :          */
    3252 GIC           1 :         appendPQExpBufferStr(delQry, "UPDATE pg_catalog.pg_database "
    3253                 :                              "SET datistemplate = false WHERE datname = ");
    3254 CBC           1 :         appendStringLiteralAH(delQry, datname, fout);
    3255 GIC           1 :         appendPQExpBufferStr(delQry, ";\n");
    3256 ECB             :     }
    3257                 : 
    3258                 :     /* Add database-specific SET options */
    3259 CBC          50 :     dumpDatabaseConfig(fout, creaQry, datname, dbCatId.oid);
    3260                 : 
    3261                 :     /*
    3262                 :      * We stick this binary-upgrade query into the DATABASE PROPERTIES archive
    3263                 :      * entry, too, for lack of a better place.
    3264                 :      */
    3265 GIC          50 :     if (dopt->binary_upgrade)
    3266                 :     {
    3267 CBC           7 :         appendPQExpBufferStr(creaQry, "\n-- For binary upgrade, set datfrozenxid and datminmxid.\n");
    3268 GIC           7 :         appendPQExpBuffer(creaQry, "UPDATE pg_catalog.pg_database\n"
    3269                 :                           "SET datfrozenxid = '%u', datminmxid = '%u'\n"
    3270                 :                           "WHERE datname = ",
    3271                 :                           frozenxid, minmxid);
    3272               7 :         appendStringLiteralAH(creaQry, datname, fout);
    3273               7 :         appendPQExpBufferStr(creaQry, ";\n");
    3274                 :     }
    3275                 : 
    3276 CBC          50 :     if (creaQry->len > 0)
    3277 GIC          11 :         ArchiveEntry(fout, nilCatalogId, createDumpId(),
    3278 CBC          11 :                      ARCHIVE_OPTS(.tag = datname,
    3279                 :                                   .owner = dba,
    3280 ECB             :                                   .description = "DATABASE PROPERTIES",
    3281                 :                                   .section = SECTION_PRE_DATA,
    3282                 :                                   .createStmt = creaQry->data,
    3283                 :                                   .dropStmt = delQry->data,
    3284                 :                                   .deps = &dbDumpId));
    3285                 : 
    3286                 :     /*
    3287                 :      * pg_largeobject comes from the old system intact, so set its
    3288                 :      * relfrozenxids, relminmxids and relfilenode.
    3289                 :      */
    3290 CBC          50 :     if (dopt->binary_upgrade)
    3291 ECB             :     {
    3292                 :         PGresult   *lo_res;
    3293 GIC           7 :         PQExpBuffer loFrozenQry = createPQExpBuffer();
    3294               7 :         PQExpBuffer loOutQry = createPQExpBuffer();
    3295               7 :         PQExpBuffer loHorizonQry = createPQExpBuffer();
    3296                 :         int         ii_relfrozenxid,
    3297                 :                     ii_relfilenode,
    3298                 :                     ii_oid,
    3299                 :                     ii_relminmxid;
    3300                 : 
    3301                 :         /*
    3302 ECB             :          * pg_largeobject
    3303                 :          */
    3304 GIC           7 :         if (fout->remoteVersion >= 90300)
    3305               7 :             appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid, relminmxid, relfilenode, oid\n"
    3306                 :                               "FROM pg_catalog.pg_class\n"
    3307 ECB             :                               "WHERE oid IN (%u, %u);\n",
    3308                 :                               LargeObjectRelationId, LargeObjectLOidPNIndexId);
    3309                 :         else
    3310 LBC           0 :             appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid, 0 AS relminmxid, relfilenode, oid\n"
    3311 ECB             :                               "FROM pg_catalog.pg_class\n"
    3312                 :                               "WHERE oid IN (%u, %u);\n",
    3313                 :                               LargeObjectRelationId, LargeObjectLOidPNIndexId);
    3314 EUB             : 
    3315 GBC           7 :         lo_res = ExecuteSqlQuery(fout, loFrozenQry->data, PGRES_TUPLES_OK);
    3316                 : 
    3317 GIC           7 :         ii_relfrozenxid = PQfnumber(lo_res, "relfrozenxid");
    3318               7 :         ii_relminmxid = PQfnumber(lo_res, "relminmxid");
    3319               7 :         ii_relfilenode = PQfnumber(lo_res, "relfilenode");
    3320               7 :         ii_oid = PQfnumber(lo_res, "oid");
    3321                 : 
    3322 CBC           7 :         appendPQExpBufferStr(loHorizonQry, "\n-- For binary upgrade, set pg_largeobject relfrozenxid and relminmxid\n");
    3323               7 :         appendPQExpBufferStr(loOutQry, "\n-- For binary upgrade, preserve pg_largeobject and index relfilenodes\n");
    3324 GIC          21 :         for (int i = 0; i < PQntuples(lo_res); ++i)
    3325                 :         {
    3326                 :             Oid     oid;
    3327                 :             RelFileNumber   relfilenumber;
    3328                 : 
    3329              14 :             appendPQExpBuffer(loHorizonQry, "UPDATE pg_catalog.pg_class\n"
    3330 ECB             :                               "SET relfrozenxid = '%u', relminmxid = '%u'\n"
    3331                 :                               "WHERE oid = %u;\n",
    3332 GIC          14 :                               atooid(PQgetvalue(lo_res, i, ii_relfrozenxid)),
    3333 CBC          14 :                               atooid(PQgetvalue(lo_res, i, ii_relminmxid)),
    3334 GIC          14 :                               atooid(PQgetvalue(lo_res, i, ii_oid)));
    3335                 : 
    3336              14 :             oid = atooid(PQgetvalue(lo_res, i, ii_oid));
    3337 GNC          14 :             relfilenumber = atooid(PQgetvalue(lo_res, i, ii_relfilenode));
    3338                 : 
    3339 GIC          14 :             if (oid == LargeObjectRelationId)
    3340               7 :                 appendPQExpBuffer(loOutQry,
    3341                 :                                   "SELECT pg_catalog.binary_upgrade_set_next_heap_relfilenode('%u'::pg_catalog.oid);\n",
    3342                 :                                   relfilenumber);
    3343               7 :             else if (oid == LargeObjectLOidPNIndexId)
    3344               7 :                 appendPQExpBuffer(loOutQry,
    3345 ECB             :                                   "SELECT pg_catalog.binary_upgrade_set_next_index_relfilenode('%u'::pg_catalog.oid);\n",
    3346                 :                                   relfilenumber);
    3347                 :         }
    3348                 : 
    3349 GBC           7 :         appendPQExpBufferStr(loOutQry,
    3350                 :                              "TRUNCATE pg_catalog.pg_largeobject;\n");
    3351 GIC           7 :         appendPQExpBufferStr(loOutQry, loHorizonQry->data);
    3352 ECB             : 
    3353 GIC           7 :         ArchiveEntry(fout, nilCatalogId, createDumpId(),
    3354 CBC           7 :                      ARCHIVE_OPTS(.tag = "pg_largeobject",
    3355                 :                                   .description = "pg_largeobject",
    3356                 :                                   .section = SECTION_PRE_DATA,
    3357                 :                                   .createStmt = loOutQry->data));
    3358                 : 
    3359 GIC           7 :         PQclear(lo_res);
    3360                 : 
    3361               7 :         destroyPQExpBuffer(loFrozenQry);
    3362               7 :         destroyPQExpBuffer(loHorizonQry);
    3363               7 :         destroyPQExpBuffer(loOutQry);
    3364 ECB             :     }
    3365                 : 
    3366 CBC          50 :     PQclear(res);
    3367 ECB             : 
    3368 GIC          50 :     free(qdatname);
    3369              50 :     destroyPQExpBuffer(dbQry);
    3370              50 :     destroyPQExpBuffer(delQry);
    3371 CBC          50 :     destroyPQExpBuffer(creaQry);
    3372 GIC          50 :     destroyPQExpBuffer(labelq);
    3373              50 : }
    3374                 : 
    3375                 : /*
    3376                 :  * Collect any database-specific or role-and-database-specific SET options
    3377 ECB             :  * for this database, and append them to outbuf.
    3378                 :  */
    3379                 : static void
    3380 CBC          50 : dumpDatabaseConfig(Archive *AH, PQExpBuffer outbuf,
    3381                 :                    const char *dbname, Oid dboid)
    3382                 : {
    3383 GIC          50 :     PGconn     *conn = GetConnection(AH);
    3384 CBC          50 :     PQExpBuffer buf = createPQExpBuffer();
    3385 ECB             :     PGresult   *res;
    3386                 : 
    3387                 :     /* First collect database-specific options */
    3388 GNC          50 :     printfPQExpBuffer(buf, "SELECT unnest(setconfig)");
    3389              50 :     if (AH->remoteVersion >= 160000)
    3390              50 :         appendPQExpBufferStr(buf, ", unnest(setuser)");
    3391              50 :     appendPQExpBuffer(buf, " FROM pg_db_role_setting "
    3392 ECB             :                       "WHERE setrole = 0 AND setdatabase = '%u'::oid",
    3393                 :                       dboid);
    3394                 : 
    3395 GIC          50 :     res = ExecuteSqlQuery(AH, buf->data, PGRES_TUPLES_OK);
    3396                 : 
    3397              80 :     for (int i = 0; i < PQntuples(res); i++)
    3398                 :     {
    3399 GNC          30 :         char       *userset = NULL;
    3400                 : 
    3401              30 :         if (AH->remoteVersion >= 160000)
    3402              30 :             userset = PQgetvalue(res, i, 1);
    3403              30 :         makeAlterConfigCommand(conn, PQgetvalue(res, i, 0), userset,
    3404                 :                                "DATABASE", dbname, NULL, NULL,
    3405                 :                                outbuf);
    3406                 :     }
    3407                 : 
    3408 GIC          50 :     PQclear(res);
    3409                 : 
    3410                 :     /* Now look for role-and-database-specific options */
    3411 GNC          50 :     printfPQExpBuffer(buf, "SELECT rolname, unnest(setconfig)");
    3412              50 :     if (AH->remoteVersion >= 160000)
    3413              50 :         appendPQExpBufferStr(buf, ", unnest(setuser)");
    3414              50 :     appendPQExpBuffer(buf, " FROM pg_db_role_setting s, pg_roles r "
    3415                 :                       "WHERE setrole = r.oid AND setdatabase = '%u'::oid",
    3416 ECB             :                       dboid);
    3417                 : 
    3418 CBC          50 :     res = ExecuteSqlQuery(AH, buf->data, PGRES_TUPLES_OK);
    3419                 : 
    3420 GIC          50 :     for (int i = 0; i < PQntuples(res); i++)
    3421                 :     {
    3422 UNC           0 :         char       *userset = NULL;
    3423                 : 
    3424               0 :         if (AH->remoteVersion >= 160000)
    3425               0 :             userset = PQgetvalue(res, i, 2);
    3426               0 :         makeAlterConfigCommand(conn, PQgetvalue(res, i, 1), userset,
    3427 UIC           0 :                                "ROLE", PQgetvalue(res, i, 0),
    3428                 :                                "DATABASE", dbname,
    3429                 :                                outbuf);
    3430                 :     }
    3431                 : 
    3432 GIC          50 :     PQclear(res);
    3433 ECB             : 
    3434 CBC          50 :     destroyPQExpBuffer(buf);
    3435 GIC          50 : }
    3436                 : 
    3437                 : /*
    3438                 :  * dumpEncoding: put the correct encoding into the archive
    3439 EUB             :  */
    3440                 : static void
    3441 GIC         118 : dumpEncoding(Archive *AH)
    3442                 : {
    3443             118 :     const char *encname = pg_encoding_to_char(AH->encoding);
    3444 CBC         118 :     PQExpBuffer qry = createPQExpBuffer();
    3445                 : 
    3446             118 :     pg_log_info("saving encoding = %s", encname);
    3447 ECB             : 
    3448 CBC         118 :     appendPQExpBufferStr(qry, "SET client_encoding = ");
    3449             118 :     appendStringLiteralAH(qry, encname, AH);
    3450 GIC         118 :     appendPQExpBufferStr(qry, ";\n");
    3451 ECB             : 
    3452 CBC         118 :     ArchiveEntry(AH, nilCatalogId, createDumpId(),
    3453             118 :                  ARCHIVE_OPTS(.tag = "ENCODING",
    3454                 :                               .description = "ENCODING",
    3455                 :                               .section = SECTION_PRE_DATA,
    3456                 :                               .createStmt = qry->data));
    3457                 : 
    3458             118 :     destroyPQExpBuffer(qry);
    3459 GIC         118 : }
    3460                 : 
    3461 ECB             : 
    3462                 : /*
    3463                 :  * dumpStdStrings: put the correct escape string behavior into the archive
    3464                 :  */
    3465                 : static void
    3466 CBC         118 : dumpStdStrings(Archive *AH)
    3467                 : {
    3468             118 :     const char *stdstrings = AH->std_strings ? "on" : "off";
    3469             118 :     PQExpBuffer qry = createPQExpBuffer();
    3470                 : 
    3471 GIC         118 :     pg_log_info("saving standard_conforming_strings = %s",
    3472 ECB             :                 stdstrings);
    3473                 : 
    3474 GIC         118 :     appendPQExpBuffer(qry, "SET standard_conforming_strings = '%s';\n",
    3475                 :                       stdstrings);
    3476                 : 
    3477             118 :     ArchiveEntry(AH, nilCatalogId, createDumpId(),
    3478 CBC         118 :                  ARCHIVE_OPTS(.tag = "STDSTRINGS",
    3479                 :                               .description = "STDSTRINGS",
    3480 ECB             :                               .section = SECTION_PRE_DATA,
    3481                 :                               .createStmt = qry->data));
    3482                 : 
    3483 CBC         118 :     destroyPQExpBuffer(qry);
    3484 GIC         118 : }
    3485                 : 
    3486                 : /*
    3487                 :  * dumpSearchPath: record the active search_path in the archive
    3488 ECB             :  */
    3489                 : static void
    3490 CBC         118 : dumpSearchPath(Archive *AH)
    3491 ECB             : {
    3492 CBC         118 :     PQExpBuffer qry = createPQExpBuffer();
    3493 GIC         118 :     PQExpBuffer path = createPQExpBuffer();
    3494                 :     PGresult   *res;
    3495 CBC         118 :     char      **schemanames = NULL;
    3496 GIC         118 :     int         nschemanames = 0;
    3497 ECB             :     int         i;
    3498                 : 
    3499                 :     /*
    3500                 :      * We use the result of current_schemas(), not the search_path GUC,
    3501                 :      * because that might contain wildcards such as "$user", which won't
    3502                 :      * necessarily have the same value during restore.  Also, this way avoids
    3503                 :      * listing schemas that may appear in search_path but not actually exist,
    3504                 :      * which seems like a prudent exclusion.
    3505                 :      */
    3506 GIC         118 :     res = ExecuteSqlQueryForSingleRow(AH,
    3507                 :                                       "SELECT pg_catalog.current_schemas(false)");
    3508                 : 
    3509 CBC         118 :     if (!parsePGArray(PQgetvalue(res, 0, 0), &schemanames, &nschemanames))
    3510 UIC           0 :         pg_fatal("could not parse result of current_schemas()");
    3511                 : 
    3512 ECB             :     /*
    3513                 :      * We use set_config(), not a simple "SET search_path" command, because
    3514                 :      * the latter has less-clean behavior if the search path is empty.  While
    3515                 :      * that's likely to get fixed at some point, it seems like a good idea to
    3516                 :      * be as backwards-compatible as possible in what we put into archives.
    3517                 :      */
    3518 CBC         118 :     for (i = 0; i < nschemanames; i++)
    3519 ECB             :     {
    3520 LBC           0 :         if (i > 0)
    3521 UIC           0 :             appendPQExpBufferStr(path, ", ");
    3522               0 :         appendPQExpBufferStr(path, fmtId(schemanames[i]));
    3523                 :     }
    3524 ECB             : 
    3525 GIC         118 :     appendPQExpBufferStr(qry, "SELECT pg_catalog.set_config('search_path', ");
    3526 CBC         118 :     appendStringLiteralAH(qry, path->data, AH);
    3527 GIC         118 :     appendPQExpBufferStr(qry, ", false);\n");
    3528 ECB             : 
    3529 GIC         118 :     pg_log_info("saving search_path = %s", path->data);
    3530 ECB             : 
    3531 CBC         118 :     ArchiveEntry(AH, nilCatalogId, createDumpId(),
    3532             118 :                  ARCHIVE_OPTS(.tag = "SEARCHPATH",
    3533                 :                               .description = "SEARCHPATH",
    3534                 :                               .section = SECTION_PRE_DATA,
    3535                 :                               .createStmt = qry->data));
    3536                 : 
    3537 ECB             :     /* Also save it in AH->searchpath, in case we're doing plain text dump */
    3538 GIC         118 :     AH->searchpath = pg_strdup(qry->data);
    3539                 : 
    3540 GNC         118 :     free(schemanames);
    3541 CBC         118 :     PQclear(res);
    3542             118 :     destroyPQExpBuffer(qry);
    3543 GIC         118 :     destroyPQExpBuffer(path);
    3544             118 : }
    3545                 : 
    3546 ECB             : 
    3547                 : /*
    3548                 :  * getLOs:
    3549                 :  *  Collect schema-level data about large objects
    3550 EUB             :  */
    3551                 : static void
    3552 GNC         104 : getLOs(Archive *fout)
    3553 EUB             : {
    3554 GBC         104 :     DumpOptions *dopt = fout->dopt;
    3555 GNC         104 :     PQExpBuffer loQry = createPQExpBuffer();
    3556                 :     LoInfo     *loinfo;
    3557                 :     DumpableObject *lodata;
    3558                 :     PGresult   *res;
    3559                 :     int         ntups;
    3560 ECB             :     int         i;
    3561                 :     int         i_oid;
    3562                 :     int         i_lomowner;
    3563                 :     int         i_lomacl;
    3564                 :     int         i_acldefault;
    3565                 : 
    3566 GIC         104 :     pg_log_info("reading large objects");
    3567                 : 
    3568                 :     /* Fetch LO OIDs, and owner/ACL data */
    3569 GNC         104 :     appendPQExpBufferStr(loQry,
    3570                 :                          "SELECT oid, lomowner, lomacl, "
    3571                 :                          "acldefault('L', lomowner) AS acldefault "
    3572                 :                          "FROM pg_largeobject_metadata");
    3573                 : 
    3574             104 :     res = ExecuteSqlQuery(fout, loQry->data, PGRES_TUPLES_OK);
    3575                 : 
    3576 CBC         104 :     i_oid = PQfnumber(res, "oid");
    3577             104 :     i_lomowner = PQfnumber(res, "lomowner");
    3578             104 :     i_lomacl = PQfnumber(res, "lomacl");
    3579 GIC         104 :     i_acldefault = PQfnumber(res, "acldefault");
    3580 ECB             : 
    3581 CBC         104 :     ntups = PQntuples(res);
    3582                 : 
    3583                 :     /*
    3584                 :      * Each large object has its own "BLOB" archive entry.
    3585                 :      */
    3586 GNC         104 :     loinfo = (LoInfo *) pg_malloc(ntups * sizeof(LoInfo));
    3587 ECB             : 
    3588 GIC         193 :     for (i = 0; i < ntups; i++)
    3589                 :     {
    3590 GNC          89 :         loinfo[i].dobj.objType = DO_LARGE_OBJECT;
    3591              89 :         loinfo[i].dobj.catId.tableoid = LargeObjectRelationId;
    3592              89 :         loinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    3593              89 :         AssignDumpId(&loinfo[i].dobj);
    3594 ECB             : 
    3595 GNC          89 :         loinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_oid));
    3596              89 :         loinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_lomacl));
    3597              89 :         loinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
    3598              89 :         loinfo[i].dacl.privtype = 0;
    3599              89 :         loinfo[i].dacl.initprivs = NULL;
    3600              89 :         loinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_lomowner));
    3601                 : 
    3602                 :         /* LOs have data */
    3603              89 :         loinfo[i].dobj.components |= DUMP_COMPONENT_DATA;
    3604                 : 
    3605                 :         /* Mark whether LO has an ACL */
    3606 CBC          89 :         if (!PQgetisnull(res, i, i_lomacl))
    3607 GNC          37 :             loinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
    3608                 : 
    3609                 :         /*
    3610                 :          * In binary-upgrade mode for LOs, we do *not* dump out the LO
    3611 ECB             :          * data, as it will be copied by pg_upgrade, which simply copies the
    3612                 :          * pg_largeobject table. We *do* however dump out anything but the
    3613                 :          * data, as pg_upgrade copies just pg_largeobject, but not
    3614                 :          * pg_largeobject_metadata, after the dump is restored.
    3615                 :          */
    3616 GIC          89 :         if (dopt->binary_upgrade)
    3617 GNC           5 :             loinfo[i].dobj.dump &= ~DUMP_COMPONENT_DATA;
    3618 ECB             :     }
    3619                 : 
    3620                 :     /*
    3621                 :      * If we have any large objects, a "BLOBS" archive entry is needed. This
    3622                 :      * is just a placeholder for sorting; it carries no data now.
    3623                 :      */
    3624 CBC         104 :     if (ntups > 0)
    3625                 :     {
    3626 GNC          42 :         lodata = (DumpableObject *) pg_malloc(sizeof(DumpableObject));
    3627              42 :         lodata->objType = DO_LARGE_OBJECT_DATA;
    3628              42 :         lodata->catId = nilCatalogId;
    3629              42 :         AssignDumpId(lodata);
    3630              42 :         lodata->name = pg_strdup("BLOBS");
    3631              42 :         lodata->components |= DUMP_COMPONENT_DATA;
    3632                 :     }
    3633                 : 
    3634 CBC         104 :     PQclear(res);
    3635 GNC         104 :     destroyPQExpBuffer(loQry);
    3636 GIC         104 : }
    3637 ECB             : 
    3638 EUB             : /*
    3639                 :  * dumpLO
    3640                 :  *
    3641                 :  * dump the definition (metadata) of the given large object
    3642                 :  */
    3643                 : static void
    3644 GNC          89 : dumpLO(Archive *fout, const LoInfo *loinfo)
    3645                 : {
    3646 CBC          89 :     PQExpBuffer cquery = createPQExpBuffer();
    3647 GIC          89 :     PQExpBuffer dquery = createPQExpBuffer();
    3648 EUB             : 
    3649 GBC          89 :     appendPQExpBuffer(cquery,
    3650 EUB             :                       "SELECT pg_catalog.lo_create('%s');\n",
    3651 GNC          89 :                       loinfo->dobj.name);
    3652                 : 
    3653 CBC          89 :     appendPQExpBuffer(dquery,
    3654 ECB             :                       "SELECT pg_catalog.lo_unlink('%s');\n",
    3655 GNC          89 :                       loinfo->dobj.name);
    3656                 : 
    3657              89 :     if (loinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
    3658              89 :         ArchiveEntry(fout, loinfo->dobj.catId, loinfo->dobj.dumpId,
    3659              89 :                      ARCHIVE_OPTS(.tag = loinfo->dobj.name,
    3660                 :                                   .owner = loinfo->rolname,
    3661                 :                                   .description = "BLOB",
    3662                 :                                   .section = SECTION_PRE_DATA,
    3663                 :                                   .createStmt = cquery->data,
    3664                 :                                   .dropStmt = dquery->data));
    3665                 : 
    3666 ECB             :     /* Dump comment if any */
    3667 GNC          89 :     if (loinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
    3668              47 :         dumpComment(fout, "LARGE OBJECT", loinfo->dobj.name,
    3669              47 :                     NULL, loinfo->rolname,
    3670              47 :                     loinfo->dobj.catId, 0, loinfo->dobj.dumpId);
    3671 ECB             : 
    3672                 :     /* Dump security label if any */
    3673 GNC          89 :     if (loinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
    3674 UNC           0 :         dumpSecLabel(fout, "LARGE OBJECT", loinfo->dobj.name,
    3675               0 :                      NULL, loinfo->rolname,
    3676               0 :                      loinfo->dobj.catId, 0, loinfo->dobj.dumpId);
    3677                 : 
    3678                 :     /* Dump ACL if any */
    3679 GNC          89 :     if (loinfo->dobj.dump & DUMP_COMPONENT_ACL)
    3680              37 :         dumpACL(fout, loinfo->dobj.dumpId, InvalidDumpId, "LARGE OBJECT",
    3681              37 :                 loinfo->dobj.name, NULL,
    3682              37 :                 NULL, loinfo->rolname, &loinfo->dacl);
    3683 ECB             : 
    3684 GIC          89 :     destroyPQExpBuffer(cquery);
    3685              89 :     destroyPQExpBuffer(dquery);
    3686              89 : }
    3687                 : 
    3688                 : /*
    3689                 :  * dumpLOs:
    3690                 :  *  dump the data contents of all large objects
    3691                 :  */
    3692                 : static int
    3693 GNC          38 : dumpLOs(Archive *fout, const void *arg)
    3694 ECB             : {
    3695                 :     const char *loQry;
    3696                 :     const char *loFetchQry;
    3697 CBC          38 :     PGconn     *conn = GetConnection(fout);
    3698                 :     PGresult   *res;
    3699                 :     char        buf[LOBBUFSIZE];
    3700                 :     int         ntups;
    3701                 :     int         i;
    3702 ECB             :     int         cnt;
    3703                 : 
    3704 CBC          38 :     pg_log_info("saving large objects");
    3705 ECB             : 
    3706                 :     /*
    3707                 :      * Currently, we re-fetch all LO OIDs using a cursor.  Consider scanning
    3708                 :      * the already-in-memory dumpable objects instead...
    3709                 :      */
    3710 GNC          38 :     loQry =
    3711                 :         "DECLARE looid CURSOR FOR "
    3712                 :         "SELECT oid FROM pg_largeobject_metadata ORDER BY 1";
    3713                 : 
    3714              38 :     ExecuteSqlStatement(fout, loQry);
    3715                 : 
    3716 ECB             :     /* Command to fetch from cursor */
    3717 GNC          38 :     loFetchQry = "FETCH 1000 IN looid";
    3718 ECB             : 
    3719                 :     do
    3720                 :     {
    3721                 :         /* Do a fetch */
    3722 GNC          76 :         res = ExecuteSqlQuery(fout, loFetchQry, PGRES_TUPLES_OK);
    3723 ECB             : 
    3724                 :         /* Process the tuples, if any */
    3725 CBC          76 :         ntups = PQntuples(res);
    3726             156 :         for (i = 0; i < ntups; i++)
    3727 ECB             :         {
    3728                 :             Oid         loOid;
    3729                 :             int         loFd;
    3730                 : 
    3731 GNC          80 :             loOid = atooid(PQgetvalue(res, i, 0));
    3732                 :             /* Open the LO */
    3733              80 :             loFd = lo_open(conn, loOid, INV_READ);
    3734 CBC          80 :             if (loFd == -1)
    3735 LBC           0 :                 pg_fatal("could not open large object %u: %s",
    3736                 :                          loOid, PQerrorMessage(conn));
    3737                 : 
    3738 GNC          80 :             StartLO(fout, loOid);
    3739                 : 
    3740                 :             /* Now read it in chunks, sending data to archive */
    3741                 :             do
    3742                 :             {
    3743 GIC         122 :                 cnt = lo_read(conn, loFd, buf, LOBBUFSIZE);
    3744 CBC         122 :                 if (cnt < 0)
    3745 LBC           0 :                     pg_fatal("error reading large object %u: %s",
    3746                 :                              loOid, PQerrorMessage(conn));
    3747                 : 
    3748 GIC         122 :                 WriteData(fout, buf, cnt);
    3749             122 :             } while (cnt > 0);
    3750                 : 
    3751              80 :             lo_close(conn, loFd);
    3752 ECB             : 
    3753 GNC          80 :             EndLO(fout, loOid);
    3754 ECB             :         }
    3755                 : 
    3756 CBC          76 :         PQclear(res);
    3757              76 :     } while (ntups > 0);
    3758 ECB             : 
    3759 CBC          38 :     return 1;
    3760                 : }
    3761                 : 
    3762 ECB             : /*
    3763                 :  * getPolicies
    3764                 :  *    get information about all RLS policies on dumpable tables.
    3765                 :  */
    3766                 : void
    3767 GIC         118 : getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
    3768                 : {
    3769                 :     PQExpBuffer query;
    3770                 :     PQExpBuffer tbloids;
    3771                 :     PGresult   *res;
    3772 ECB             :     PolicyInfo *polinfo;
    3773                 :     int         i_oid;
    3774                 :     int         i_tableoid;
    3775                 :     int         i_polrelid;
    3776                 :     int         i_polname;
    3777                 :     int         i_polcmd;
    3778                 :     int         i_polpermissive;
    3779                 :     int         i_polroles;
    3780                 :     int         i_polqual;
    3781                 :     int         i_polwithcheck;
    3782                 :     int         i,
    3783                 :                 j,
    3784                 :                 ntups;
    3785                 : 
    3786                 :     /* No policies before 9.5 */
    3787 CBC         118 :     if (fout->remoteVersion < 90500)
    3788 UIC           0 :         return;
    3789                 : 
    3790 GIC         118 :     query = createPQExpBuffer();
    3791             118 :     tbloids = createPQExpBuffer();
    3792                 : 
    3793                 :     /*
    3794                 :      * Identify tables of interest, and check which ones have RLS enabled.
    3795 ECB             :      */
    3796 CBC         118 :     appendPQExpBufferChar(tbloids, '{');
    3797           30474 :     for (i = 0; i < numTables; i++)
    3798 ECB             :     {
    3799 GIC       30356 :         TableInfo  *tbinfo = &tblinfo[i];
    3800                 : 
    3801 ECB             :         /* Ignore row security on tables not to be dumped */
    3802 GBC       30356 :         if (!(tbinfo->dobj.dump & DUMP_COMPONENT_POLICY))
    3803           25064 :             continue;
    3804 EUB             : 
    3805                 :         /* It can't have RLS or policies if it's not a table */
    3806 GIC        5292 :         if (tbinfo->relkind != RELKIND_RELATION &&
    3807 CBC        1551 :             tbinfo->relkind != RELKIND_PARTITIONED_TABLE)
    3808            1079 :             continue;
    3809 ECB             : 
    3810                 :         /* Add it to the list of table OIDs to be probed below */
    3811 GIC        4213 :         if (tbloids->len > 1) /* do we have more than the '{'? */
    3812 CBC        4138 :             appendPQExpBufferChar(tbloids, ',');
    3813            4213 :         appendPQExpBuffer(tbloids, "%u", tbinfo->dobj.catId.oid);
    3814 ECB             : 
    3815                 :         /* Is RLS enabled?  (That's separate from whether it has policies) */
    3816 GIC        4213 :         if (tbinfo->rowsec)
    3817                 :         {
    3818              55 :             tbinfo->dobj.components |= DUMP_COMPONENT_POLICY;
    3819                 : 
    3820                 :             /*
    3821 ECB             :              * We represent RLS being enabled on a table by creating a
    3822                 :              * PolicyInfo object with null polname.
    3823                 :              *
    3824                 :              * Note: use tableoid 0 so that this object won't be mistaken for
    3825                 :              * something that pg_depend entries apply to.
    3826                 :              */
    3827 GIC          55 :             polinfo = pg_malloc(sizeof(PolicyInfo));
    3828              55 :             polinfo->dobj.objType = DO_POLICY;
    3829              55 :             polinfo->dobj.catId.tableoid = 0;
    3830              55 :             polinfo->dobj.catId.oid = tbinfo->dobj.catId.oid;
    3831              55 :             AssignDumpId(&polinfo->dobj);
    3832 CBC          55 :             polinfo->dobj.namespace = tbinfo->dobj.namespace;
    3833 GIC          55 :             polinfo->dobj.name = pg_strdup(tbinfo->dobj.name);
    3834              55 :             polinfo->poltable = tbinfo;
    3835              55 :             polinfo->polname = NULL;
    3836              55 :             polinfo->polcmd = '\0';
    3837              55 :             polinfo->polpermissive = 0;
    3838 CBC          55 :             polinfo->polroles = NULL;
    3839 GIC          55 :             polinfo->polqual = NULL;
    3840              55 :             polinfo->polwithcheck = NULL;
    3841                 :         }
    3842 ECB             :     }
    3843 GIC         118 :     appendPQExpBufferChar(tbloids, '}');
    3844                 : 
    3845 ECB             :     /*
    3846                 :      * Now, read all RLS policies belonging to the tables of interest, and
    3847                 :      * create PolicyInfo objects for them.  (Note that we must filter the
    3848                 :      * results server-side not locally, because we dare not apply pg_get_expr
    3849                 :      * to tables we don't have lock on.)
    3850                 :      */
    3851 GIC         118 :     pg_log_info("reading row-level security policies");
    3852                 : 
    3853 CBC         118 :     printfPQExpBuffer(query,
    3854 ECB             :                       "SELECT pol.oid, pol.tableoid, pol.polrelid, pol.polname, pol.polcmd, ");
    3855 GIC         118 :     if (fout->remoteVersion >= 100000)
    3856 GNC         118 :         appendPQExpBufferStr(query, "pol.polpermissive, ");
    3857                 :     else
    3858 UNC           0 :         appendPQExpBufferStr(query, "'t' as polpermissive, ");
    3859 CBC         118 :     appendPQExpBuffer(query,
    3860                 :                       "CASE WHEN pol.polroles = '{0}' THEN NULL ELSE "
    3861 ECB             :                       "   pg_catalog.array_to_string(ARRAY(SELECT pg_catalog.quote_ident(rolname) from pg_catalog.pg_roles WHERE oid = ANY(pol.polroles)), ', ') END AS polroles, "
    3862                 :                       "pg_catalog.pg_get_expr(pol.polqual, pol.polrelid) AS polqual, "
    3863 EUB             :                       "pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid) AS polwithcheck "
    3864                 :                       "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
    3865                 :                       "JOIN pg_catalog.pg_policy pol ON (src.tbloid = pol.polrelid)",
    3866 ECB             :                       tbloids->data);
    3867                 : 
    3868 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    3869                 : 
    3870             118 :     ntups = PQntuples(res);
    3871 CBC         118 :     if (ntups > 0)
    3872 ECB             :     {
    3873 GBC          45 :         i_oid = PQfnumber(res, "oid");
    3874 GIC          45 :         i_tableoid = PQfnumber(res, "tableoid");
    3875              45 :         i_polrelid = PQfnumber(res, "polrelid");
    3876 CBC          45 :         i_polname = PQfnumber(res, "polname");
    3877              45 :         i_polcmd = PQfnumber(res, "polcmd");
    3878 GIC          45 :         i_polpermissive = PQfnumber(res, "polpermissive");
    3879 CBC          45 :         i_polroles = PQfnumber(res, "polroles");
    3880 GIC          45 :         i_polqual = PQfnumber(res, "polqual");
    3881 CBC          45 :         i_polwithcheck = PQfnumber(res, "polwithcheck");
    3882                 : 
    3883 GIC          45 :         polinfo = pg_malloc(ntups * sizeof(PolicyInfo));
    3884 ECB             : 
    3885 CBC         330 :         for (j = 0; j < ntups; j++)
    3886                 :         {
    3887             285 :             Oid         polrelid = atooid(PQgetvalue(res, j, i_polrelid));
    3888 GIC         285 :             TableInfo  *tbinfo = findTableByOid(polrelid);
    3889                 : 
    3890             285 :             tbinfo->dobj.components |= DUMP_COMPONENT_POLICY;
    3891                 : 
    3892             285 :             polinfo[j].dobj.objType = DO_POLICY;
    3893             285 :             polinfo[j].dobj.catId.tableoid =
    3894             285 :                 atooid(PQgetvalue(res, j, i_tableoid));
    3895 CBC         285 :             polinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
    3896 GIC         285 :             AssignDumpId(&polinfo[j].dobj);
    3897             285 :             polinfo[j].dobj.namespace = tbinfo->dobj.namespace;
    3898             285 :             polinfo[j].poltable = tbinfo;
    3899             285 :             polinfo[j].polname = pg_strdup(PQgetvalue(res, j, i_polname));
    3900             285 :             polinfo[j].dobj.name = pg_strdup(polinfo[j].polname);
    3901                 : 
    3902             285 :             polinfo[j].polcmd = *(PQgetvalue(res, j, i_polcmd));
    3903             285 :             polinfo[j].polpermissive = *(PQgetvalue(res, j, i_polpermissive)) == 't';
    3904                 : 
    3905             285 :             if (PQgetisnull(res, j, i_polroles))
    3906             125 :                 polinfo[j].polroles = NULL;
    3907                 :             else
    3908             160 :                 polinfo[j].polroles = pg_strdup(PQgetvalue(res, j, i_polroles));
    3909                 : 
    3910             285 :             if (PQgetisnull(res, j, i_polqual))
    3911              40 :                 polinfo[j].polqual = NULL;
    3912                 :             else
    3913             245 :                 polinfo[j].polqual = pg_strdup(PQgetvalue(res, j, i_polqual));
    3914                 : 
    3915 CBC         285 :             if (PQgetisnull(res, j, i_polwithcheck))
    3916 GBC         150 :                 polinfo[j].polwithcheck = NULL;
    3917                 :             else
    3918 CBC         135 :                 polinfo[j].polwithcheck
    3919             135 :                     = pg_strdup(PQgetvalue(res, j, i_polwithcheck));
    3920                 :         }
    3921                 :     }
    3922                 : 
    3923 GIC         118 :     PQclear(res);
    3924 ECB             : 
    3925 CBC         118 :     destroyPQExpBuffer(query);
    3926 GIC         118 :     destroyPQExpBuffer(tbloids);
    3927 ECB             : }
    3928                 : 
    3929                 : /*
    3930                 :  * dumpPolicy
    3931                 :  *    dump the definition of the given policy
    3932                 :  */
    3933                 : static void
    3934 CBC         340 : dumpPolicy(Archive *fout, const PolicyInfo *polinfo)
    3935 ECB             : {
    3936 CBC         340 :     DumpOptions *dopt = fout->dopt;
    3937 GIC         340 :     TableInfo  *tbinfo = polinfo->poltable;
    3938                 :     PQExpBuffer query;
    3939 ECB             :     PQExpBuffer delqry;
    3940                 :     PQExpBuffer polprefix;
    3941                 :     char       *qtabname;
    3942                 :     const char *cmd;
    3943                 :     char       *tag;
    3944                 : 
    3945                 :     /* Do nothing in data-only dump */
    3946 CBC         340 :     if (dopt->dataOnly)
    3947 GIC          28 :         return;
    3948                 : 
    3949                 :     /*
    3950                 :      * If polname is NULL, then this record is just indicating that ROW LEVEL
    3951                 :      * SECURITY is enabled for the table. Dump as ALTER TABLE <table> ENABLE
    3952                 :      * ROW LEVEL SECURITY.
    3953                 :      */
    3954             312 :     if (polinfo->polname == NULL)
    3955 ECB             :     {
    3956 CBC          51 :         query = createPQExpBuffer();
    3957 ECB             : 
    3958 CBC          51 :         appendPQExpBuffer(query, "ALTER TABLE %s ENABLE ROW LEVEL SECURITY;",
    3959              51 :                           fmtQualifiedDumpable(tbinfo));
    3960 ECB             : 
    3961                 :         /*
    3962                 :          * We must emit the ROW SECURITY object's dependency on its table
    3963                 :          * explicitly, because it will not match anything in pg_depend (unlike
    3964                 :          * the case for other PolicyInfo objects).
    3965                 :          */
    3966 CBC          51 :         if (polinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
    3967              51 :             ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
    3968              51 :                          ARCHIVE_OPTS(.tag = polinfo->dobj.name,
    3969                 :                                       .namespace = polinfo->dobj.namespace->dobj.name,
    3970                 :                                       .owner = tbinfo->rolname,
    3971 ECB             :                                       .description = "ROW SECURITY",
    3972                 :                                       .section = SECTION_POST_DATA,
    3973                 :                                       .createStmt = query->data,
    3974                 :                                       .deps = &(tbinfo->dobj.dumpId),
    3975                 :                                       .nDeps = 1));
    3976                 : 
    3977 GIC          51 :         destroyPQExpBuffer(query);
    3978              51 :         return;
    3979 ECB             :     }
    3980                 : 
    3981 CBC         261 :     if (polinfo->polcmd == '*')
    3982 GIC          87 :         cmd = "";
    3983 CBC         174 :     else if (polinfo->polcmd == 'r')
    3984              46 :         cmd = " FOR SELECT";
    3985 GIC         128 :     else if (polinfo->polcmd == 'a')
    3986 GBC          36 :         cmd = " FOR INSERT";
    3987 CBC          92 :     else if (polinfo->polcmd == 'w')
    3988 GIC          46 :         cmd = " FOR UPDATE";
    3989              46 :     else if (polinfo->polcmd == 'd')
    3990              46 :         cmd = " FOR DELETE";
    3991                 :     else
    3992 UIC           0 :         pg_fatal("unexpected policy command type: %c",
    3993                 :                  polinfo->polcmd);
    3994                 : 
    3995 GIC         261 :     query = createPQExpBuffer();
    3996 CBC         261 :     delqry = createPQExpBuffer();
    3997 GIC         261 :     polprefix = createPQExpBuffer();
    3998 ECB             : 
    3999 CBC         261 :     qtabname = pg_strdup(fmtId(tbinfo->dobj.name));
    4000                 : 
    4001             261 :     appendPQExpBuffer(query, "CREATE POLICY %s", fmtId(polinfo->polname));
    4002 ECB             : 
    4003 CBC         261 :     appendPQExpBuffer(query, " ON %s%s%s", fmtQualifiedDumpable(tbinfo),
    4004             261 :                       !polinfo->polpermissive ? " AS RESTRICTIVE" : "", cmd);
    4005 ECB             : 
    4006 CBC         261 :     if (polinfo->polroles != NULL)
    4007             144 :         appendPQExpBuffer(query, " TO %s", polinfo->polroles);
    4008 ECB             : 
    4009 CBC         261 :     if (polinfo->polqual != NULL)
    4010 GIC         225 :         appendPQExpBuffer(query, " USING (%s)", polinfo->polqual);
    4011 ECB             : 
    4012 GIC         261 :     if (polinfo->polwithcheck != NULL)
    4013 CBC         123 :         appendPQExpBuffer(query, " WITH CHECK (%s)", polinfo->polwithcheck);
    4014                 : 
    4015             261 :     appendPQExpBufferStr(query, ";\n");
    4016 ECB             : 
    4017 GIC         261 :     appendPQExpBuffer(delqry, "DROP POLICY %s", fmtId(polinfo->polname));
    4018 CBC         261 :     appendPQExpBuffer(delqry, " ON %s;\n", fmtQualifiedDumpable(tbinfo));
    4019                 : 
    4020             261 :     appendPQExpBuffer(polprefix, "POLICY %s ON",
    4021             261 :                       fmtId(polinfo->polname));
    4022 ECB             : 
    4023 CBC         261 :     tag = psprintf("%s %s", tbinfo->dobj.name, polinfo->dobj.name);
    4024 ECB             : 
    4025 CBC         261 :     if (polinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
    4026             261 :         ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
    4027             261 :                      ARCHIVE_OPTS(.tag = tag,
    4028 ECB             :                                   .namespace = polinfo->dobj.namespace->dobj.name,
    4029                 :                                   .owner = tbinfo->rolname,
    4030                 :                                   .description = "POLICY",
    4031                 :                                   .section = SECTION_POST_DATA,
    4032                 :                                   .createStmt = query->data,
    4033                 :                                   .dropStmt = delqry->data));
    4034                 : 
    4035 GIC         261 :     if (polinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
    4036 LBC           0 :         dumpComment(fout, polprefix->data, qtabname,
    4037 UIC           0 :                     tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
    4038 LBC           0 :                     polinfo->dobj.catId, 0, polinfo->dobj.dumpId);
    4039 ECB             : 
    4040 GIC         261 :     free(tag);
    4041 CBC         261 :     destroyPQExpBuffer(query);
    4042 GIC         261 :     destroyPQExpBuffer(delqry);
    4043 CBC         261 :     destroyPQExpBuffer(polprefix);
    4044             261 :     free(qtabname);
    4045                 : }
    4046 ECB             : 
    4047                 : /*
    4048                 :  * getPublications
    4049                 :  *    get information about publications
    4050                 :  */
    4051                 : PublicationInfo *
    4052 GIC         118 : getPublications(Archive *fout, int *numPublications)
    4053 ECB             : {
    4054 CBC         118 :     DumpOptions *dopt = fout->dopt;
    4055                 :     PQExpBuffer query;
    4056                 :     PGresult   *res;
    4057                 :     PublicationInfo *pubinfo;
    4058                 :     int         i_tableoid;
    4059                 :     int         i_oid;
    4060                 :     int         i_pubname;
    4061                 :     int         i_pubowner;
    4062 ECB             :     int         i_puballtables;
    4063                 :     int         i_pubinsert;
    4064                 :     int         i_pubupdate;
    4065                 :     int         i_pubdelete;
    4066                 :     int         i_pubtruncate;
    4067                 :     int         i_pubviaroot;
    4068                 :     int         i,
    4069                 :                 ntups;
    4070                 : 
    4071 GIC         118 :     if (dopt->no_publications || fout->remoteVersion < 100000)
    4072                 :     {
    4073 UIC           0 :         *numPublications = 0;
    4074 LBC           0 :         return NULL;
    4075 ECB             :     }
    4076                 : 
    4077 GIC         118 :     query = createPQExpBuffer();
    4078                 : 
    4079             118 :     resetPQExpBuffer(query);
    4080                 : 
    4081                 :     /* Get the publications. */
    4082 CBC         118 :     if (fout->remoteVersion >= 130000)
    4083 GNC         118 :         appendPQExpBufferStr(query,
    4084                 :                              "SELECT p.tableoid, p.oid, p.pubname, "
    4085                 :                              "p.pubowner, "
    4086                 :                              "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, p.pubviaroot "
    4087                 :                              "FROM pg_publication p");
    4088 UIC           0 :     else if (fout->remoteVersion >= 110000)
    4089 UNC           0 :         appendPQExpBufferStr(query,
    4090                 :                              "SELECT p.tableoid, p.oid, p.pubname, "
    4091                 :                              "p.pubowner, "
    4092                 :                              "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate, false AS pubviaroot "
    4093                 :                              "FROM pg_publication p");
    4094 ECB             :     else
    4095 UNC           0 :         appendPQExpBufferStr(query,
    4096                 :                              "SELECT p.tableoid, p.oid, p.pubname, "
    4097                 :                              "p.pubowner, "
    4098                 :                              "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, false AS pubtruncate, false AS pubviaroot "
    4099                 :                              "FROM pg_publication p");
    4100                 : 
    4101 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    4102                 : 
    4103             118 :     ntups = PQntuples(res);
    4104                 : 
    4105 CBC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    4106             118 :     i_oid = PQfnumber(res, "oid");
    4107 GIC         118 :     i_pubname = PQfnumber(res, "pubname");
    4108             118 :     i_pubowner = PQfnumber(res, "pubowner");
    4109 CBC         118 :     i_puballtables = PQfnumber(res, "puballtables");
    4110             118 :     i_pubinsert = PQfnumber(res, "pubinsert");
    4111             118 :     i_pubupdate = PQfnumber(res, "pubupdate");
    4112             118 :     i_pubdelete = PQfnumber(res, "pubdelete");
    4113             118 :     i_pubtruncate = PQfnumber(res, "pubtruncate");
    4114             118 :     i_pubviaroot = PQfnumber(res, "pubviaroot");
    4115 ECB             : 
    4116 CBC         118 :     pubinfo = pg_malloc(ntups * sizeof(PublicationInfo));
    4117 ECB             : 
    4118 CBC         298 :     for (i = 0; i < ntups; i++)
    4119                 :     {
    4120 GBC         180 :         pubinfo[i].dobj.objType = DO_PUBLICATION;
    4121 GIC         180 :         pubinfo[i].dobj.catId.tableoid =
    4122             180 :             atooid(PQgetvalue(res, i, i_tableoid));
    4123 CBC         180 :         pubinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    4124             180 :         AssignDumpId(&pubinfo[i].dobj);
    4125             180 :         pubinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_pubname));
    4126 GIC         180 :         pubinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_pubowner));
    4127 CBC         180 :         pubinfo[i].puballtables =
    4128 GIC         180 :             (strcmp(PQgetvalue(res, i, i_puballtables), "t") == 0);
    4129 CBC         180 :         pubinfo[i].pubinsert =
    4130 GIC         180 :             (strcmp(PQgetvalue(res, i, i_pubinsert), "t") == 0);
    4131 CBC         180 :         pubinfo[i].pubupdate =
    4132             180 :             (strcmp(PQgetvalue(res, i, i_pubupdate), "t") == 0);
    4133 GIC         180 :         pubinfo[i].pubdelete =
    4134 CBC         180 :             (strcmp(PQgetvalue(res, i, i_pubdelete), "t") == 0);
    4135             180 :         pubinfo[i].pubtruncate =
    4136 GIC         180 :             (strcmp(PQgetvalue(res, i, i_pubtruncate), "t") == 0);
    4137 CBC         180 :         pubinfo[i].pubviaroot =
    4138             180 :             (strcmp(PQgetvalue(res, i, i_pubviaroot), "t") == 0);
    4139                 : 
    4140 ECB             :         /* Decide whether we want to dump it */
    4141 CBC         180 :         selectDumpableObject(&(pubinfo[i].dobj), fout);
    4142                 :     }
    4143             118 :     PQclear(res);
    4144                 : 
    4145             118 :     destroyPQExpBuffer(query);
    4146 ECB             : 
    4147 GIC         118 :     *numPublications = ntups;
    4148 CBC         118 :     return pubinfo;
    4149 ECB             : }
    4150                 : 
    4151                 : /*
    4152                 :  * dumpPublication
    4153                 :  *    dump the definition of the given publication
    4154                 :  */
    4155                 : static void
    4156 GIC         152 : dumpPublication(Archive *fout, const PublicationInfo *pubinfo)
    4157                 : {
    4158             152 :     DumpOptions *dopt = fout->dopt;
    4159                 :     PQExpBuffer delq;
    4160                 :     PQExpBuffer query;
    4161                 :     char       *qpubname;
    4162             152 :     bool        first = true;
    4163 ECB             : 
    4164 EUB             :     /* Do nothing in data-only dump */
    4165 GBC         152 :     if (dopt->dataOnly)
    4166              12 :         return;
    4167                 : 
    4168 CBC         140 :     delq = createPQExpBuffer();
    4169             140 :     query = createPQExpBuffer();
    4170 ECB             : 
    4171 CBC         140 :     qpubname = pg_strdup(fmtId(pubinfo->dobj.name));
    4172 ECB             : 
    4173 GIC         140 :     appendPQExpBuffer(delq, "DROP PUBLICATION %s;\n",
    4174                 :                       qpubname);
    4175                 : 
    4176             140 :     appendPQExpBuffer(query, "CREATE PUBLICATION %s",
    4177                 :                       qpubname);
    4178                 : 
    4179             140 :     if (pubinfo->puballtables)
    4180 CBC          35 :         appendPQExpBufferStr(query, " FOR ALL TABLES");
    4181                 : 
    4182             140 :     appendPQExpBufferStr(query, " WITH (publish = '");
    4183 GIC         140 :     if (pubinfo->pubinsert)
    4184                 :     {
    4185             105 :         appendPQExpBufferStr(query, "insert");
    4186             105 :         first = false;
    4187                 :     }
    4188                 : 
    4189             140 :     if (pubinfo->pubupdate)
    4190                 :     {
    4191             105 :         if (!first)
    4192             105 :             appendPQExpBufferStr(query, ", ");
    4193                 : 
    4194             105 :         appendPQExpBufferStr(query, "update");
    4195             105 :         first = false;
    4196                 :     }
    4197                 : 
    4198             140 :     if (pubinfo->pubdelete)
    4199 ECB             :     {
    4200 GIC         105 :         if (!first)
    4201 GBC         105 :             appendPQExpBufferStr(query, ", ");
    4202 EUB             : 
    4203 GIC         105 :         appendPQExpBufferStr(query, "delete");
    4204             105 :         first = false;
    4205 ECB             :     }
    4206                 : 
    4207 CBC         140 :     if (pubinfo->pubtruncate)
    4208                 :     {
    4209 GIC         105 :         if (!first)
    4210 CBC         105 :             appendPQExpBufferStr(query, ", ");
    4211 ECB             : 
    4212 GIC         105 :         appendPQExpBufferStr(query, "truncate");
    4213             105 :         first = false;
    4214                 :     }
    4215                 : 
    4216 GNC         140 :     appendPQExpBufferChar(query, '\'');
    4217 EUB             : 
    4218 GIC         140 :     if (pubinfo->pubviaroot)
    4219 UIC           0 :         appendPQExpBufferStr(query, ", publish_via_partition_root = true");
    4220                 : 
    4221 GIC         140 :     appendPQExpBufferStr(query, ");\n");
    4222                 : 
    4223 GBC         140 :     if (pubinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
    4224 GIC         140 :         ArchiveEntry(fout, pubinfo->dobj.catId, pubinfo->dobj.dumpId,
    4225             140 :                      ARCHIVE_OPTS(.tag = pubinfo->dobj.name,
    4226                 :                                   .owner = pubinfo->rolname,
    4227                 :                                   .description = "PUBLICATION",
    4228                 :                                   .section = SECTION_POST_DATA,
    4229 ECB             :                                   .createStmt = query->data,
    4230                 :                                   .dropStmt = delq->data));
    4231                 : 
    4232 GIC         140 :     if (pubinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
    4233 CBC          35 :         dumpComment(fout, "PUBLICATION", qpubname,
    4234              35 :                     NULL, pubinfo->rolname,
    4235              35 :                     pubinfo->dobj.catId, 0, pubinfo->dobj.dumpId);
    4236 ECB             : 
    4237 CBC         140 :     if (pubinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
    4238 LBC           0 :         dumpSecLabel(fout, "PUBLICATION", qpubname,
    4239               0 :                      NULL, pubinfo->rolname,
    4240               0 :                      pubinfo->dobj.catId, 0, pubinfo->dobj.dumpId);
    4241 ECB             : 
    4242 CBC         140 :     destroyPQExpBuffer(delq);
    4243 GIC         140 :     destroyPQExpBuffer(query);
    4244 CBC         140 :     free(qpubname);
    4245                 : }
    4246 ECB             : 
    4247                 : /*
    4248                 :  * getPublicationNamespaces
    4249                 :  *    get information about publication membership for dumpable schemas.
    4250                 :  */
    4251                 : void
    4252 CBC         118 : getPublicationNamespaces(Archive *fout)
    4253 ECB             : {
    4254                 :     PQExpBuffer query;
    4255                 :     PGresult   *res;
    4256                 :     PublicationSchemaInfo *pubsinfo;
    4257 CBC         118 :     DumpOptions *dopt = fout->dopt;
    4258 ECB             :     int         i_tableoid;
    4259                 :     int         i_oid;
    4260                 :     int         i_pnpubid;
    4261                 :     int         i_pnnspid;
    4262                 :     int         i,
    4263                 :                 j,
    4264                 :                 ntups;
    4265                 : 
    4266 CBC         118 :     if (dopt->no_publications || fout->remoteVersion < 150000)
    4267 UIC           0 :         return;
    4268                 : 
    4269 CBC         118 :     query = createPQExpBuffer();
    4270                 : 
    4271 ECB             :     /* Collect all publication membership info. */
    4272 GIC         118 :     appendPQExpBufferStr(query,
    4273 ECB             :                          "SELECT tableoid, oid, pnpubid, pnnspid "
    4274                 :                          "FROM pg_catalog.pg_publication_namespace");
    4275 CBC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    4276 ECB             : 
    4277 GIC         118 :     ntups = PQntuples(res);
    4278                 : 
    4279             118 :     i_tableoid = PQfnumber(res, "tableoid");
    4280             118 :     i_oid = PQfnumber(res, "oid");
    4281             118 :     i_pnpubid = PQfnumber(res, "pnpubid");
    4282             118 :     i_pnnspid = PQfnumber(res, "pnnspid");
    4283                 : 
    4284 ECB             :     /* this allocation may be more than we need */
    4285 GIC         118 :     pubsinfo = pg_malloc(ntups * sizeof(PublicationSchemaInfo));
    4286 CBC         118 :     j = 0;
    4287                 : 
    4288 GIC         208 :     for (i = 0; i < ntups; i++)
    4289                 :     {
    4290 CBC          90 :         Oid         pnpubid = atooid(PQgetvalue(res, i, i_pnpubid));
    4291 GIC          90 :         Oid         pnnspid = atooid(PQgetvalue(res, i, i_pnnspid));
    4292                 :         PublicationInfo *pubinfo;
    4293 ECB             :         NamespaceInfo *nspinfo;
    4294                 : 
    4295                 :         /*
    4296                 :          * Ignore any entries for which we aren't interested in either the
    4297                 :          * publication or the rel.
    4298                 :          */
    4299 CBC          90 :         pubinfo = findPublicationByOid(pnpubid);
    4300 GIC          90 :         if (pubinfo == NULL)
    4301 LBC           0 :             continue;
    4302 GIC          90 :         nspinfo = findNamespaceByOid(pnnspid);
    4303              90 :         if (nspinfo == NULL)
    4304 LBC           0 :             continue;
    4305                 : 
    4306                 :         /*
    4307 ECB             :          * We always dump publication namespaces unless the corresponding
    4308                 :          * namespace is excluded from the dump.
    4309                 :          */
    4310 CBC          90 :         if (nspinfo->dobj.dump == DUMP_COMPONENT_NONE)
    4311              13 :             continue;
    4312                 : 
    4313 ECB             :         /* OK, make a DumpableObject for this relationship */
    4314 CBC          77 :         pubsinfo[j].dobj.objType = DO_PUBLICATION_TABLE_IN_SCHEMA;
    4315 GIC          77 :         pubsinfo[j].dobj.catId.tableoid =
    4316              77 :             atooid(PQgetvalue(res, i, i_tableoid));
    4317 CBC          77 :         pubsinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    4318 GIC          77 :         AssignDumpId(&pubsinfo[j].dobj);
    4319 CBC          77 :         pubsinfo[j].dobj.namespace = nspinfo->dobj.namespace;
    4320              77 :         pubsinfo[j].dobj.name = nspinfo->dobj.name;
    4321 GIC          77 :         pubsinfo[j].publication = pubinfo;
    4322 CBC          77 :         pubsinfo[j].pubschema = nspinfo;
    4323 ECB             : 
    4324                 :         /* Decide whether we want to dump it */
    4325 GIC          77 :         selectDumpablePublicationObject(&(pubsinfo[j].dobj), fout);
    4326 ECB             : 
    4327 GIC          77 :         j++;
    4328 ECB             :     }
    4329                 : 
    4330 GIC         118 :     PQclear(res);
    4331 CBC         118 :     destroyPQExpBuffer(query);
    4332 ECB             : }
    4333                 : 
    4334                 : /*
    4335                 :  * getPublicationTables
    4336                 :  *    get information about publication membership for dumpable tables.
    4337                 :  */
    4338                 : void
    4339 GIC         118 : getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
    4340 ECB             : {
    4341                 :     PQExpBuffer query;
    4342                 :     PGresult   *res;
    4343                 :     PublicationRelInfo *pubrinfo;
    4344 CBC         118 :     DumpOptions *dopt = fout->dopt;
    4345                 :     int         i_tableoid;
    4346 ECB             :     int         i_oid;
    4347 EUB             :     int         i_prpubid;
    4348                 :     int         i_prrelid;
    4349 ECB             :     int         i_prrelqual;
    4350                 :     int         i_prattrs;
    4351                 :     int         i,
    4352                 :                 j,
    4353                 :                 ntups;
    4354                 : 
    4355 GIC         118 :     if (dopt->no_publications || fout->remoteVersion < 100000)
    4356 UIC           0 :         return;
    4357                 : 
    4358 GIC         118 :     query = createPQExpBuffer();
    4359                 : 
    4360 ECB             :     /* Collect all publication membership info. */
    4361 CBC         118 :     if (fout->remoteVersion >= 150000)
    4362             118 :         appendPQExpBufferStr(query,
    4363 ECB             :                              "SELECT tableoid, oid, prpubid, prrelid, "
    4364                 :                              "pg_catalog.pg_get_expr(prqual, prrelid) AS prrelqual, "
    4365                 :                              "(CASE\n"
    4366 EUB             :                              "  WHEN pr.prattrs IS NOT NULL THEN\n"
    4367                 :                              "    (SELECT array_agg(attname)\n"
    4368                 :                              "       FROM\n"
    4369                 :                              "         pg_catalog.generate_series(0, pg_catalog.array_upper(pr.prattrs::pg_catalog.int2[], 1)) s,\n"
    4370 ECB             :                              "         pg_catalog.pg_attribute\n"
    4371                 :                              "      WHERE attrelid = pr.prrelid AND attnum = prattrs[s])\n"
    4372                 :                              "  ELSE NULL END) prattrs "
    4373                 :                              "FROM pg_catalog.pg_publication_rel pr");
    4374                 :     else
    4375 UIC           0 :         appendPQExpBufferStr(query,
    4376                 :                              "SELECT tableoid, oid, prpubid, prrelid, "
    4377                 :                              "NULL AS prrelqual, NULL AS prattrs "
    4378                 :                              "FROM pg_catalog.pg_publication_rel");
    4379 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    4380 ECB             : 
    4381 GIC         118 :     ntups = PQntuples(res);
    4382                 : 
    4383             118 :     i_tableoid = PQfnumber(res, "tableoid");
    4384             118 :     i_oid = PQfnumber(res, "oid");
    4385 CBC         118 :     i_prpubid = PQfnumber(res, "prpubid");
    4386 GIC         118 :     i_prrelid = PQfnumber(res, "prrelid");
    4387             118 :     i_prrelqual = PQfnumber(res, "prrelqual");
    4388             118 :     i_prattrs = PQfnumber(res, "prattrs");
    4389                 : 
    4390                 :     /* this allocation may be more than we need */
    4391             118 :     pubrinfo = pg_malloc(ntups * sizeof(PublicationRelInfo));
    4392             118 :     j = 0;
    4393                 : 
    4394 CBC         433 :     for (i = 0; i < ntups; i++)
    4395 EUB             :     {
    4396 GIC         315 :         Oid         prpubid = atooid(PQgetvalue(res, i, i_prpubid));
    4397 CBC         315 :         Oid         prrelid = atooid(PQgetvalue(res, i, i_prrelid));
    4398                 :         PublicationInfo *pubinfo;
    4399                 :         TableInfo  *tbinfo;
    4400 ECB             : 
    4401                 :         /*
    4402                 :          * Ignore any entries for which we aren't interested in either the
    4403                 :          * publication or the rel.
    4404                 :          */
    4405 CBC         315 :         pubinfo = findPublicationByOid(prpubid);
    4406 GIC         315 :         if (pubinfo == NULL)
    4407 LBC           0 :             continue;
    4408 CBC         315 :         tbinfo = findTableByOid(prrelid);
    4409             315 :         if (tbinfo == NULL)
    4410 LBC           0 :             continue;
    4411                 : 
    4412                 :         /*
    4413 ECB             :          * Ignore publication membership of tables whose definitions are not
    4414                 :          * to be dumped.
    4415                 :          */
    4416 CBC         315 :         if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
    4417 GIC          39 :             continue;
    4418 ECB             : 
    4419                 :         /* OK, make a DumpableObject for this relationship */
    4420 GIC         276 :         pubrinfo[j].dobj.objType = DO_PUBLICATION_REL;
    4421             276 :         pubrinfo[j].dobj.catId.tableoid =
    4422             276 :             atooid(PQgetvalue(res, i, i_tableoid));
    4423             276 :         pubrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    4424             276 :         AssignDumpId(&pubrinfo[j].dobj);
    4425             276 :         pubrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
    4426             276 :         pubrinfo[j].dobj.name = tbinfo->dobj.name;
    4427 CBC         276 :         pubrinfo[j].publication = pubinfo;
    4428             276 :         pubrinfo[j].pubtable = tbinfo;
    4429 GBC         276 :         if (PQgetisnull(res, i, i_prrelqual))
    4430 CBC         158 :             pubrinfo[j].pubrelqual = NULL;
    4431 ECB             :         else
    4432 GBC         118 :             pubrinfo[j].pubrelqual = pg_strdup(PQgetvalue(res, i, i_prrelqual));
    4433                 : 
    4434 GIC         276 :         if (!PQgetisnull(res, i, i_prattrs))
    4435                 :         {
    4436                 :             char      **attnames;
    4437                 :             int         nattnames;
    4438 ECB             :             PQExpBuffer attribs;
    4439                 : 
    4440 GIC          78 :             if (!parsePGArray(PQgetvalue(res, i, i_prattrs),
    4441                 :                               &attnames, &nattnames))
    4442 LBC           0 :                 pg_fatal("could not parse %s array", "prattrs");
    4443 CBC          78 :             attribs = createPQExpBuffer();
    4444             234 :             for (int k = 0; k < nattnames; k++)
    4445 ECB             :             {
    4446 CBC         156 :                 if (k > 0)
    4447              78 :                     appendPQExpBufferStr(attribs, ", ");
    4448 ECB             : 
    4449 CBC         156 :                 appendPQExpBufferStr(attribs, fmtId(attnames[k]));
    4450 ECB             :             }
    4451 GIC          78 :             pubrinfo[j].pubrattrs = attribs->data;
    4452                 :         }
    4453 ECB             :         else
    4454 GIC         198 :             pubrinfo[j].pubrattrs = NULL;
    4455 ECB             : 
    4456                 :         /* Decide whether we want to dump it */
    4457 GIC         276 :         selectDumpablePublicationObject(&(pubrinfo[j].dobj), fout);
    4458 ECB             : 
    4459 CBC         276 :         j++;
    4460                 :     }
    4461                 : 
    4462 GIC         118 :     PQclear(res);
    4463             118 :     destroyPQExpBuffer(query);
    4464                 : }
    4465                 : 
    4466                 : /*
    4467 ECB             :  * dumpPublicationNamespace
    4468                 :  *    dump the definition of the given publication schema mapping.
    4469                 :  */
    4470                 : static void
    4471 GIC          75 : dumpPublicationNamespace(Archive *fout, const PublicationSchemaInfo *pubsinfo)
    4472 ECB             : {
    4473 GIC          75 :     DumpOptions *dopt = fout->dopt;
    4474              75 :     NamespaceInfo *schemainfo = pubsinfo->pubschema;
    4475              75 :     PublicationInfo *pubinfo = pubsinfo->publication;
    4476                 :     PQExpBuffer query;
    4477                 :     char       *tag;
    4478                 : 
    4479                 :     /* Do nothing in data-only dump */
    4480              75 :     if (dopt->dataOnly)
    4481               6 :         return;
    4482                 : 
    4483 CBC          69 :     tag = psprintf("%s %s", pubinfo->dobj.name, schemainfo->dobj.name);
    4484 EUB             : 
    4485 GIC          69 :     query = createPQExpBuffer();
    4486 ECB             : 
    4487 GIC          69 :     appendPQExpBuffer(query, "ALTER PUBLICATION %s ", fmtId(pubinfo->dobj.name));
    4488              69 :     appendPQExpBuffer(query, "ADD TABLES IN SCHEMA %s;\n", fmtId(schemainfo->dobj.name));
    4489 ECB             : 
    4490                 :     /*
    4491                 :      * There is no point in creating drop query as the drop is done by schema
    4492                 :      * drop.
    4493                 :      */
    4494 GIC          69 :     if (pubsinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
    4495              69 :         ArchiveEntry(fout, pubsinfo->dobj.catId, pubsinfo->dobj.dumpId,
    4496              69 :                      ARCHIVE_OPTS(.tag = tag,
    4497                 :                                   .namespace = schemainfo->dobj.name,
    4498                 :                                   .owner = pubinfo->rolname,
    4499                 :                                   .description = "PUBLICATION TABLES IN SCHEMA",
    4500                 :                                   .section = SECTION_POST_DATA,
    4501                 :                                   .createStmt = query->data));
    4502                 : 
    4503 EUB             :     /* These objects can't currently have comments or seclabels */
    4504                 : 
    4505 GIC          69 :     free(tag);
    4506              69 :     destroyPQExpBuffer(query);
    4507 ECB             : }
    4508                 : 
    4509                 : /*
    4510                 :  * dumpPublicationTable
    4511                 :  *    dump the definition of the given publication table mapping
    4512                 :  */
    4513                 : static void
    4514 CBC         256 : dumpPublicationTable(Archive *fout, const PublicationRelInfo *pubrinfo)
    4515 ECB             : {
    4516 CBC         256 :     DumpOptions *dopt = fout->dopt;
    4517 GIC         256 :     PublicationInfo *pubinfo = pubrinfo->publication;
    4518             256 :     TableInfo  *tbinfo = pubrinfo->pubtable;
    4519 ECB             :     PQExpBuffer query;
    4520                 :     char       *tag;
    4521                 : 
    4522                 :     /* Do nothing in data-only dump */
    4523 GIC         256 :     if (dopt->dataOnly)
    4524 CBC          21 :         return;
    4525 ECB             : 
    4526 GIC         235 :     tag = psprintf("%s %s", pubinfo->dobj.name, tbinfo->dobj.name);
    4527                 : 
    4528             235 :     query = createPQExpBuffer();
    4529                 : 
    4530             235 :     appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY",
    4531             235 :                       fmtId(pubinfo->dobj.name));
    4532             235 :     appendPQExpBuffer(query, " %s",
    4533 CBC         235 :                       fmtQualifiedDumpable(tbinfo));
    4534 ECB             : 
    4535 GBC         235 :     if (pubrinfo->pubrattrs)
    4536 CBC          68 :         appendPQExpBuffer(query, " (%s)", pubrinfo->pubrattrs);
    4537 ECB             : 
    4538 GBC         235 :     if (pubrinfo->pubrelqual)
    4539                 :     {
    4540                 :         /*
    4541                 :          * It's necessary to add parentheses around the expression because
    4542                 :          * pg_get_expr won't supply the parentheses for things like WHERE
    4543                 :          * TRUE.
    4544 ECB             :          */
    4545 CBC         101 :         appendPQExpBuffer(query, " WHERE (%s)", pubrinfo->pubrelqual);
    4546                 :     }
    4547 GIC         235 :     appendPQExpBufferStr(query, ";\n");
    4548 ECB             : 
    4549                 :     /*
    4550                 :      * There is no point in creating a drop query as the drop is done by table
    4551                 :      * drop.  (If you think to change this, see also _printTocEntry().)
    4552                 :      * Although this object doesn't really have ownership as such, set the
    4553                 :      * owner field anyway to ensure that the command is run by the correct
    4554                 :      * role at restore time.
    4555                 :      */
    4556 CBC         235 :     if (pubrinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
    4557             235 :         ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId,
    4558             235 :                      ARCHIVE_OPTS(.tag = tag,
    4559                 :                                   .namespace = tbinfo->dobj.namespace->dobj.name,
    4560 ECB             :                                   .owner = pubinfo->rolname,
    4561                 :                                   .description = "PUBLICATION TABLE",
    4562                 :                                   .section = SECTION_POST_DATA,
    4563                 :                                   .createStmt = query->data));
    4564                 : 
    4565                 :     /* These objects can't currently have comments or seclabels */
    4566                 : 
    4567 GIC         235 :     free(tag);
    4568 CBC         235 :     destroyPQExpBuffer(query);
    4569                 : }
    4570 EUB             : 
    4571 ECB             : /*
    4572                 :  * Is the currently connected user a superuser?
    4573                 :  */
    4574                 : static bool
    4575 CBC         118 : is_superuser(Archive *fout)
    4576                 : {
    4577             118 :     ArchiveHandle *AH = (ArchiveHandle *) fout;
    4578                 :     const char *val;
    4579 ECB             : 
    4580 GIC         118 :     val = PQparameterStatus(AH->connection, "is_superuser");
    4581                 : 
    4582 CBC         118 :     if (val && strcmp(val, "on") == 0)
    4583 GIC         116 :         return true;
    4584                 : 
    4585 CBC           2 :     return false;
    4586                 : }
    4587 ECB             : 
    4588                 : /*
    4589                 :  * getSubscriptions
    4590                 :  *    get information about subscriptions
    4591                 :  */
    4592                 : void
    4593 GIC         118 : getSubscriptions(Archive *fout)
    4594                 : {
    4595             118 :     DumpOptions *dopt = fout->dopt;
    4596                 :     PQExpBuffer query;
    4597                 :     PGresult   *res;
    4598                 :     SubscriptionInfo *subinfo;
    4599 ECB             :     int         i_tableoid;
    4600                 :     int         i_oid;
    4601                 :     int         i_subname;
    4602                 :     int         i_subowner;
    4603                 :     int         i_substream;
    4604                 :     int         i_subtwophasestate;
    4605                 :     int         i_subdisableonerr;
    4606                 :     int         i_suborigin;
    4607                 :     int         i_subconninfo;
    4608                 :     int         i_subslotname;
    4609                 :     int         i_subsynccommit;
    4610                 :     int         i_subpublications;
    4611                 :     int         i_subbinary;
    4612                 :     int         i_subpasswordrequired;
    4613                 :     int         i,
    4614                 :                 ntups;
    4615                 : 
    4616 GIC         118 :     if (dopt->no_subscriptions || fout->remoteVersion < 100000)
    4617 LBC           0 :         return;
    4618 ECB             : 
    4619 GIC         118 :     if (!is_superuser(fout))
    4620                 :     {
    4621                 :         int         n;
    4622                 : 
    4623               2 :         res = ExecuteSqlQuery(fout,
    4624 ECB             :                               "SELECT count(*) FROM pg_subscription "
    4625                 :                               "WHERE subdbid = (SELECT oid FROM pg_database"
    4626                 :                               "                 WHERE datname = current_database())",
    4627                 :                               PGRES_TUPLES_OK);
    4628 GIC           2 :         n = atoi(PQgetvalue(res, 0, 0));
    4629               2 :         if (n > 0)
    4630               2 :             pg_log_warning("subscriptions not dumped because current user is not a superuser");
    4631               2 :         PQclear(res);
    4632               2 :         return;
    4633                 :     }
    4634                 : 
    4635 CBC         116 :     query = createPQExpBuffer();
    4636 ECB             : 
    4637                 :     /* Get the subscriptions in current database. */
    4638 GNC         116 :     appendPQExpBufferStr(query,
    4639                 :                          "SELECT s.tableoid, s.oid, s.subname,\n"
    4640                 :                          " s.subowner,\n"
    4641                 :                          " s.subconninfo, s.subslotname, s.subsynccommit,\n"
    4642                 :                          " s.subpublications,\n");
    4643                 : 
    4644 CBC         116 :     if (fout->remoteVersion >= 140000)
    4645 GIC         116 :         appendPQExpBufferStr(query, " s.subbinary,\n");
    4646 ECB             :     else
    4647 LBC           0 :         appendPQExpBufferStr(query, " false AS subbinary,\n");
    4648 ECB             : 
    4649 GIC         116 :     if (fout->remoteVersion >= 140000)
    4650             116 :         appendPQExpBufferStr(query, " s.substream,\n");
    4651                 :     else
    4652 UNC           0 :         appendPQExpBufferStr(query, " 'f' AS substream,\n");
    4653 ECB             : 
    4654 CBC         116 :     if (fout->remoteVersion >= 150000)
    4655 GIC         116 :         appendPQExpBufferStr(query,
    4656 ECB             :                              " s.subtwophasestate,\n"
    4657                 :                              " s.subdisableonerr,\n");
    4658                 :     else
    4659 UIC           0 :         appendPQExpBuffer(query,
    4660 ECB             :                           " '%c' AS subtwophasestate,\n"
    4661                 :                           " false AS subdisableonerr,\n",
    4662                 :                           LOGICALREP_TWOPHASE_STATE_DISABLED);
    4663                 : 
    4664 GNC         116 :     if (fout->remoteVersion >= 160000)
    4665             116 :         appendPQExpBufferStr(query,
    4666                 :                              " s.suborigin,\n"
    4667                 :                              " s.subpasswordrequired\n");
    4668                 :     else
    4669 UNC           0 :         appendPQExpBuffer(query,
    4670                 :                           " '%s' AS suborigin,\n"
    4671                 :                           " 't' AS subpasswordrequired\n",
    4672                 :                           LOGICALREP_ORIGIN_ANY);
    4673                 : 
    4674 GIC         116 :     appendPQExpBufferStr(query,
    4675 ECB             :                          "FROM pg_subscription s\n"
    4676                 :                          "WHERE s.subdbid = (SELECT oid FROM pg_database\n"
    4677                 :                          "                   WHERE datname = current_database())");
    4678                 : 
    4679 GIC         116 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    4680                 : 
    4681             116 :     ntups = PQntuples(res);
    4682                 : 
    4683                 :     /*
    4684                 :      * Get subscription fields. We don't include subskiplsn in the dump as
    4685 ECB             :      * after restoring the dump this value may no longer be relevant.
    4686                 :      */
    4687 CBC         116 :     i_tableoid = PQfnumber(res, "tableoid");
    4688 GIC         116 :     i_oid = PQfnumber(res, "oid");
    4689             116 :     i_subname = PQfnumber(res, "subname");
    4690             116 :     i_subowner = PQfnumber(res, "subowner");
    4691             116 :     i_subconninfo = PQfnumber(res, "subconninfo");
    4692             116 :     i_subslotname = PQfnumber(res, "subslotname");
    4693             116 :     i_subsynccommit = PQfnumber(res, "subsynccommit");
    4694             116 :     i_subpublications = PQfnumber(res, "subpublications");
    4695             116 :     i_subbinary = PQfnumber(res, "subbinary");
    4696 CBC         116 :     i_substream = PQfnumber(res, "substream");
    4697             116 :     i_subtwophasestate = PQfnumber(res, "subtwophasestate");
    4698             116 :     i_subdisableonerr = PQfnumber(res, "subdisableonerr");
    4699 GNC         116 :     i_suborigin = PQfnumber(res, "suborigin");
    4700             116 :     i_subpasswordrequired = PQfnumber(res, "subpasswordrequired");
    4701                 : 
    4702 GIC         116 :     subinfo = pg_malloc(ntups * sizeof(SubscriptionInfo));
    4703                 : 
    4704             245 :     for (i = 0; i < ntups; i++)
    4705                 :     {
    4706             129 :         subinfo[i].dobj.objType = DO_SUBSCRIPTION;
    4707             129 :         subinfo[i].dobj.catId.tableoid =
    4708             129 :             atooid(PQgetvalue(res, i, i_tableoid));
    4709 CBC         129 :         subinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    4710             129 :         AssignDumpId(&subinfo[i].dobj);
    4711 GIC         129 :         subinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_subname));
    4712             129 :         subinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_subowner));
    4713             129 :         subinfo[i].subconninfo = pg_strdup(PQgetvalue(res, i, i_subconninfo));
    4714             129 :         if (PQgetisnull(res, i, i_subslotname))
    4715 UIC           0 :             subinfo[i].subslotname = NULL;
    4716                 :         else
    4717 CBC         129 :             subinfo[i].subslotname = pg_strdup(PQgetvalue(res, i, i_subslotname));
    4718 GIC         258 :         subinfo[i].subsynccommit =
    4719 CBC         129 :             pg_strdup(PQgetvalue(res, i, i_subsynccommit));
    4720 GIC         258 :         subinfo[i].subpublications =
    4721             129 :             pg_strdup(PQgetvalue(res, i, i_subpublications));
    4722 CBC         258 :         subinfo[i].subbinary =
    4723 GIC         129 :             pg_strdup(PQgetvalue(res, i, i_subbinary));
    4724 CBC         258 :         subinfo[i].substream =
    4725             129 :             pg_strdup(PQgetvalue(res, i, i_substream));
    4726 GIC         258 :         subinfo[i].subtwophasestate =
    4727 CBC         129 :             pg_strdup(PQgetvalue(res, i, i_subtwophasestate));
    4728 GIC         258 :         subinfo[i].subdisableonerr =
    4729             129 :             pg_strdup(PQgetvalue(res, i, i_subdisableonerr));
    4730 GNC         129 :         subinfo[i].suborigin = pg_strdup(PQgetvalue(res, i, i_suborigin));
    4731             258 :         subinfo[i].subpasswordrequired =
    4732             129 :             pg_strdup(PQgetvalue(res, i, i_subpasswordrequired));
    4733                 : 
    4734                 :         /* Decide whether we want to dump it */
    4735 GIC         129 :         selectDumpableObject(&(subinfo[i].dobj), fout);
    4736                 :     }
    4737             116 :     PQclear(res);
    4738 ECB             : 
    4739 GIC         116 :     destroyPQExpBuffer(query);
    4740 ECB             : }
    4741                 : 
    4742                 : /*
    4743                 :  * dumpSubscription
    4744                 :  *    dump the definition of the given subscription
    4745                 :  */
    4746                 : static void
    4747 GIC         114 : dumpSubscription(Archive *fout, const SubscriptionInfo *subinfo)
    4748                 : {
    4749             114 :     DumpOptions *dopt = fout->dopt;
    4750                 :     PQExpBuffer delq;
    4751                 :     PQExpBuffer query;
    4752                 :     PQExpBuffer publications;
    4753                 :     char       *qsubname;
    4754             114 :     char      **pubnames = NULL;
    4755             114 :     int         npubnames = 0;
    4756                 :     int         i;
    4757             114 :     char        two_phase_disabled[] = {LOGICALREP_TWOPHASE_STATE_DISABLED, '\0'};
    4758                 : 
    4759                 :     /* Do nothing in data-only dump */
    4760             114 :     if (dopt->dataOnly)
    4761 CBC           9 :         return;
    4762 EUB             : 
    4763 GIC         105 :     delq = createPQExpBuffer();
    4764 CBC         105 :     query = createPQExpBuffer();
    4765                 : 
    4766 GIC         105 :     qsubname = pg_strdup(fmtId(subinfo->dobj.name));
    4767                 : 
    4768 CBC         105 :     appendPQExpBuffer(delq, "DROP SUBSCRIPTION %s;\n",
    4769                 :                       qsubname);
    4770                 : 
    4771 GIC         105 :     appendPQExpBuffer(query, "CREATE SUBSCRIPTION %s CONNECTION ",
    4772                 :                       qsubname);
    4773 CBC         105 :     appendStringLiteralAH(query, subinfo->subconninfo, fout);
    4774 ECB             : 
    4775                 :     /* Build list of quoted publications and append them to query. */
    4776 CBC         105 :     if (!parsePGArray(subinfo->subpublications, &pubnames, &npubnames))
    4777 LBC           0 :         pg_fatal("could not parse %s array", "subpublications");
    4778                 : 
    4779 GIC         105 :     publications = createPQExpBuffer();
    4780 CBC         210 :     for (i = 0; i < npubnames; i++)
    4781                 :     {
    4782 GIC         105 :         if (i > 0)
    4783 LBC           0 :             appendPQExpBufferStr(publications, ", ");
    4784                 : 
    4785 GIC         105 :         appendPQExpBufferStr(publications, fmtId(pubnames[i]));
    4786                 :     }
    4787                 : 
    4788             105 :     appendPQExpBuffer(query, " PUBLICATION %s WITH (connect = false, slot_name = ", publications->data);
    4789 CBC         105 :     if (subinfo->subslotname)
    4790             105 :         appendStringLiteralAH(query, subinfo->subslotname, fout);
    4791                 :     else
    4792 UBC           0 :         appendPQExpBufferStr(query, "NONE");
    4793                 : 
    4794 CBC         105 :     if (strcmp(subinfo->subbinary, "t") == 0)
    4795 LBC           0 :         appendPQExpBufferStr(query, ", binary = true");
    4796                 : 
    4797 GNC         105 :     if (strcmp(subinfo->substream, "t") == 0)
    4798 UIC           0 :         appendPQExpBufferStr(query, ", streaming = on");
    4799 GNC         105 :     else if (strcmp(subinfo->substream, "p") == 0)
    4800 UNC           0 :         appendPQExpBufferStr(query, ", streaming = parallel");
    4801 ECB             : 
    4802 CBC         105 :     if (strcmp(subinfo->subtwophasestate, two_phase_disabled) != 0)
    4803 UIC           0 :         appendPQExpBufferStr(query, ", two_phase = on");
    4804                 : 
    4805 GIC         105 :     if (strcmp(subinfo->subdisableonerr, "t") == 0)
    4806 UBC           0 :         appendPQExpBufferStr(query, ", disable_on_error = true");
    4807                 : 
    4808 GNC         105 :     if (pg_strcasecmp(subinfo->suborigin, LOGICALREP_ORIGIN_ANY) != 0)
    4809              35 :         appendPQExpBuffer(query, ", origin = %s", subinfo->suborigin);
    4810                 : 
    4811 GIC         105 :     if (strcmp(subinfo->subsynccommit, "off") != 0)
    4812 UIC           0 :         appendPQExpBuffer(query, ", synchronous_commit = %s", fmtId(subinfo->subsynccommit));
    4813                 : 
    4814 GNC         105 :     if (strcmp(subinfo->subpasswordrequired, "t") != 0)
    4815 UNC           0 :         appendPQExpBuffer(query, ", password_required = false");
    4816                 : 
    4817 CBC         105 :     appendPQExpBufferStr(query, ");\n");
    4818 ECB             : 
    4819 GIC         105 :     if (subinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
    4820             105 :         ArchiveEntry(fout, subinfo->dobj.catId, subinfo->dobj.dumpId,
    4821             105 :                      ARCHIVE_OPTS(.tag = subinfo->dobj.name,
    4822 EUB             :                                   .owner = subinfo->rolname,
    4823                 :                                   .description = "SUBSCRIPTION",
    4824                 :                                   .section = SECTION_POST_DATA,
    4825                 :                                   .createStmt = query->data,
    4826                 :                                   .dropStmt = delq->data));
    4827 ECB             : 
    4828 GIC         105 :     if (subinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
    4829              35 :         dumpComment(fout, "SUBSCRIPTION", qsubname,
    4830              35 :                     NULL, subinfo->rolname,
    4831              35 :                     subinfo->dobj.catId, 0, subinfo->dobj.dumpId);
    4832 ECB             : 
    4833 GIC         105 :     if (subinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
    4834 LBC           0 :         dumpSecLabel(fout, "SUBSCRIPTION", qsubname,
    4835 UIC           0 :                      NULL, subinfo->rolname,
    4836               0 :                      subinfo->dobj.catId, 0, subinfo->dobj.dumpId);
    4837                 : 
    4838 GIC         105 :     destroyPQExpBuffer(publications);
    4839 GNC         105 :     free(pubnames);
    4840 ECB             : 
    4841 CBC         105 :     destroyPQExpBuffer(delq);
    4842             105 :     destroyPQExpBuffer(query);
    4843             105 :     free(qsubname);
    4844 ECB             : }
    4845                 : 
    4846                 : /*
    4847                 :  * Given a "create query", append as many ALTER ... DEPENDS ON EXTENSION as
    4848                 :  * the object needs.
    4849                 :  */
    4850                 : static void
    4851 CBC        4296 : append_depends_on_extension(Archive *fout,
    4852 ECB             :                             PQExpBuffer create,
    4853                 :                             const DumpableObject *dobj,
    4854                 :                             const char *catalog,
    4855                 :                             const char *keyword,
    4856                 :                             const char *objname)
    4857                 : {
    4858 CBC        4296 :     if (dobj->depends_on_ext)
    4859 ECB             :     {
    4860                 :         char       *nm;
    4861                 :         PGresult   *res;
    4862                 :         PQExpBuffer query;
    4863                 :         int         ntups;
    4864                 :         int         i_extname;
    4865                 :         int         i;
    4866                 : 
    4867 EUB             :         /* dodge fmtId() non-reentrancy */
    4868 GIC          38 :         nm = pg_strdup(objname);
    4869 ECB             : 
    4870 CBC          38 :         query = createPQExpBuffer();
    4871              38 :         appendPQExpBuffer(query,
    4872 ECB             :                           "SELECT e.extname "
    4873                 :                           "FROM pg_catalog.pg_depend d, pg_catalog.pg_extension e "
    4874                 :                           "WHERE d.refobjid = e.oid AND classid = '%s'::pg_catalog.regclass "
    4875                 :                           "AND objid = '%u'::pg_catalog.oid AND deptype = 'x' "
    4876                 :                           "AND refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass",
    4877                 :                           catalog,
    4878 CBC          38 :                           dobj->catId.oid);
    4879              38 :         res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    4880              38 :         ntups = PQntuples(res);
    4881              38 :         i_extname = PQfnumber(res, "extname");
    4882              76 :         for (i = 0; i < ntups; i++)
    4883 ECB             :         {
    4884 CBC          38 :             appendPQExpBuffer(create, "ALTER %s %s DEPENDS ON EXTENSION %s;\n",
    4885                 :                               keyword, nm,
    4886 GIC          38 :                               fmtId(PQgetvalue(res, i, i_extname)));
    4887 ECB             :         }
    4888                 : 
    4889 CBC          38 :         PQclear(res);
    4890 GIC          38 :         destroyPQExpBuffer(query);
    4891 CBC          38 :         pg_free(nm);
    4892                 :     }
    4893 GIC        4296 : }
    4894                 : 
    4895                 : static Oid
    4896 UIC           0 : get_next_possible_free_pg_type_oid(Archive *fout, PQExpBuffer upgrade_query)
    4897                 : {
    4898                 :     /*
    4899 ECB             :      * If the old version didn't assign an array type, but the new version
    4900                 :      * does, we must select an unused type OID to assign.  This currently only
    4901                 :      * happens for domains, when upgrading pre-v11 to v11 and up.
    4902                 :      *
    4903                 :      * Note: local state here is kind of ugly, but we must have some, since we
    4904                 :      * mustn't choose the same unused OID more than once.
    4905                 :      */
    4906                 :     static Oid  next_possible_free_oid = FirstNormalObjectId;
    4907                 :     PGresult   *res;
    4908                 :     bool        is_dup;
    4909                 : 
    4910                 :     do
    4911                 :     {
    4912 LBC           0 :         ++next_possible_free_oid;
    4913               0 :         printfPQExpBuffer(upgrade_query,
    4914                 :                           "SELECT EXISTS(SELECT 1 "
    4915 ECB             :                           "FROM pg_catalog.pg_type "
    4916                 :                           "WHERE oid = '%u'::pg_catalog.oid);",
    4917                 :                           next_possible_free_oid);
    4918 LBC           0 :         res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
    4919 UIC           0 :         is_dup = (PQgetvalue(res, 0, 0)[0] == 't');
    4920 LBC           0 :         PQclear(res);
    4921 UIC           0 :     } while (is_dup);
    4922                 : 
    4923 LBC           0 :     return next_possible_free_oid;
    4924                 : }
    4925 ECB             : 
    4926                 : static void
    4927 GIC         771 : binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
    4928 ECB             :                                          PQExpBuffer upgrade_buffer,
    4929 EUB             :                                          Oid pg_type_oid,
    4930                 :                                          bool force_array_type,
    4931 ECB             :                                          bool include_multirange_type)
    4932                 : {
    4933 GIC         771 :     PQExpBuffer upgrade_query = createPQExpBuffer();
    4934 ECB             :     PGresult   *res;
    4935 EUB             :     Oid         pg_type_array_oid;
    4936                 :     Oid         pg_type_multirange_oid;
    4937 ECB             :     Oid         pg_type_multirange_array_oid;
    4938                 : 
    4939 GIC         771 :     appendPQExpBufferStr(upgrade_buffer, "\n-- For binary upgrade, must preserve pg_type oid\n");
    4940 CBC         771 :     appendPQExpBuffer(upgrade_buffer,
    4941 ECB             :                       "SELECT pg_catalog.binary_upgrade_set_next_pg_type_oid('%u'::pg_catalog.oid);\n\n",
    4942                 :                       pg_type_oid);
    4943                 : 
    4944 GBC         771 :     appendPQExpBuffer(upgrade_query,
    4945                 :                       "SELECT typarray "
    4946 ECB             :                       "FROM pg_catalog.pg_type "
    4947 EUB             :                       "WHERE oid = '%u'::pg_catalog.oid;",
    4948                 :                       pg_type_oid);
    4949 ECB             : 
    4950 GBC         771 :     res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
    4951 ECB             : 
    4952 GBC         771 :     pg_type_array_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typarray")));
    4953                 : 
    4954 CBC         771 :     PQclear(res);
    4955 EUB             : 
    4956 GIC         771 :     if (!OidIsValid(pg_type_array_oid) && force_array_type)
    4957 LBC           0 :         pg_type_array_oid = get_next_possible_free_pg_type_oid(fout, upgrade_query);
    4958 EUB             : 
    4959 GIC         771 :     if (OidIsValid(pg_type_array_oid))
    4960 ECB             :     {
    4961 CBC         769 :         appendPQExpBufferStr(upgrade_buffer,
    4962                 :                              "\n-- For binary upgrade, must preserve pg_type array oid\n");
    4963             769 :         appendPQExpBuffer(upgrade_buffer,
    4964 EUB             :                           "SELECT pg_catalog.binary_upgrade_set_next_array_pg_type_oid('%u'::pg_catalog.oid);\n\n",
    4965                 :                           pg_type_array_oid);
    4966 ECB             :     }
    4967 EUB             : 
    4968                 :     /*
    4969 ECB             :      * Pre-set the multirange type oid and its own array type oid.
    4970                 :      */
    4971 CBC         771 :     if (include_multirange_type)
    4972 ECB             :     {
    4973 CBC           6 :         if (fout->remoteVersion >= 140000)
    4974                 :         {
    4975 GIC           6 :             printfPQExpBuffer(upgrade_query,
    4976                 :                               "SELECT t.oid, t.typarray "
    4977                 :                               "FROM pg_catalog.pg_type t "
    4978                 :                               "JOIN pg_catalog.pg_range r "
    4979                 :                               "ON t.oid = r.rngmultitypid "
    4980 ECB             :                               "WHERE r.rngtypid = '%u'::pg_catalog.oid;",
    4981                 :                               pg_type_oid);
    4982                 : 
    4983 CBC           6 :             res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
    4984                 : 
    4985               6 :             pg_type_multirange_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "oid")));
    4986 GBC           6 :             pg_type_multirange_array_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typarray")));
    4987 EUB             : 
    4988 GBC           6 :             PQclear(res);
    4989                 :         }
    4990 ECB             :         else
    4991                 :         {
    4992 UIC           0 :             pg_type_multirange_oid = get_next_possible_free_pg_type_oid(fout, upgrade_query);
    4993 LBC           0 :             pg_type_multirange_array_oid = get_next_possible_free_pg_type_oid(fout, upgrade_query);
    4994 ECB             :         }
    4995                 : 
    4996 GIC           6 :         appendPQExpBufferStr(upgrade_buffer,
    4997                 :                              "\n-- For binary upgrade, must preserve multirange pg_type oid\n");
    4998               6 :         appendPQExpBuffer(upgrade_buffer,
    4999                 :                           "SELECT pg_catalog.binary_upgrade_set_next_multirange_pg_type_oid('%u'::pg_catalog.oid);\n\n",
    5000                 :                           pg_type_multirange_oid);
    5001               6 :         appendPQExpBufferStr(upgrade_buffer,
    5002                 :                              "\n-- For binary upgrade, must preserve multirange pg_type array oid\n");
    5003 CBC           6 :         appendPQExpBuffer(upgrade_buffer,
    5004                 :                           "SELECT pg_catalog.binary_upgrade_set_next_multirange_array_pg_type_oid('%u'::pg_catalog.oid);\n\n",
    5005                 :                           pg_type_multirange_array_oid);
    5006                 :     }
    5007                 : 
    5008 GIC         771 :     destroyPQExpBuffer(upgrade_query);
    5009             771 : }
    5010 ECB             : 
    5011                 : static void
    5012 GIC         709 : binary_upgrade_set_type_oids_by_rel(Archive *fout,
    5013                 :                                     PQExpBuffer upgrade_buffer,
    5014                 :                                     const TableInfo *tbinfo)
    5015                 : {
    5016             709 :     Oid         pg_type_oid = tbinfo->reltype;
    5017                 : 
    5018             709 :     if (OidIsValid(pg_type_oid))
    5019             709 :         binary_upgrade_set_type_oids_by_type_oid(fout, upgrade_buffer,
    5020 ECB             :                                                  pg_type_oid, false, false);
    5021 GIC         709 : }
    5022 ECB             : 
    5023                 : static void
    5024 GIC        1028 : binary_upgrade_set_pg_class_oids(Archive *fout,
    5025                 :                                  PQExpBuffer upgrade_buffer, Oid pg_class_oid,
    5026                 :                                  bool is_index)
    5027                 : {
    5028            1028 :     PQExpBuffer upgrade_query = createPQExpBuffer();
    5029                 :     PGresult   *upgrade_res;
    5030                 :     RelFileNumber relfilenumber;
    5031 ECB             :     Oid         toast_oid;
    5032                 :     RelFileNumber toast_relfilenumber;
    5033                 :     char        relkind;
    5034                 :     Oid         toast_index_oid;
    5035                 :     RelFileNumber toast_index_relfilenumber;
    5036                 : 
    5037                 :     /*
    5038                 :      * Preserve the OID and relfilenumber of the table, table's index, table's
    5039                 :      * toast table and toast table's index if any.
    5040                 :      *
    5041                 :      * One complexity is that the current table definition might not require
    5042                 :      * the creation of a TOAST table, but the old database might have a TOAST
    5043                 :      * table that was created earlier, before some wide columns were dropped.
    5044                 :      * By setting the TOAST oid we force creation of the TOAST heap and index
    5045                 :      * by the new backend, so we can copy the files during binary upgrade
    5046                 :      * without worrying about this case.
    5047                 :      */
    5048 GBC        1028 :     appendPQExpBuffer(upgrade_query,
    5049                 :                       "SELECT c.relkind, c.relfilenode, c.reltoastrelid, ct.relfilenode AS toast_relfilenode, i.indexrelid, cti.relfilenode AS toast_index_relfilenode "
    5050                 :                       "FROM pg_catalog.pg_class c LEFT JOIN "
    5051                 :                       "pg_catalog.pg_index i ON (c.reltoastrelid = i.indrelid AND i.indisvalid) "
    5052                 :                       "LEFT JOIN pg_catalog.pg_class ct ON (c.reltoastrelid = ct.oid) "
    5053                 :                       "LEFT JOIN pg_catalog.pg_class AS cti ON (i.indexrelid = cti.oid) "
    5054                 :                       "WHERE c.oid = '%u'::pg_catalog.oid;",
    5055                 :                       pg_class_oid);
    5056                 : 
    5057 GIC        1028 :     upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
    5058                 : 
    5059            1028 :     relkind = *PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "relkind"));
    5060                 : 
    5061 GNC        1028 :     relfilenumber = atooid(PQgetvalue(upgrade_res, 0,
    5062                 :                                       PQfnumber(upgrade_res, "relfilenode")));
    5063 GIC        1028 :     toast_oid = atooid(PQgetvalue(upgrade_res, 0,
    5064 EUB             :                                   PQfnumber(upgrade_res, "reltoastrelid")));
    5065 GNC        1028 :     toast_relfilenumber = atooid(PQgetvalue(upgrade_res, 0,
    5066                 :                                             PQfnumber(upgrade_res, "toast_relfilenode")));
    5067 GIC        1028 :     toast_index_oid = atooid(PQgetvalue(upgrade_res, 0,
    5068                 :                                         PQfnumber(upgrade_res, "indexrelid")));
    5069 GNC        1028 :     toast_index_relfilenumber = atooid(PQgetvalue(upgrade_res, 0,
    5070                 :                                                   PQfnumber(upgrade_res, "toast_index_relfilenode")));
    5071 EUB             : 
    5072 GBC        1028 :     appendPQExpBufferStr(upgrade_buffer,
    5073 EUB             :                          "\n-- For binary upgrade, must preserve pg_class oids and relfilenodes\n");
    5074                 : 
    5075 GBC        1028 :     if (!is_index)
    5076                 :     {
    5077 GIC         773 :         appendPQExpBuffer(upgrade_buffer,
    5078                 :                           "SELECT pg_catalog.binary_upgrade_set_next_heap_pg_class_oid('%u'::pg_catalog.oid);\n",
    5079 ECB             :                           pg_class_oid);
    5080                 : 
    5081                 :         /*
    5082                 :          * Not every relation has storage. Also, in a pre-v12 database,
    5083                 :          * partitioned tables have a relfilenumber, which should not be
    5084                 :          * preserved when upgrading.
    5085                 :          */
    5086 GNC         773 :         if (RelFileNumberIsValid(relfilenumber) && relkind != RELKIND_PARTITIONED_TABLE)
    5087 GIC         628 :             appendPQExpBuffer(upgrade_buffer,
    5088                 :                               "SELECT pg_catalog.binary_upgrade_set_next_heap_relfilenode('%u'::pg_catalog.oid);\n",
    5089                 :                               relfilenumber);
    5090                 : 
    5091 ECB             :         /*
    5092                 :          * In a pre-v12 database, partitioned tables might be marked as having
    5093                 :          * toast tables, but we should ignore them if so.
    5094                 :          */
    5095 GIC         773 :         if (OidIsValid(toast_oid) &&
    5096 ECB             :             relkind != RELKIND_PARTITIONED_TABLE)
    5097                 :         {
    5098 GIC         251 :             appendPQExpBuffer(upgrade_buffer,
    5099                 :                               "SELECT pg_catalog.binary_upgrade_set_next_toast_pg_class_oid('%u'::pg_catalog.oid);\n",
    5100                 :                               toast_oid);
    5101             251 :             appendPQExpBuffer(upgrade_buffer,
    5102 ECB             :                               "SELECT pg_catalog.binary_upgrade_set_next_toast_relfilenode('%u'::pg_catalog.oid);\n",
    5103                 :                               toast_relfilenumber);
    5104                 : 
    5105                 :             /* every toast table has an index */
    5106 CBC         251 :             appendPQExpBuffer(upgrade_buffer,
    5107                 :                               "SELECT pg_catalog.binary_upgrade_set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n",
    5108 ECB             :                               toast_index_oid);
    5109 GBC         251 :             appendPQExpBuffer(upgrade_buffer,
    5110                 :                               "SELECT pg_catalog.binary_upgrade_set_next_index_relfilenode('%u'::pg_catalog.oid);\n",
    5111                 :                               toast_index_relfilenumber);
    5112                 :         }
    5113 ECB             : 
    5114 GIC         773 :         PQclear(upgrade_res);
    5115 ECB             :     }
    5116                 :     else
    5117                 :     {
    5118                 :         /* Preserve the OID and relfilenumber of the index */
    5119 GIC         255 :         appendPQExpBuffer(upgrade_buffer,
    5120                 :                           "SELECT pg_catalog.binary_upgrade_set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n",
    5121                 :                           pg_class_oid);
    5122             255 :         appendPQExpBuffer(upgrade_buffer,
    5123 ECB             :                           "SELECT pg_catalog.binary_upgrade_set_next_index_relfilenode('%u'::pg_catalog.oid);\n",
    5124                 :                           relfilenumber);
    5125                 :     }
    5126                 : 
    5127 CBC        1028 :     appendPQExpBufferChar(upgrade_buffer, '\n');
    5128                 : 
    5129 GIC        1028 :     destroyPQExpBuffer(upgrade_query);
    5130            1028 : }
    5131                 : 
    5132                 : /*
    5133                 :  * If the DumpableObject is a member of an extension, add a suitable
    5134                 :  * ALTER EXTENSION ADD command to the creation commands in upgrade_buffer.
    5135 ECB             :  *
    5136                 :  * For somewhat historical reasons, objname should already be quoted,
    5137                 :  * but not objnamespace (if any).
    5138                 :  */
    5139                 : static void
    5140 CBC        1233 : binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
    5141                 :                                 const DumpableObject *dobj,
    5142                 :                                 const char *objtype,
    5143                 :                                 const char *objname,
    5144 EUB             :                                 const char *objnamespace)
    5145                 : {
    5146 GIC        1233 :     DumpableObject *extobj = NULL;
    5147                 :     int         i;
    5148 ECB             : 
    5149 GIC        1233 :     if (!dobj->ext_member)
    5150 CBC        1217 :         return;
    5151                 : 
    5152                 :     /*
    5153 ECB             :      * Find the parent extension.  We could avoid this search if we wanted to
    5154                 :      * add a link field to DumpableObject, but the space costs of that would
    5155                 :      * be considerable.  We assume that member objects could only have a
    5156                 :      * direct dependency on their own extension, not any others.
    5157                 :      */
    5158 GIC          16 :     for (i = 0; i < dobj->nDeps; i++)
    5159                 :     {
    5160 CBC          16 :         extobj = findObjectByDumpId(dobj->dependencies[i]);
    5161              16 :         if (extobj && extobj->objType == DO_EXTENSION)
    5162 GIC          16 :             break;
    5163 UIC           0 :         extobj = NULL;
    5164 ECB             :     }
    5165 GIC          16 :     if (extobj == NULL)
    5166 UIC           0 :         pg_fatal("could not find parent extension for %s %s",
    5167                 :                  objtype, objname);
    5168 ECB             : 
    5169 GIC          16 :     appendPQExpBufferStr(upgrade_buffer,
    5170 ECB             :                          "\n-- For binary upgrade, handle extension membership the hard way\n");
    5171 CBC          16 :     appendPQExpBuffer(upgrade_buffer, "ALTER EXTENSION %s ADD %s ",
    5172 GIC          16 :                       fmtId(extobj->name),
    5173 ECB             :                       objtype);
    5174 GIC          16 :     if (objnamespace && *objnamespace)
    5175              13 :         appendPQExpBuffer(upgrade_buffer, "%s.", fmtId(objnamespace));
    5176 CBC          16 :     appendPQExpBuffer(upgrade_buffer, "%s;\n", objname);
    5177                 : }
    5178                 : 
    5179                 : /*
    5180 ECB             :  * getNamespaces:
    5181                 :  *    read all namespaces in the system catalogs and return them in the
    5182                 :  * NamespaceInfo* structure
    5183                 :  *
    5184                 :  *  numNamespaces is set to the number of namespaces read in
    5185                 :  */
    5186                 : NamespaceInfo *
    5187 GIC         119 : getNamespaces(Archive *fout, int *numNamespaces)
    5188                 : {
    5189                 :     PGresult   *res;
    5190                 :     int         ntups;
    5191                 :     int         i;
    5192                 :     PQExpBuffer query;
    5193                 :     NamespaceInfo *nsinfo;
    5194                 :     int         i_tableoid;
    5195                 :     int         i_oid;
    5196                 :     int         i_nspname;
    5197                 :     int         i_nspowner;
    5198                 :     int         i_nspacl;
    5199                 :     int         i_acldefault;
    5200 ECB             : 
    5201 GIC         119 :     query = createPQExpBuffer();
    5202                 : 
    5203                 :     /*
    5204                 :      * we fetch all namespaces including system ones, so that every object we
    5205                 :      * read in can be linked to a containing namespace.
    5206                 :      */
    5207 GNC         119 :     appendPQExpBufferStr(query, "SELECT n.tableoid, n.oid, n.nspname, "
    5208                 :                          "n.nspowner, "
    5209                 :                          "n.nspacl, "
    5210                 :                          "acldefault('n', n.nspowner) AS acldefault "
    5211                 :                          "FROM pg_namespace n");
    5212                 : 
    5213 CBC         119 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    5214                 : 
    5215             119 :     ntups = PQntuples(res);
    5216                 : 
    5217             119 :     nsinfo = (NamespaceInfo *) pg_malloc(ntups * sizeof(NamespaceInfo));
    5218                 : 
    5219             119 :     i_tableoid = PQfnumber(res, "tableoid");
    5220 GIC         119 :     i_oid = PQfnumber(res, "oid");
    5221 CBC         119 :     i_nspname = PQfnumber(res, "nspname");
    5222 GIC         119 :     i_nspowner = PQfnumber(res, "nspowner");
    5223             119 :     i_nspacl = PQfnumber(res, "nspacl");
    5224 CBC         119 :     i_acldefault = PQfnumber(res, "acldefault");
    5225                 : 
    5226 GIC         902 :     for (i = 0; i < ntups; i++)
    5227 ECB             :     {
    5228                 :         const char *nspowner;
    5229                 : 
    5230 GIC         783 :         nsinfo[i].dobj.objType = DO_NAMESPACE;
    5231             783 :         nsinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    5232             783 :         nsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    5233             783 :         AssignDumpId(&nsinfo[i].dobj);
    5234             783 :         nsinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_nspname));
    5235             783 :         nsinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_nspacl));
    5236             783 :         nsinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
    5237             783 :         nsinfo[i].dacl.privtype = 0;
    5238 CBC         783 :         nsinfo[i].dacl.initprivs = NULL;
    5239             783 :         nspowner = PQgetvalue(res, i, i_nspowner);
    5240 GIC         783 :         nsinfo[i].nspowner = atooid(nspowner);
    5241             783 :         nsinfo[i].rolname = getRoleName(nspowner);
    5242                 : 
    5243                 :         /* Decide whether to dump this namespace */
    5244             783 :         selectDumpableNamespace(&nsinfo[i], fout);
    5245                 : 
    5246                 :         /* Mark whether namespace has an ACL */
    5247 CBC         783 :         if (!PQgetisnull(res, i, i_nspacl))
    5248 GIC         403 :             nsinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
    5249                 : 
    5250 ECB             :         /*
    5251                 :          * We ignore any pg_init_privs.initprivs entry for the public schema
    5252                 :          * and assume a predetermined default, for several reasons.  First,
    5253                 :          * dropping and recreating the schema removes its pg_init_privs entry,
    5254                 :          * but an empty destination database starts with this ACL nonetheless.
    5255                 :          * Second, we support dump/reload of public schema ownership changes.
    5256                 :          * ALTER SCHEMA OWNER filters nspacl through aclnewowner(), but
    5257                 :          * initprivs continues to reflect the initial owner.  Hence,
    5258                 :          * synthesize the value that nspacl will have after the restore's
    5259                 :          * ALTER SCHEMA OWNER.  Third, this makes the destination database
    5260                 :          * match the source's ACL, even if the latter was an initdb-default
    5261                 :          * ACL, which changed in v15.  An upgrade pulls in changes to most
    5262                 :          * system object ACLs that the DBA had not customized.  We've made the
    5263                 :          * public schema depart from that, because changing its ACL so easily
    5264                 :          * breaks applications.
    5265                 :          */
    5266 CBC         783 :         if (strcmp(nsinfo[i].dobj.name, "public") == 0)
    5267                 :         {
    5268 GIC         115 :             PQExpBuffer aclarray = createPQExpBuffer();
    5269             115 :             PQExpBuffer aclitem = createPQExpBuffer();
    5270                 : 
    5271 ECB             :             /* Standard ACL as of v15 is {owner=UC/owner,=U/owner} */
    5272 GIC         115 :             appendPQExpBufferChar(aclarray, '{');
    5273             115 :             quoteAclUserName(aclitem, nsinfo[i].rolname);
    5274 CBC         115 :             appendPQExpBufferStr(aclitem, "=UC/");
    5275 GIC         115 :             quoteAclUserName(aclitem, nsinfo[i].rolname);
    5276             115 :             appendPGArray(aclarray, aclitem->data);
    5277             115 :             resetPQExpBuffer(aclitem);
    5278             115 :             appendPQExpBufferStr(aclitem, "=U/");
    5279 CBC         115 :             quoteAclUserName(aclitem, nsinfo[i].rolname);
    5280 GIC         115 :             appendPGArray(aclarray, aclitem->data);
    5281 CBC         115 :             appendPQExpBufferChar(aclarray, '}');
    5282 ECB             : 
    5283 GIC         115 :             nsinfo[i].dacl.privtype = 'i';
    5284             115 :             nsinfo[i].dacl.initprivs = pstrdup(aclarray->data);
    5285             115 :             nsinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
    5286                 : 
    5287             115 :             destroyPQExpBuffer(aclarray);
    5288             115 :             destroyPQExpBuffer(aclitem);
    5289                 :         }
    5290                 :     }
    5291                 : 
    5292 CBC         119 :     PQclear(res);
    5293 GIC         119 :     destroyPQExpBuffer(query);
    5294                 : 
    5295             119 :     *numNamespaces = ntups;
    5296                 : 
    5297             119 :     return nsinfo;
    5298 ECB             : }
    5299                 : 
    5300                 : /*
    5301                 :  * findNamespace:
    5302                 :  *      given a namespace OID, look up the info read by getNamespaces
    5303                 :  */
    5304                 : static NamespaceInfo *
    5305 GIC      446370 : findNamespace(Oid nsoid)
    5306                 : {
    5307                 :     NamespaceInfo *nsinfo;
    5308                 : 
    5309          446370 :     nsinfo = findNamespaceByOid(nsoid);
    5310 CBC      446370 :     if (nsinfo == NULL)
    5311 UIC           0 :         pg_fatal("schema with OID %u does not exist", nsoid);
    5312 CBC      446370 :     return nsinfo;
    5313 ECB             : }
    5314                 : 
    5315 EUB             : /*
    5316                 :  * getExtensions:
    5317 ECB             :  *    read all extensions in the system catalogs and return them in the
    5318 EUB             :  * ExtensionInfo* structure
    5319                 :  *
    5320                 :  *  numExtensions is set to the number of extensions read in
    5321 ECB             :  */
    5322                 : ExtensionInfo *
    5323 CBC         119 : getExtensions(Archive *fout, int *numExtensions)
    5324 ECB             : {
    5325 GIC         119 :     DumpOptions *dopt = fout->dopt;
    5326 ECB             :     PGresult   *res;
    5327                 :     int         ntups;
    5328                 :     int         i;
    5329                 :     PQExpBuffer query;
    5330                 :     ExtensionInfo *extinfo;
    5331                 :     int         i_tableoid;
    5332                 :     int         i_oid;
    5333                 :     int         i_extname;
    5334                 :     int         i_nspname;
    5335                 :     int         i_extrelocatable;
    5336                 :     int         i_extversion;
    5337                 :     int         i_extconfig;
    5338                 :     int         i_extcondition;
    5339                 : 
    5340 GIC         119 :     query = createPQExpBuffer();
    5341                 : 
    5342             119 :     appendPQExpBufferStr(query, "SELECT x.tableoid, x.oid, "
    5343                 :                          "x.extname, n.nspname, x.extrelocatable, x.extversion, x.extconfig, x.extcondition "
    5344                 :                          "FROM pg_extension x "
    5345                 :                          "JOIN pg_namespace n ON n.oid = x.extnamespace");
    5346                 : 
    5347             119 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    5348                 : 
    5349             119 :     ntups = PQntuples(res);
    5350                 : 
    5351             119 :     extinfo = (ExtensionInfo *) pg_malloc(ntups * sizeof(ExtensionInfo));
    5352                 : 
    5353 CBC         119 :     i_tableoid = PQfnumber(res, "tableoid");
    5354 GIC         119 :     i_oid = PQfnumber(res, "oid");
    5355             119 :     i_extname = PQfnumber(res, "extname");
    5356             119 :     i_nspname = PQfnumber(res, "nspname");
    5357             119 :     i_extrelocatable = PQfnumber(res, "extrelocatable");
    5358             119 :     i_extversion = PQfnumber(res, "extversion");
    5359 CBC         119 :     i_extconfig = PQfnumber(res, "extconfig");
    5360 GIC         119 :     i_extcondition = PQfnumber(res, "extcondition");
    5361                 : 
    5362             260 :     for (i = 0; i < ntups; i++)
    5363                 :     {
    5364             141 :         extinfo[i].dobj.objType = DO_EXTENSION;
    5365 CBC         141 :         extinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    5366 GIC         141 :         extinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    5367 CBC         141 :         AssignDumpId(&extinfo[i].dobj);
    5368 GIC         141 :         extinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_extname));
    5369 CBC         141 :         extinfo[i].namespace = pg_strdup(PQgetvalue(res, i, i_nspname));
    5370 GIC         141 :         extinfo[i].relocatable = *(PQgetvalue(res, i, i_extrelocatable)) == 't';
    5371 CBC         141 :         extinfo[i].extversion = pg_strdup(PQgetvalue(res, i, i_extversion));
    5372             141 :         extinfo[i].extconfig = pg_strdup(PQgetvalue(res, i, i_extconfig));
    5373             141 :         extinfo[i].extcondition = pg_strdup(PQgetvalue(res, i, i_extcondition));
    5374 ECB             : 
    5375                 :         /* Decide whether we want to dump it */
    5376 CBC         141 :         selectDumpableExtension(&(extinfo[i]), dopt);
    5377                 :     }
    5378 ECB             : 
    5379 GIC         119 :     PQclear(res);
    5380             119 :     destroyPQExpBuffer(query);
    5381                 : 
    5382 CBC         119 :     *numExtensions = ntups;
    5383 ECB             : 
    5384 CBC         119 :     return extinfo;
    5385 ECB             : }
    5386                 : 
    5387                 : /*
    5388                 :  * getTypes:
    5389                 :  *    read all types in the system catalogs and return them in the
    5390                 :  * TypeInfo* structure
    5391                 :  *
    5392                 :  *  numTypes is set to the number of types read in
    5393                 :  *
    5394                 :  * NB: this must run after getFuncs() because we assume we can do
    5395                 :  * findFuncByOid().
    5396                 :  */
    5397                 : TypeInfo *
    5398 GIC         118 : getTypes(Archive *fout, int *numTypes)
    5399 ECB             : {
    5400                 :     PGresult   *res;
    5401                 :     int         ntups;
    5402                 :     int         i;
    5403 GIC         118 :     PQExpBuffer query = createPQExpBuffer();
    5404                 :     TypeInfo   *tyinfo;
    5405                 :     ShellTypeInfo *stinfo;
    5406                 :     int         i_tableoid;
    5407                 :     int         i_oid;
    5408                 :     int         i_typname;
    5409                 :     int         i_typnamespace;
    5410                 :     int         i_typacl;
    5411                 :     int         i_acldefault;
    5412                 :     int         i_typowner;
    5413                 :     int         i_typelem;
    5414                 :     int         i_typrelid;
    5415                 :     int         i_typrelkind;
    5416                 :     int         i_typtype;
    5417                 :     int         i_typisdefined;
    5418 ECB             :     int         i_isarray;
    5419                 : 
    5420                 :     /*
    5421                 :      * we include even the built-in types because those may be used as array
    5422                 :      * elements by user-defined types
    5423                 :      *
    5424                 :      * we filter out the built-in types when we dump out the types
    5425                 :      *
    5426                 :      * same approach for undefined (shell) types and array types
    5427                 :      *
    5428                 :      * Note: as of 8.3 we can reliably detect whether a type is an
    5429                 :      * auto-generated array type by checking the element type's typarray.
    5430                 :      * (Before that the test is capable of generating false positives.) We
    5431                 :      * still check for name beginning with '_', though, so as to avoid the
    5432                 :      * cost of the subselect probe for all standard types.  This would have to
    5433                 :      * be revisited if the backend ever allows renaming of array types.
    5434                 :      */
    5435 GNC         118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, typname, "
    5436                 :                          "typnamespace, typacl, "
    5437                 :                          "acldefault('T', typowner) AS acldefault, "
    5438                 :                          "typowner, "
    5439                 :                          "typelem, typrelid, "
    5440                 :                          "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
    5441                 :                          "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
    5442                 :                          "typtype, typisdefined, "
    5443                 :                          "typname[0] = '_' AND typelem != 0 AND "
    5444                 :                          "(SELECT typarray FROM pg_type te WHERE oid = pg_type.typelem) = oid AS isarray "
    5445                 :                          "FROM pg_type");
    5446                 : 
    5447 CBC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    5448                 : 
    5449             118 :     ntups = PQntuples(res);
    5450                 : 
    5451 GIC         118 :     tyinfo = (TypeInfo *) pg_malloc(ntups * sizeof(TypeInfo));
    5452                 : 
    5453             118 :     i_tableoid = PQfnumber(res, "tableoid");
    5454             118 :     i_oid = PQfnumber(res, "oid");
    5455             118 :     i_typname = PQfnumber(res, "typname");
    5456             118 :     i_typnamespace = PQfnumber(res, "typnamespace");
    5457 CBC         118 :     i_typacl = PQfnumber(res, "typacl");
    5458 GIC         118 :     i_acldefault = PQfnumber(res, "acldefault");
    5459             118 :     i_typowner = PQfnumber(res, "typowner");
    5460             118 :     i_typelem = PQfnumber(res, "typelem");
    5461 CBC         118 :     i_typrelid = PQfnumber(res, "typrelid");
    5462             118 :     i_typrelkind = PQfnumber(res, "typrelkind");
    5463 GBC         118 :     i_typtype = PQfnumber(res, "typtype");
    5464 CBC         118 :     i_typisdefined = PQfnumber(res, "typisdefined");
    5465 GIC         118 :     i_isarray = PQfnumber(res, "isarray");
    5466                 : 
    5467           83984 :     for (i = 0; i < ntups; i++)
    5468                 :     {
    5469           83866 :         tyinfo[i].dobj.objType = DO_TYPE;
    5470           83866 :         tyinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    5471           83866 :         tyinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    5472           83866 :         AssignDumpId(&tyinfo[i].dobj);
    5473           83866 :         tyinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_typname));
    5474          167732 :         tyinfo[i].dobj.namespace =
    5475 CBC       83866 :             findNamespace(atooid(PQgetvalue(res, i, i_typnamespace)));
    5476 GIC       83866 :         tyinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_typacl));
    5477 CBC       83866 :         tyinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
    5478 GIC       83866 :         tyinfo[i].dacl.privtype = 0;
    5479           83866 :         tyinfo[i].dacl.initprivs = NULL;
    5480           83866 :         tyinfo[i].ftypname = NULL;  /* may get filled later */
    5481           83866 :         tyinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_typowner));
    5482           83866 :         tyinfo[i].typelem = atooid(PQgetvalue(res, i, i_typelem));
    5483           83866 :         tyinfo[i].typrelid = atooid(PQgetvalue(res, i, i_typrelid));
    5484           83866 :         tyinfo[i].typrelkind = *PQgetvalue(res, i, i_typrelkind);
    5485           83866 :         tyinfo[i].typtype = *PQgetvalue(res, i, i_typtype);
    5486           83866 :         tyinfo[i].shellType = NULL;
    5487                 : 
    5488           83866 :         if (strcmp(PQgetvalue(res, i, i_typisdefined), "t") == 0)
    5489           83816 :             tyinfo[i].isDefined = true;
    5490                 :         else
    5491              50 :             tyinfo[i].isDefined = false;
    5492 ECB             : 
    5493 GIC       83866 :         if (strcmp(PQgetvalue(res, i, i_isarray), "t") == 0)
    5494 CBC       40197 :             tyinfo[i].isArray = true;
    5495                 :         else
    5496 GIC       43669 :             tyinfo[i].isArray = false;
    5497                 : 
    5498           83866 :         if (tyinfo[i].typtype == 'm')
    5499 CBC         818 :             tyinfo[i].isMultirange = true;
    5500                 :         else
    5501           83048 :             tyinfo[i].isMultirange = false;
    5502                 : 
    5503 ECB             :         /* Decide whether we want to dump it */
    5504 GIC       83866 :         selectDumpableType(&tyinfo[i], fout);
    5505 ECB             : 
    5506                 :         /* Mark whether type has an ACL */
    5507 CBC       83866 :         if (!PQgetisnull(res, i, i_typacl))
    5508             202 :             tyinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
    5509 ECB             : 
    5510                 :         /*
    5511                 :          * If it's a domain, fetch info about its constraints, if any
    5512                 :          */
    5513 GIC       83866 :         tyinfo[i].nDomChecks = 0;
    5514 CBC       83866 :         tyinfo[i].domChecks = NULL;
    5515 GIC       83866 :         if ((tyinfo[i].dobj.dump & DUMP_COMPONENT_DEFINITION) &&
    5516 CBC       10888 :             tyinfo[i].typtype == TYPTYPE_DOMAIN)
    5517             124 :             getDomainConstraints(fout, &(tyinfo[i]));
    5518 ECB             : 
    5519                 :         /*
    5520                 :          * If it's a base type, make a DumpableObject representing a shell
    5521                 :          * definition of the type.  We will need to dump that ahead of the I/O
    5522                 :          * functions for the type.  Similarly, range types need a shell
    5523                 :          * definition in case they have a canonicalize function.
    5524                 :          *
    5525                 :          * Note: the shell type doesn't have a catId.  You might think it
    5526                 :          * should copy the base type's catId, but then it might capture the
    5527                 :          * pg_depend entries for the type, which we don't want.
    5528                 :          */
    5529 GIC       83866 :         if ((tyinfo[i].dobj.dump & DUMP_COMPONENT_DEFINITION) &&
    5530           10888 :             (tyinfo[i].typtype == TYPTYPE_BASE ||
    5531 CBC        5344 :              tyinfo[i].typtype == TYPTYPE_RANGE))
    5532 ECB             :         {
    5533 GIC        5642 :             stinfo = (ShellTypeInfo *) pg_malloc(sizeof(ShellTypeInfo));
    5534 CBC        5642 :             stinfo->dobj.objType = DO_SHELL_TYPE;
    5535 GIC        5642 :             stinfo->dobj.catId = nilCatalogId;
    5536 CBC        5642 :             AssignDumpId(&stinfo->dobj);
    5537 GIC        5642 :             stinfo->dobj.name = pg_strdup(tyinfo[i].dobj.name);
    5538            5642 :             stinfo->dobj.namespace = tyinfo[i].dobj.namespace;
    5539            5642 :             stinfo->baseType = &(tyinfo[i]);
    5540            5642 :             tyinfo[i].shellType = stinfo;
    5541                 : 
    5542                 :             /*
    5543                 :              * Initially mark the shell type as not to be dumped.  We'll only
    5544                 :              * dump it if the I/O or canonicalize functions need to be dumped;
    5545                 :              * this is taken care of while sorting dependencies.
    5546                 :              */
    5547            5642 :             stinfo->dobj.dump = DUMP_COMPONENT_NONE;
    5548                 :         }
    5549                 :     }
    5550 ECB             : 
    5551 GIC         118 :     *numTypes = ntups;
    5552                 : 
    5553             118 :     PQclear(res);
    5554                 : 
    5555 CBC         118 :     destroyPQExpBuffer(query);
    5556                 : 
    5557 GIC         118 :     return tyinfo;
    5558                 : }
    5559                 : 
    5560                 : /*
    5561                 :  * getOperators:
    5562                 :  *    read all operators in the system catalogs and return them in the
    5563                 :  * OprInfo* structure
    5564                 :  *
    5565                 :  *  numOprs is set to the number of operators read in
    5566                 :  */
    5567                 : OprInfo *
    5568             118 : getOperators(Archive *fout, int *numOprs)
    5569                 : {
    5570                 :     PGresult   *res;
    5571                 :     int         ntups;
    5572                 :     int         i;
    5573             118 :     PQExpBuffer query = createPQExpBuffer();
    5574                 :     OprInfo    *oprinfo;
    5575                 :     int         i_tableoid;
    5576                 :     int         i_oid;
    5577                 :     int         i_oprname;
    5578                 :     int         i_oprnamespace;
    5579                 :     int         i_oprowner;
    5580                 :     int         i_oprkind;
    5581                 :     int         i_oprcode;
    5582                 : 
    5583                 :     /*
    5584                 :      * find all operators, including builtin operators; we filter out
    5585                 :      * system-defined operators at dump-out time.
    5586                 :      */
    5587 ECB             : 
    5588 GNC         118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, oprname, "
    5589                 :                          "oprnamespace, "
    5590                 :                          "oprowner, "
    5591                 :                          "oprkind, "
    5592                 :                          "oprcode::oid AS oprcode "
    5593                 :                          "FROM pg_operator");
    5594                 : 
    5595 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    5596                 : 
    5597             118 :     ntups = PQntuples(res);
    5598             118 :     *numOprs = ntups;
    5599 ECB             : 
    5600 GIC         118 :     oprinfo = (OprInfo *) pg_malloc(ntups * sizeof(OprInfo));
    5601 ECB             : 
    5602 GIC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    5603 CBC         118 :     i_oid = PQfnumber(res, "oid");
    5604 GIC         118 :     i_oprname = PQfnumber(res, "oprname");
    5605 CBC         118 :     i_oprnamespace = PQfnumber(res, "oprnamespace");
    5606             118 :     i_oprowner = PQfnumber(res, "oprowner");
    5607             118 :     i_oprkind = PQfnumber(res, "oprkind");
    5608             118 :     i_oprcode = PQfnumber(res, "oprcode");
    5609 ECB             : 
    5610 CBC       94514 :     for (i = 0; i < ntups; i++)
    5611 ECB             :     {
    5612 CBC       94396 :         oprinfo[i].dobj.objType = DO_OPERATOR;
    5613           94396 :         oprinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    5614           94396 :         oprinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    5615           94396 :         AssignDumpId(&oprinfo[i].dobj);
    5616           94396 :         oprinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_oprname));
    5617          188792 :         oprinfo[i].dobj.namespace =
    5618 GIC       94396 :             findNamespace(atooid(PQgetvalue(res, i, i_oprnamespace)));
    5619 CBC       94396 :         oprinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_oprowner));
    5620 GIC       94396 :         oprinfo[i].oprkind = (PQgetvalue(res, i, i_oprkind))[0];
    5621 CBC       94396 :         oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode));
    5622 ECB             : 
    5623                 :         /* Decide whether we want to dump it */
    5624 CBC       94396 :         selectDumpableObject(&(oprinfo[i].dobj), fout);
    5625 ECB             :     }
    5626                 : 
    5627 CBC         118 :     PQclear(res);
    5628 ECB             : 
    5629 CBC         118 :     destroyPQExpBuffer(query);
    5630 ECB             : 
    5631 CBC         118 :     return oprinfo;
    5632 ECB             : }
    5633                 : 
    5634                 : /*
    5635                 :  * getCollations:
    5636                 :  *    read all collations in the system catalogs and return them in the
    5637                 :  * CollInfo* structure
    5638                 :  *
    5639                 :  *  numCollations is set to the number of collations read in
    5640                 :  */
    5641                 : CollInfo *
    5642 GIC         118 : getCollations(Archive *fout, int *numCollations)
    5643 ECB             : {
    5644                 :     PGresult   *res;
    5645                 :     int         ntups;
    5646                 :     int         i;
    5647                 :     PQExpBuffer query;
    5648                 :     CollInfo   *collinfo;
    5649                 :     int         i_tableoid;
    5650                 :     int         i_oid;
    5651                 :     int         i_collname;
    5652                 :     int         i_collnamespace;
    5653                 :     int         i_collowner;
    5654                 : 
    5655 GIC         118 :     query = createPQExpBuffer();
    5656 ECB             : 
    5657                 :     /*
    5658                 :      * find all collations, including builtin collations; we filter out
    5659                 :      * system-defined collations at dump-out time.
    5660                 :      */
    5661                 : 
    5662 GNC         118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, collname, "
    5663                 :                          "collnamespace, "
    5664                 :                          "collowner "
    5665                 :                          "FROM pg_collation");
    5666 ECB             : 
    5667 CBC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    5668 ECB             : 
    5669 CBC         118 :     ntups = PQntuples(res);
    5670 GIC         118 :     *numCollations = ntups;
    5671                 : 
    5672             118 :     collinfo = (CollInfo *) pg_malloc(ntups * sizeof(CollInfo));
    5673                 : 
    5674             118 :     i_tableoid = PQfnumber(res, "tableoid");
    5675             118 :     i_oid = PQfnumber(res, "oid");
    5676             118 :     i_collname = PQfnumber(res, "collname");
    5677             118 :     i_collnamespace = PQfnumber(res, "collnamespace");
    5678             118 :     i_collowner = PQfnumber(res, "collowner");
    5679                 : 
    5680          172493 :     for (i = 0; i < ntups; i++)
    5681 ECB             :     {
    5682 CBC      172375 :         collinfo[i].dobj.objType = DO_COLLATION;
    5683          172375 :         collinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    5684 GIC      172375 :         collinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    5685 CBC      172375 :         AssignDumpId(&collinfo[i].dobj);
    5686          172375 :         collinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_collname));
    5687          344750 :         collinfo[i].dobj.namespace =
    5688          172375 :             findNamespace(atooid(PQgetvalue(res, i, i_collnamespace)));
    5689          172375 :         collinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_collowner));
    5690 ECB             : 
    5691                 :         /* Decide whether we want to dump it */
    5692 CBC      172375 :         selectDumpableObject(&(collinfo[i].dobj), fout);
    5693                 :     }
    5694                 : 
    5695 GIC         118 :     PQclear(res);
    5696                 : 
    5697             118 :     destroyPQExpBuffer(query);
    5698                 : 
    5699 CBC         118 :     return collinfo;
    5700                 : }
    5701                 : 
    5702                 : /*
    5703 ECB             :  * getConversions:
    5704                 :  *    read all conversions in the system catalogs and return them in the
    5705                 :  * ConvInfo* structure
    5706                 :  *
    5707                 :  *  numConversions is set to the number of conversions read in
    5708                 :  */
    5709                 : ConvInfo *
    5710 GIC         118 : getConversions(Archive *fout, int *numConversions)
    5711                 : {
    5712                 :     PGresult   *res;
    5713                 :     int         ntups;
    5714                 :     int         i;
    5715                 :     PQExpBuffer query;
    5716                 :     ConvInfo   *convinfo;
    5717                 :     int         i_tableoid;
    5718                 :     int         i_oid;
    5719                 :     int         i_conname;
    5720 ECB             :     int         i_connamespace;
    5721                 :     int         i_conowner;
    5722                 : 
    5723 GIC         118 :     query = createPQExpBuffer();
    5724                 : 
    5725 ECB             :     /*
    5726                 :      * find all conversions, including builtin conversions; we filter out
    5727                 :      * system-defined conversions at dump-out time.
    5728                 :      */
    5729                 : 
    5730 GNC         118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, conname, "
    5731                 :                          "connamespace, "
    5732                 :                          "conowner "
    5733                 :                          "FROM pg_conversion");
    5734                 : 
    5735 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    5736                 : 
    5737             118 :     ntups = PQntuples(res);
    5738             118 :     *numConversions = ntups;
    5739                 : 
    5740 CBC         118 :     convinfo = (ConvInfo *) pg_malloc(ntups * sizeof(ConvInfo));
    5741                 : 
    5742 GIC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    5743             118 :     i_oid = PQfnumber(res, "oid");
    5744             118 :     i_conname = PQfnumber(res, "conname");
    5745             118 :     i_connamespace = PQfnumber(res, "connamespace");
    5746             118 :     i_conowner = PQfnumber(res, "conowner");
    5747 ECB             : 
    5748 GIC       15267 :     for (i = 0; i < ntups; i++)
    5749 ECB             :     {
    5750 CBC       15149 :         convinfo[i].dobj.objType = DO_CONVERSION;
    5751 GIC       15149 :         convinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    5752 CBC       15149 :         convinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    5753 GIC       15149 :         AssignDumpId(&convinfo[i].dobj);
    5754 CBC       15149 :         convinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
    5755           30298 :         convinfo[i].dobj.namespace =
    5756           15149 :             findNamespace(atooid(PQgetvalue(res, i, i_connamespace)));
    5757           15149 :         convinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_conowner));
    5758 ECB             : 
    5759                 :         /* Decide whether we want to dump it */
    5760 CBC       15149 :         selectDumpableObject(&(convinfo[i].dobj), fout);
    5761                 :     }
    5762 ECB             : 
    5763 GIC         118 :     PQclear(res);
    5764 ECB             : 
    5765 CBC         118 :     destroyPQExpBuffer(query);
    5766 ECB             : 
    5767 CBC         118 :     return convinfo;
    5768 ECB             : }
    5769                 : 
    5770                 : /*
    5771                 :  * getAccessMethods:
    5772                 :  *    read all user-defined access methods in the system catalogs and return
    5773                 :  *    them in the AccessMethodInfo* structure
    5774                 :  *
    5775                 :  *  numAccessMethods is set to the number of access methods read in
    5776                 :  */
    5777                 : AccessMethodInfo *
    5778 GIC         118 : getAccessMethods(Archive *fout, int *numAccessMethods)
    5779 ECB             : {
    5780                 :     PGresult   *res;
    5781                 :     int         ntups;
    5782                 :     int         i;
    5783                 :     PQExpBuffer query;
    5784                 :     AccessMethodInfo *aminfo;
    5785                 :     int         i_tableoid;
    5786                 :     int         i_oid;
    5787                 :     int         i_amname;
    5788                 :     int         i_amhandler;
    5789                 :     int         i_amtype;
    5790                 : 
    5791                 :     /* Before 9.6, there are no user-defined access methods */
    5792 GIC         118 :     if (fout->remoteVersion < 90600)
    5793                 :     {
    5794 LBC           0 :         *numAccessMethods = 0;
    5795 UIC           0 :         return NULL;
    5796                 :     }
    5797                 : 
    5798 GIC         118 :     query = createPQExpBuffer();
    5799                 : 
    5800                 :     /* Select all access methods from pg_am table */
    5801             118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, amname, amtype, "
    5802                 :                          "amhandler::pg_catalog.regproc AS amhandler "
    5803                 :                          "FROM pg_am");
    5804                 : 
    5805             118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    5806                 : 
    5807 CBC         118 :     ntups = PQntuples(res);
    5808 GIC         118 :     *numAccessMethods = ntups;
    5809                 : 
    5810             118 :     aminfo = (AccessMethodInfo *) pg_malloc(ntups * sizeof(AccessMethodInfo));
    5811                 : 
    5812             118 :     i_tableoid = PQfnumber(res, "tableoid");
    5813             118 :     i_oid = PQfnumber(res, "oid");
    5814 CBC         118 :     i_amname = PQfnumber(res, "amname");
    5815 GIC         118 :     i_amhandler = PQfnumber(res, "amhandler");
    5816             118 :     i_amtype = PQfnumber(res, "amtype");
    5817                 : 
    5818            1061 :     for (i = 0; i < ntups; i++)
    5819 ECB             :     {
    5820 GIC         943 :         aminfo[i].dobj.objType = DO_ACCESS_METHOD;
    5821 CBC         943 :         aminfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    5822             943 :         aminfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    5823 GIC         943 :         AssignDumpId(&aminfo[i].dobj);
    5824 CBC         943 :         aminfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_amname));
    5825 GIC         943 :         aminfo[i].dobj.namespace = NULL;
    5826 CBC         943 :         aminfo[i].amhandler = pg_strdup(PQgetvalue(res, i, i_amhandler));
    5827             943 :         aminfo[i].amtype = *(PQgetvalue(res, i, i_amtype));
    5828 ECB             : 
    5829                 :         /* Decide whether we want to dump it */
    5830 CBC         943 :         selectDumpableAccessMethod(&(aminfo[i]), fout);
    5831                 :     }
    5832 ECB             : 
    5833 GIC         118 :     PQclear(res);
    5834 ECB             : 
    5835 CBC         118 :     destroyPQExpBuffer(query);
    5836 ECB             : 
    5837 CBC         118 :     return aminfo;
    5838 ECB             : }
    5839                 : 
    5840                 : 
    5841                 : /*
    5842                 :  * getOpclasses:
    5843                 :  *    read all opclasses in the system catalogs and return them in the
    5844                 :  * OpclassInfo* structure
    5845                 :  *
    5846                 :  *  numOpclasses is set to the number of opclasses read in
    5847                 :  */
    5848                 : OpclassInfo *
    5849 CBC         118 : getOpclasses(Archive *fout, int *numOpclasses)
    5850                 : {
    5851 ECB             :     PGresult   *res;
    5852                 :     int         ntups;
    5853                 :     int         i;
    5854 GIC         118 :     PQExpBuffer query = createPQExpBuffer();
    5855                 :     OpclassInfo *opcinfo;
    5856                 :     int         i_tableoid;
    5857                 :     int         i_oid;
    5858                 :     int         i_opcname;
    5859                 :     int         i_opcnamespace;
    5860                 :     int         i_opcowner;
    5861                 : 
    5862 ECB             :     /*
    5863                 :      * find all opclasses, including builtin opclasses; we filter out
    5864                 :      * system-defined opclasses at dump-out time.
    5865                 :      */
    5866                 : 
    5867 GNC         118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, opcname, "
    5868                 :                          "opcnamespace, "
    5869                 :                          "opcowner "
    5870                 :                          "FROM pg_opclass");
    5871                 : 
    5872 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    5873                 : 
    5874             118 :     ntups = PQntuples(res);
    5875 CBC         118 :     *numOpclasses = ntups;
    5876                 : 
    5877 GIC         118 :     opcinfo = (OpclassInfo *) pg_malloc(ntups * sizeof(OpclassInfo));
    5878                 : 
    5879             118 :     i_tableoid = PQfnumber(res, "tableoid");
    5880             118 :     i_oid = PQfnumber(res, "oid");
    5881             118 :     i_opcname = PQfnumber(res, "opcname");
    5882 CBC         118 :     i_opcnamespace = PQfnumber(res, "opcnamespace");
    5883 GIC         118 :     i_opcowner = PQfnumber(res, "opcowner");
    5884                 : 
    5885           21154 :     for (i = 0; i < ntups; i++)
    5886                 :     {
    5887 CBC       21036 :         opcinfo[i].dobj.objType = DO_OPCLASS;
    5888 GIC       21036 :         opcinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    5889 CBC       21036 :         opcinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    5890           21036 :         AssignDumpId(&opcinfo[i].dobj);
    5891 GIC       21036 :         opcinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opcname));
    5892 CBC       42072 :         opcinfo[i].dobj.namespace =
    5893 GIC       21036 :             findNamespace(atooid(PQgetvalue(res, i, i_opcnamespace)));
    5894 CBC       21036 :         opcinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_opcowner));
    5895 ECB             : 
    5896                 :         /* Decide whether we want to dump it */
    5897 CBC       21036 :         selectDumpableObject(&(opcinfo[i].dobj), fout);
    5898 ECB             :     }
    5899                 : 
    5900 CBC         118 :     PQclear(res);
    5901                 : 
    5902             118 :     destroyPQExpBuffer(query);
    5903 ECB             : 
    5904 CBC         118 :     return opcinfo;
    5905 ECB             : }
    5906                 : 
    5907                 : /*
    5908                 :  * getOpfamilies:
    5909                 :  *    read all opfamilies in the system catalogs and return them in the
    5910                 :  * OpfamilyInfo* structure
    5911                 :  *
    5912                 :  *  numOpfamilies is set to the number of opfamilies read in
    5913                 :  */
    5914                 : OpfamilyInfo *
    5915 CBC         118 : getOpfamilies(Archive *fout, int *numOpfamilies)
    5916                 : {
    5917 ECB             :     PGresult   *res;
    5918                 :     int         ntups;
    5919                 :     int         i;
    5920                 :     PQExpBuffer query;
    5921                 :     OpfamilyInfo *opfinfo;
    5922                 :     int         i_tableoid;
    5923                 :     int         i_oid;
    5924                 :     int         i_opfname;
    5925                 :     int         i_opfnamespace;
    5926                 :     int         i_opfowner;
    5927                 : 
    5928 GIC         118 :     query = createPQExpBuffer();
    5929                 : 
    5930 ECB             :     /*
    5931                 :      * find all opfamilies, including builtin opfamilies; we filter out
    5932                 :      * system-defined opfamilies at dump-out time.
    5933                 :      */
    5934                 : 
    5935 GNC         118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, opfname, "
    5936                 :                          "opfnamespace, "
    5937                 :                          "opfowner "
    5938                 :                          "FROM pg_opfamily");
    5939                 : 
    5940 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    5941                 : 
    5942             118 :     ntups = PQntuples(res);
    5943             118 :     *numOpfamilies = ntups;
    5944 ECB             : 
    5945 GIC         118 :     opfinfo = (OpfamilyInfo *) pg_malloc(ntups * sizeof(OpfamilyInfo));
    5946 EUB             : 
    5947 GBC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    5948 GIC         118 :     i_oid = PQfnumber(res, "oid");
    5949             118 :     i_opfname = PQfnumber(res, "opfname");
    5950 CBC         118 :     i_opfnamespace = PQfnumber(res, "opfnamespace");
    5951 GIC         118 :     i_opfowner = PQfnumber(res, "opfowner");
    5952                 : 
    5953 CBC       17471 :     for (i = 0; i < ntups; i++)
    5954                 :     {
    5955 GIC       17353 :         opfinfo[i].dobj.objType = DO_OPFAMILY;
    5956           17353 :         opfinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    5957 CBC       17353 :         opfinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    5958 GIC       17353 :         AssignDumpId(&opfinfo[i].dobj);
    5959 CBC       17353 :         opfinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opfname));
    5960           34706 :         opfinfo[i].dobj.namespace =
    5961 GIC       17353 :             findNamespace(atooid(PQgetvalue(res, i, i_opfnamespace)));
    5962 CBC       17353 :         opfinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_opfowner));
    5963                 : 
    5964 ECB             :         /* Decide whether we want to dump it */
    5965 CBC       17353 :         selectDumpableObject(&(opfinfo[i].dobj), fout);
    5966 ECB             :     }
    5967                 : 
    5968 CBC         118 :     PQclear(res);
    5969                 : 
    5970             118 :     destroyPQExpBuffer(query);
    5971                 : 
    5972             118 :     return opfinfo;
    5973 ECB             : }
    5974                 : 
    5975                 : /*
    5976                 :  * getAggregates:
    5977                 :  *    read all the user-defined aggregates in the system catalogs and
    5978                 :  * return them in the AggInfo* structure
    5979                 :  *
    5980                 :  * numAggs is set to the number of aggregates read in
    5981                 :  */
    5982                 : AggInfo *
    5983 GIC         118 : getAggregates(Archive *fout, int *numAggs)
    5984                 : {
    5985 CBC         118 :     DumpOptions *dopt = fout->dopt;
    5986                 :     PGresult   *res;
    5987 ECB             :     int         ntups;
    5988                 :     int         i;
    5989 CBC         118 :     PQExpBuffer query = createPQExpBuffer();
    5990                 :     AggInfo    *agginfo;
    5991                 :     int         i_tableoid;
    5992                 :     int         i_oid;
    5993                 :     int         i_aggname;
    5994                 :     int         i_aggnamespace;
    5995                 :     int         i_pronargs;
    5996                 :     int         i_proargtypes;
    5997                 :     int         i_proowner;
    5998                 :     int         i_aggacl;
    5999                 :     int         i_acldefault;
    6000                 : 
    6001 ECB             :     /*
    6002                 :      * Find all interesting aggregates.  See comment in getFuncs() for the
    6003                 :      * rationale behind the filtering logic.
    6004                 :      */
    6005 GIC         118 :     if (fout->remoteVersion >= 90600)
    6006 ECB             :     {
    6007                 :         const char *agg_check;
    6008                 : 
    6009 GIC         236 :         agg_check = (fout->remoteVersion >= 110000 ? "p.prokind = 'a'"
    6010             118 :                      : "p.proisagg");
    6011                 : 
    6012             118 :         appendPQExpBuffer(query, "SELECT p.tableoid, p.oid, "
    6013                 :                           "p.proname AS aggname, "
    6014                 :                           "p.pronamespace AS aggnamespace, "
    6015                 :                           "p.pronargs, p.proargtypes, "
    6016                 :                           "p.proowner, "
    6017                 :                           "p.proacl AS aggacl, "
    6018                 :                           "acldefault('f', p.proowner) AS acldefault "
    6019 ECB             :                           "FROM pg_proc p "
    6020                 :                           "LEFT JOIN pg_init_privs pip ON "
    6021                 :                           "(p.oid = pip.objoid "
    6022                 :                           "AND pip.classoid = 'pg_proc'::regclass "
    6023                 :                           "AND pip.objsubid = 0) "
    6024                 :                           "WHERE %s AND ("
    6025                 :                           "p.pronamespace != "
    6026                 :                           "(SELECT oid FROM pg_namespace "
    6027                 :                           "WHERE nspname = 'pg_catalog') OR "
    6028                 :                           "p.proacl IS DISTINCT FROM pip.initprivs",
    6029                 :                           agg_check);
    6030 GIC         118 :         if (dopt->binary_upgrade)
    6031 CBC           8 :             appendPQExpBufferStr(query,
    6032 ECB             :                                  " OR EXISTS(SELECT 1 FROM pg_depend WHERE "
    6033                 :                                  "classid = 'pg_proc'::regclass AND "
    6034                 :                                  "objid = p.oid AND "
    6035                 :                                  "refclassid = 'pg_extension'::regclass AND "
    6036                 :                                  "deptype = 'e')");
    6037 CBC         118 :         appendPQExpBufferChar(query, ')');
    6038                 :     }
    6039 ECB             :     else
    6040                 :     {
    6041 UNC           0 :         appendPQExpBufferStr(query, "SELECT tableoid, oid, proname AS aggname, "
    6042                 :                              "pronamespace AS aggnamespace, "
    6043                 :                              "pronargs, proargtypes, "
    6044                 :                              "proowner, "
    6045                 :                              "proacl AS aggacl, "
    6046                 :                              "acldefault('f', proowner) AS acldefault "
    6047                 :                              "FROM pg_proc p "
    6048                 :                              "WHERE proisagg AND ("
    6049                 :                              "pronamespace != "
    6050                 :                              "(SELECT oid FROM pg_namespace "
    6051                 :                              "WHERE nspname = 'pg_catalog')");
    6052 LBC           0 :         if (dopt->binary_upgrade)
    6053 UIC           0 :             appendPQExpBufferStr(query,
    6054 ECB             :                                  " OR EXISTS(SELECT 1 FROM pg_depend WHERE "
    6055                 :                                  "classid = 'pg_proc'::regclass AND "
    6056                 :                                  "objid = p.oid AND "
    6057                 :                                  "refclassid = 'pg_extension'::regclass AND "
    6058                 :                                  "deptype = 'e')");
    6059 UIC           0 :         appendPQExpBufferChar(query, ')');
    6060                 :     }
    6061                 : 
    6062 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    6063                 : 
    6064             118 :     ntups = PQntuples(res);
    6065             118 :     *numAggs = ntups;
    6066                 : 
    6067 CBC         118 :     agginfo = (AggInfo *) pg_malloc(ntups * sizeof(AggInfo));
    6068                 : 
    6069 GIC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    6070             118 :     i_oid = PQfnumber(res, "oid");
    6071             118 :     i_aggname = PQfnumber(res, "aggname");
    6072             118 :     i_aggnamespace = PQfnumber(res, "aggnamespace");
    6073             118 :     i_pronargs = PQfnumber(res, "pronargs");
    6074             118 :     i_proargtypes = PQfnumber(res, "proargtypes");
    6075             118 :     i_proowner = PQfnumber(res, "proowner");
    6076             118 :     i_aggacl = PQfnumber(res, "aggacl");
    6077             118 :     i_acldefault = PQfnumber(res, "acldefault");
    6078                 : 
    6079             420 :     for (i = 0; i < ntups; i++)
    6080 ECB             :     {
    6081 GIC         302 :         agginfo[i].aggfn.dobj.objType = DO_AGG;
    6082             302 :         agginfo[i].aggfn.dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    6083             302 :         agginfo[i].aggfn.dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    6084             302 :         AssignDumpId(&agginfo[i].aggfn.dobj);
    6085             302 :         agginfo[i].aggfn.dobj.name = pg_strdup(PQgetvalue(res, i, i_aggname));
    6086             604 :         agginfo[i].aggfn.dobj.namespace =
    6087 CBC         302 :             findNamespace(atooid(PQgetvalue(res, i, i_aggnamespace)));
    6088 GIC         302 :         agginfo[i].aggfn.dacl.acl = pg_strdup(PQgetvalue(res, i, i_aggacl));
    6089             302 :         agginfo[i].aggfn.dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
    6090             302 :         agginfo[i].aggfn.dacl.privtype = 0;
    6091             302 :         agginfo[i].aggfn.dacl.initprivs = NULL;
    6092 CBC         302 :         agginfo[i].aggfn.rolname = getRoleName(PQgetvalue(res, i, i_proowner));
    6093 GIC         302 :         agginfo[i].aggfn.lang = InvalidOid; /* not currently interesting */
    6094 CBC         302 :         agginfo[i].aggfn.prorettype = InvalidOid;   /* not saved */
    6095             302 :         agginfo[i].aggfn.nargs = atoi(PQgetvalue(res, i, i_pronargs));
    6096 GIC         302 :         if (agginfo[i].aggfn.nargs == 0)
    6097 CBC          40 :             agginfo[i].aggfn.argtypes = NULL;
    6098                 :         else
    6099 ECB             :         {
    6100 CBC         262 :             agginfo[i].aggfn.argtypes = (Oid *) pg_malloc(agginfo[i].aggfn.nargs * sizeof(Oid));
    6101             262 :             parseOidArray(PQgetvalue(res, i, i_proargtypes),
    6102             262 :                           agginfo[i].aggfn.argtypes,
    6103             262 :                           agginfo[i].aggfn.nargs);
    6104                 :         }
    6105 ECB             : 
    6106                 :         /* Decide whether we want to dump it */
    6107 CBC         302 :         selectDumpableObject(&(agginfo[i].aggfn.dobj), fout);
    6108 ECB             : 
    6109                 :         /* Mark whether aggregate has an ACL */
    6110 CBC         302 :         if (!PQgetisnull(res, i, i_aggacl))
    6111              22 :             agginfo[i].aggfn.dobj.components |= DUMP_COMPONENT_ACL;
    6112 ECB             :     }
    6113                 : 
    6114 CBC         118 :     PQclear(res);
    6115                 : 
    6116 GIC         118 :     destroyPQExpBuffer(query);
    6117 ECB             : 
    6118 GIC         118 :     return agginfo;
    6119                 : }
    6120 ECB             : 
    6121                 : /*
    6122                 :  * getFuncs:
    6123                 :  *    read all the user-defined functions in the system catalogs and
    6124                 :  * return them in the FuncInfo* structure
    6125                 :  *
    6126                 :  * numFuncs is set to the number of functions read in
    6127                 :  */
    6128                 : FuncInfo *
    6129 GIC         118 : getFuncs(Archive *fout, int *numFuncs)
    6130                 : {
    6131             118 :     DumpOptions *dopt = fout->dopt;
    6132                 :     PGresult   *res;
    6133                 :     int         ntups;
    6134                 :     int         i;
    6135 CBC         118 :     PQExpBuffer query = createPQExpBuffer();
    6136                 :     FuncInfo   *finfo;
    6137 ECB             :     int         i_tableoid;
    6138                 :     int         i_oid;
    6139                 :     int         i_proname;
    6140                 :     int         i_pronamespace;
    6141                 :     int         i_proowner;
    6142                 :     int         i_prolang;
    6143                 :     int         i_pronargs;
    6144                 :     int         i_proargtypes;
    6145                 :     int         i_prorettype;
    6146                 :     int         i_proacl;
    6147                 :     int         i_acldefault;
    6148                 : 
    6149                 :     /*
    6150                 :      * Find all interesting functions.  This is a bit complicated:
    6151                 :      *
    6152                 :      * 1. Always exclude aggregates; those are handled elsewhere.
    6153                 :      *
    6154                 :      * 2. Always exclude functions that are internally dependent on something
    6155                 :      * else, since presumably those will be created as a result of creating
    6156                 :      * the something else.  This currently acts only to suppress constructor
    6157                 :      * functions for range types.  Note this is OK only because the
    6158                 :      * constructors don't have any dependencies the range type doesn't have;
    6159                 :      * otherwise we might not get creation ordering correct.
    6160                 :      *
    6161                 :      * 3. Otherwise, we normally exclude functions in pg_catalog.  However, if
    6162                 :      * they're members of extensions and we are in binary-upgrade mode then
    6163                 :      * include them, since we want to dump extension members individually in
    6164                 :      * that mode.  Also, if they are used by casts or transforms then we need
    6165                 :      * to gather the information about them, though they won't be dumped if
    6166                 :      * they are built-in.  Also, in 9.6 and up, include functions in
    6167                 :      * pg_catalog if they have an ACL different from what's shown in
    6168                 :      * pg_init_privs (so we have to join to pg_init_privs; annoying).
    6169                 :      */
    6170 GIC         118 :     if (fout->remoteVersion >= 90600)
    6171                 :     {
    6172                 :         const char *not_agg_check;
    6173                 : 
    6174             236 :         not_agg_check = (fout->remoteVersion >= 110000 ? "p.prokind <> 'a'"
    6175             118 :                          : "NOT p.proisagg");
    6176                 : 
    6177             118 :         appendPQExpBuffer(query,
    6178                 :                           "SELECT p.tableoid, p.oid, p.proname, p.prolang, "
    6179                 :                           "p.pronargs, p.proargtypes, p.prorettype, "
    6180                 :                           "p.proacl, "
    6181                 :                           "acldefault('f', p.proowner) AS acldefault, "
    6182 ECB             :                           "p.pronamespace, "
    6183                 :                           "p.proowner "
    6184                 :                           "FROM pg_proc p "
    6185                 :                           "LEFT JOIN pg_init_privs pip ON "
    6186                 :                           "(p.oid = pip.objoid "
    6187                 :                           "AND pip.classoid = 'pg_proc'::regclass "
    6188                 :                           "AND pip.objsubid = 0) "
    6189                 :                           "WHERE %s"
    6190                 :                           "\n  AND NOT EXISTS (SELECT 1 FROM pg_depend "
    6191                 :                           "WHERE classid = 'pg_proc'::regclass AND "
    6192                 :                           "objid = p.oid AND deptype = 'i')"
    6193 EUB             :                           "\n  AND ("
    6194                 :                           "\n  pronamespace != "
    6195                 :                           "(SELECT oid FROM pg_namespace "
    6196                 :                           "WHERE nspname = 'pg_catalog')"
    6197                 :                           "\n  OR EXISTS (SELECT 1 FROM pg_cast"
    6198                 :                           "\n  WHERE pg_cast.oid > %u "
    6199                 :                           "\n  AND p.oid = pg_cast.castfunc)"
    6200                 :                           "\n  OR EXISTS (SELECT 1 FROM pg_transform"
    6201                 :                           "\n  WHERE pg_transform.oid > %u AND "
    6202                 :                           "\n  (p.oid = pg_transform.trffromsql"
    6203                 :                           "\n  OR p.oid = pg_transform.trftosql))",
    6204                 :                           not_agg_check,
    6205                 :                           g_last_builtin_oid,
    6206                 :                           g_last_builtin_oid);
    6207 GIC         118 :         if (dopt->binary_upgrade)
    6208               8 :             appendPQExpBufferStr(query,
    6209                 :                                  "\n  OR EXISTS(SELECT 1 FROM pg_depend WHERE "
    6210                 :                                  "classid = 'pg_proc'::regclass AND "
    6211 EUB             :                                  "objid = p.oid AND "
    6212                 :                                  "refclassid = 'pg_extension'::regclass AND "
    6213                 :                                  "deptype = 'e')");
    6214 CBC         118 :         appendPQExpBufferStr(query,
    6215                 :                              "\n  OR p.proacl IS DISTINCT FROM pip.initprivs");
    6216             118 :         appendPQExpBufferChar(query, ')');
    6217 ECB             :     }
    6218                 :     else
    6219                 :     {
    6220 UIC           0 :         appendPQExpBuffer(query,
    6221 ECB             :                           "SELECT tableoid, oid, proname, prolang, "
    6222                 :                           "pronargs, proargtypes, prorettype, proacl, "
    6223                 :                           "acldefault('f', proowner) AS acldefault, "
    6224                 :                           "pronamespace, "
    6225                 :                           "proowner "
    6226                 :                           "FROM pg_proc p "
    6227                 :                           "WHERE NOT proisagg"
    6228                 :                           "\n  AND NOT EXISTS (SELECT 1 FROM pg_depend "
    6229                 :                           "WHERE classid = 'pg_proc'::regclass AND "
    6230                 :                           "objid = p.oid AND deptype = 'i')"
    6231                 :                           "\n  AND ("
    6232                 :                           "\n  pronamespace != "
    6233                 :                           "(SELECT oid FROM pg_namespace "
    6234                 :                           "WHERE nspname = 'pg_catalog')"
    6235                 :                           "\n  OR EXISTS (SELECT 1 FROM pg_cast"
    6236                 :                           "\n  WHERE pg_cast.oid > '%u'::oid"
    6237                 :                           "\n  AND p.oid = pg_cast.castfunc)",
    6238                 :                           g_last_builtin_oid);
    6239                 : 
    6240 LBC           0 :         if (fout->remoteVersion >= 90500)
    6241               0 :             appendPQExpBuffer(query,
    6242 ECB             :                               "\n  OR EXISTS (SELECT 1 FROM pg_transform"
    6243                 :                               "\n  WHERE pg_transform.oid > '%u'::oid"
    6244                 :                               "\n  AND (p.oid = pg_transform.trffromsql"
    6245                 :                               "\n  OR p.oid = pg_transform.trftosql))",
    6246                 :                               g_last_builtin_oid);
    6247                 : 
    6248 LBC           0 :         if (dopt->binary_upgrade)
    6249               0 :             appendPQExpBufferStr(query,
    6250                 :                                  "\n  OR EXISTS(SELECT 1 FROM pg_depend WHERE "
    6251                 :                                  "classid = 'pg_proc'::regclass AND "
    6252 ECB             :                                  "objid = p.oid AND "
    6253                 :                                  "refclassid = 'pg_extension'::regclass AND "
    6254                 :                                  "deptype = 'e')");
    6255 LBC           0 :         appendPQExpBufferChar(query, ')');
    6256                 :     }
    6257                 : 
    6258 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    6259 ECB             : 
    6260 GIC         118 :     ntups = PQntuples(res);
    6261                 : 
    6262 CBC         118 :     *numFuncs = ntups;
    6263 ECB             : 
    6264 GIC         118 :     finfo = (FuncInfo *) pg_malloc0(ntups * sizeof(FuncInfo));
    6265                 : 
    6266 CBC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    6267 GIC         118 :     i_oid = PQfnumber(res, "oid");
    6268 CBC         118 :     i_proname = PQfnumber(res, "proname");
    6269 GIC         118 :     i_pronamespace = PQfnumber(res, "pronamespace");
    6270 CBC         118 :     i_proowner = PQfnumber(res, "proowner");
    6271 GIC         118 :     i_prolang = PQfnumber(res, "prolang");
    6272             118 :     i_pronargs = PQfnumber(res, "pronargs");
    6273             118 :     i_proargtypes = PQfnumber(res, "proargtypes");
    6274             118 :     i_prorettype = PQfnumber(res, "prorettype");
    6275             118 :     i_proacl = PQfnumber(res, "proacl");
    6276             118 :     i_acldefault = PQfnumber(res, "acldefault");
    6277                 : 
    6278            3364 :     for (i = 0; i < ntups; i++)
    6279                 :     {
    6280            3246 :         finfo[i].dobj.objType = DO_FUNC;
    6281 CBC        3246 :         finfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    6282 GIC        3246 :         finfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    6283 CBC        3246 :         AssignDumpId(&finfo[i].dobj);
    6284 GIC        3246 :         finfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_proname));
    6285            6492 :         finfo[i].dobj.namespace =
    6286            3246 :             findNamespace(atooid(PQgetvalue(res, i, i_pronamespace)));
    6287 CBC        3246 :         finfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_proacl));
    6288 GIC        3246 :         finfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
    6289            3246 :         finfo[i].dacl.privtype = 0;
    6290            3246 :         finfo[i].dacl.initprivs = NULL;
    6291            3246 :         finfo[i].rolname = getRoleName(PQgetvalue(res, i, i_proowner));
    6292            3246 :         finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
    6293            3246 :         finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
    6294            3246 :         finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
    6295            3246 :         if (finfo[i].nargs == 0)
    6296             737 :             finfo[i].argtypes = NULL;
    6297                 :         else
    6298                 :         {
    6299            2509 :             finfo[i].argtypes = (Oid *) pg_malloc(finfo[i].nargs * sizeof(Oid));
    6300            2509 :             parseOidArray(PQgetvalue(res, i, i_proargtypes),
    6301            2509 :                           finfo[i].argtypes, finfo[i].nargs);
    6302                 :         }
    6303                 : 
    6304                 :         /* Decide whether we want to dump it */
    6305            3246 :         selectDumpableObject(&(finfo[i].dobj), fout);
    6306                 : 
    6307                 :         /* Mark whether function has an ACL */
    6308            3246 :         if (!PQgetisnull(res, i, i_proacl))
    6309             134 :             finfo[i].dobj.components |= DUMP_COMPONENT_ACL;
    6310                 :     }
    6311                 : 
    6312             118 :     PQclear(res);
    6313                 : 
    6314             118 :     destroyPQExpBuffer(query);
    6315                 : 
    6316             118 :     return finfo;
    6317                 : }
    6318                 : 
    6319                 : /*
    6320                 :  * getTables
    6321                 :  *    read all the tables (no indexes) in the system catalogs,
    6322 ECB             :  *    and return them as an array of TableInfo structures
    6323                 :  *
    6324                 :  * *numTables is set to the number of tables read in
    6325                 :  */
    6326                 : TableInfo *
    6327 CBC         119 : getTables(Archive *fout, int *numTables)
    6328                 : {
    6329             119 :     DumpOptions *dopt = fout->dopt;
    6330                 :     PGresult   *res;
    6331                 :     int         ntups;
    6332                 :     int         i;
    6333 GIC         119 :     PQExpBuffer query = createPQExpBuffer();
    6334                 :     TableInfo  *tblinfo;
    6335                 :     int         i_reltableoid;
    6336                 :     int         i_reloid;
    6337                 :     int         i_relname;
    6338                 :     int         i_relnamespace;
    6339                 :     int         i_relkind;
    6340                 :     int         i_reltype;
    6341                 :     int         i_relowner;
    6342                 :     int         i_relchecks;
    6343                 :     int         i_relhasindex;
    6344                 :     int         i_relhasrules;
    6345                 :     int         i_relpages;
    6346                 :     int         i_toastpages;
    6347                 :     int         i_owning_tab;
    6348                 :     int         i_owning_col;
    6349                 :     int         i_reltablespace;
    6350                 :     int         i_relhasoids;
    6351                 :     int         i_relhastriggers;
    6352                 :     int         i_relpersistence;
    6353                 :     int         i_relispopulated;
    6354                 :     int         i_relreplident;
    6355                 :     int         i_relrowsec;
    6356                 :     int         i_relforcerowsec;
    6357                 :     int         i_relfrozenxid;
    6358                 :     int         i_toastfrozenxid;
    6359 ECB             :     int         i_toastoid;
    6360                 :     int         i_relminmxid;
    6361                 :     int         i_toastminmxid;
    6362                 :     int         i_reloptions;
    6363                 :     int         i_checkoption;
    6364                 :     int         i_toastreloptions;
    6365                 :     int         i_reloftype;
    6366                 :     int         i_foreignserver;
    6367                 :     int         i_amname;
    6368                 :     int         i_is_identity_sequence;
    6369                 :     int         i_relacl;
    6370                 :     int         i_acldefault;
    6371                 :     int         i_ispartition;
    6372 EUB             : 
    6373                 :     /*
    6374                 :      * Find all the tables and table-like objects.
    6375                 :      *
    6376                 :      * We must fetch all tables in this phase because otherwise we cannot
    6377                 :      * correctly identify inherited columns, owned sequences, etc.
    6378                 :      *
    6379                 :      * We include system catalogs, so that we can work if a user table is
    6380                 :      * defined to inherit from a system catalog (pretty weird, but...)
    6381                 :      *
    6382                 :      * Note: in this phase we should collect only a minimal amount of
    6383                 :      * information about each table, basically just enough to decide if it is
    6384                 :      * interesting.  In particular, since we do not yet have lock on any user
    6385                 :      * table, we MUST NOT invoke any server-side data collection functions
    6386                 :      * (for instance, pg_get_partkeydef()).  Those are likely to fail or give
    6387                 :      * wrong answers if any concurrent DDL is happening.
    6388                 :      */
    6389                 : 
    6390 GNC         119 :     appendPQExpBufferStr(query,
    6391                 :                          "SELECT c.tableoid, c.oid, c.relname, "
    6392                 :                          "c.relnamespace, c.relkind, c.reltype, "
    6393                 :                          "c.relowner, "
    6394                 :                          "c.relchecks, "
    6395                 :                          "c.relhasindex, c.relhasrules, c.relpages, "
    6396                 :                          "c.relhastriggers, "
    6397                 :                          "c.relpersistence, "
    6398                 :                          "c.reloftype, "
    6399                 :                          "c.relacl, "
    6400                 :                          "acldefault(CASE WHEN c.relkind = " CppAsString2(RELKIND_SEQUENCE)
    6401                 :                          " THEN 's'::\"char\" ELSE 'r'::\"char\" END, c.relowner) AS acldefault, "
    6402                 :                          "CASE WHEN c.relkind = " CppAsString2(RELKIND_FOREIGN_TABLE) " THEN "
    6403                 :                          "(SELECT ftserver FROM pg_catalog.pg_foreign_table WHERE ftrelid = c.oid) "
    6404                 :                          "ELSE 0 END AS foreignserver, "
    6405                 :                          "c.relfrozenxid, tc.relfrozenxid AS tfrozenxid, "
    6406                 :                          "tc.oid AS toid, "
    6407                 :                          "tc.relpages AS toastpages, "
    6408                 :                          "tc.reloptions AS toast_reloptions, "
    6409                 :                          "d.refobjid AS owning_tab, "
    6410                 :                          "d.refobjsubid AS owning_col, "
    6411                 :                          "tsp.spcname AS reltablespace, ");
    6412 ECB             : 
    6413 GIC         119 :     if (fout->remoteVersion >= 120000)
    6414 CBC         119 :         appendPQExpBufferStr(query,
    6415                 :                              "false AS relhasoids, ");
    6416 ECB             :     else
    6417 UIC           0 :         appendPQExpBufferStr(query,
    6418 ECB             :                              "c.relhasoids, ");
    6419                 : 
    6420 CBC         119 :     if (fout->remoteVersion >= 90300)
    6421             119 :         appendPQExpBufferStr(query,
    6422 ECB             :                              "c.relispopulated, ");
    6423                 :     else
    6424 LBC           0 :         appendPQExpBufferStr(query,
    6425 ECB             :                              "'t' as relispopulated, ");
    6426                 : 
    6427 CBC         119 :     if (fout->remoteVersion >= 90400)
    6428             119 :         appendPQExpBufferStr(query,
    6429                 :                              "c.relreplident, ");
    6430 ECB             :     else
    6431 UIC           0 :         appendPQExpBufferStr(query,
    6432 ECB             :                              "'d' AS relreplident, ");
    6433                 : 
    6434 CBC         119 :     if (fout->remoteVersion >= 90500)
    6435             119 :         appendPQExpBufferStr(query,
    6436 ECB             :                              "c.relrowsecurity, c.relforcerowsecurity, ");
    6437                 :     else
    6438 LBC           0 :         appendPQExpBufferStr(query,
    6439 ECB             :                              "false AS relrowsecurity, "
    6440                 :                              "false AS relforcerowsecurity, ");
    6441                 : 
    6442 CBC         119 :     if (fout->remoteVersion >= 90300)
    6443             119 :         appendPQExpBufferStr(query,
    6444 ECB             :                              "c.relminmxid, tc.relminmxid AS tminmxid, ");
    6445                 :     else
    6446 LBC           0 :         appendPQExpBufferStr(query,
    6447 ECB             :                              "0 AS relminmxid, 0 AS tminmxid, ");
    6448                 : 
    6449 GIC         119 :     if (fout->remoteVersion >= 90300)
    6450             119 :         appendPQExpBufferStr(query,
    6451 ECB             :                              "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
    6452                 :                              "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
    6453                 :                              "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, ");
    6454                 :     else
    6455 UIC           0 :         appendPQExpBufferStr(query,
    6456                 :                              "c.reloptions, NULL AS checkoption, ");
    6457 ECB             : 
    6458 GIC         119 :     if (fout->remoteVersion >= 90600)
    6459             119 :         appendPQExpBufferStr(query,
    6460 ECB             :                              "am.amname, ");
    6461                 :     else
    6462 UIC           0 :         appendPQExpBufferStr(query,
    6463                 :                              "NULL AS amname, ");
    6464 ECB             : 
    6465 GIC         119 :     if (fout->remoteVersion >= 90600)
    6466 CBC         119 :         appendPQExpBufferStr(query,
    6467                 :                              "(d.deptype = 'i') IS TRUE AS is_identity_sequence, ");
    6468 ECB             :     else
    6469 UIC           0 :         appendPQExpBufferStr(query,
    6470                 :                              "false AS is_identity_sequence, ");
    6471                 : 
    6472 GIC         119 :     if (fout->remoteVersion >= 100000)
    6473             119 :         appendPQExpBufferStr(query,
    6474                 :                              "c.relispartition AS ispartition ");
    6475                 :     else
    6476 UIC           0 :         appendPQExpBufferStr(query,
    6477                 :                              "false AS ispartition ");
    6478                 : 
    6479 ECB             :     /*
    6480                 :      * Left join to pg_depend to pick up dependency info linking sequences to
    6481                 :      * their owning column, if any (note this dependency is AUTO except for
    6482                 :      * identity sequences, where it's INTERNAL). Also join to pg_tablespace to
    6483                 :      * collect the spcname.
    6484                 :      */
    6485 CBC         119 :     appendPQExpBufferStr(query,
    6486                 :                          "\nFROM pg_class c\n"
    6487                 :                          "LEFT JOIN pg_depend d ON "
    6488                 :                          "(c.relkind = " CppAsString2(RELKIND_SEQUENCE) " AND "
    6489                 :                          "d.classid = 'pg_class'::regclass AND d.objid = c.oid AND "
    6490                 :                          "d.objsubid = 0 AND "
    6491                 :                          "d.refclassid = 'pg_class'::regclass AND d.deptype IN ('a', 'i'))\n"
    6492                 :                          "LEFT JOIN pg_tablespace tsp ON (tsp.oid = c.reltablespace)\n");
    6493                 : 
    6494                 :     /*
    6495                 :      * In 9.6 and up, left join to pg_am to pick up the amname.
    6496                 :      */
    6497 GIC         119 :     if (fout->remoteVersion >= 90600)
    6498             119 :         appendPQExpBufferStr(query,
    6499                 :                              "LEFT JOIN pg_am am ON (c.relam = am.oid)\n");
    6500                 : 
    6501                 :     /*
    6502                 :      * We purposefully ignore toast OIDs for partitioned tables; the reason is
    6503                 :      * that versions 10 and 11 have them, but later versions do not, so
    6504                 :      * emitting them causes the upgrade to fail.
    6505                 :      */
    6506             119 :     appendPQExpBufferStr(query,
    6507                 :                          "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid"
    6508                 :                          " AND tc.relkind = " CppAsString2(RELKIND_TOASTVALUE)
    6509                 :                          " AND c.relkind <> " CppAsString2(RELKIND_PARTITIONED_TABLE) ")\n");
    6510                 : 
    6511                 :     /*
    6512                 :      * Restrict to interesting relkinds (in particular, not indexes).  Not all
    6513                 :      * relkinds are possible in older servers, but it's not worth the trouble
    6514                 :      * to emit a version-dependent list.
    6515                 :      *
    6516                 :      * Composite-type table entries won't be dumped as such, but we have to
    6517                 :      * make a DumpableObject for them so that we can track dependencies of the
    6518                 :      * composite type (pg_depend entries for columns of the composite type
    6519                 :      * link to the pg_class entry not the pg_type entry).
    6520                 :      */
    6521             119 :     appendPQExpBufferStr(query,
    6522                 :                          "WHERE c.relkind IN ("
    6523                 :                          CppAsString2(RELKIND_RELATION) ", "
    6524                 :                          CppAsString2(RELKIND_SEQUENCE) ", "
    6525                 :                          CppAsString2(RELKIND_VIEW) ", "
    6526                 :                          CppAsString2(RELKIND_COMPOSITE_TYPE) ", "
    6527                 :                          CppAsString2(RELKIND_MATVIEW) ", "
    6528                 :                          CppAsString2(RELKIND_FOREIGN_TABLE) ", "
    6529                 :                          CppAsString2(RELKIND_PARTITIONED_TABLE) ")\n"
    6530                 :                          "ORDER BY c.oid");
    6531                 : 
    6532             119 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    6533                 : 
    6534             119 :     ntups = PQntuples(res);
    6535                 : 
    6536             119 :     *numTables = ntups;
    6537                 : 
    6538                 :     /*
    6539                 :      * Extract data from result and lock dumpable tables.  We do the locking
    6540                 :      * before anything else, to minimize the window wherein a table could
    6541                 :      * disappear under us.
    6542 ECB             :      *
    6543                 :      * Note that we have to save info about all tables here, even when dumping
    6544                 :      * only one, because we don't yet know which tables might be inheritance
    6545                 :      * ancestors of the target table.
    6546                 :      */
    6547 GIC         119 :     tblinfo = (TableInfo *) pg_malloc0(ntups * sizeof(TableInfo));
    6548                 : 
    6549             119 :     i_reltableoid = PQfnumber(res, "tableoid");
    6550             119 :     i_reloid = PQfnumber(res, "oid");
    6551             119 :     i_relname = PQfnumber(res, "relname");
    6552             119 :     i_relnamespace = PQfnumber(res, "relnamespace");
    6553             119 :     i_relkind = PQfnumber(res, "relkind");
    6554             119 :     i_reltype = PQfnumber(res, "reltype");
    6555             119 :     i_relowner = PQfnumber(res, "relowner");
    6556             119 :     i_relchecks = PQfnumber(res, "relchecks");
    6557             119 :     i_relhasindex = PQfnumber(res, "relhasindex");
    6558             119 :     i_relhasrules = PQfnumber(res, "relhasrules");
    6559             119 :     i_relpages = PQfnumber(res, "relpages");
    6560             119 :     i_toastpages = PQfnumber(res, "toastpages");
    6561             119 :     i_owning_tab = PQfnumber(res, "owning_tab");
    6562             119 :     i_owning_col = PQfnumber(res, "owning_col");
    6563             119 :     i_reltablespace = PQfnumber(res, "reltablespace");
    6564             119 :     i_relhasoids = PQfnumber(res, "relhasoids");
    6565 CBC         119 :     i_relhastriggers = PQfnumber(res, "relhastriggers");
    6566             119 :     i_relpersistence = PQfnumber(res, "relpersistence");
    6567 GIC         119 :     i_relispopulated = PQfnumber(res, "relispopulated");
    6568             119 :     i_relreplident = PQfnumber(res, "relreplident");
    6569 GBC         119 :     i_relrowsec = PQfnumber(res, "relrowsecurity");
    6570 GIC         119 :     i_relforcerowsec = PQfnumber(res, "relforcerowsecurity");
    6571             119 :     i_relfrozenxid = PQfnumber(res, "relfrozenxid");
    6572 CBC         119 :     i_toastfrozenxid = PQfnumber(res, "tfrozenxid");
    6573             119 :     i_toastoid = PQfnumber(res, "toid");
    6574 GIC         119 :     i_relminmxid = PQfnumber(res, "relminmxid");
    6575             119 :     i_toastminmxid = PQfnumber(res, "tminmxid");
    6576 GBC         119 :     i_reloptions = PQfnumber(res, "reloptions");
    6577 GIC         119 :     i_checkoption = PQfnumber(res, "checkoption");
    6578             119 :     i_toastreloptions = PQfnumber(res, "toast_reloptions");
    6579 CBC         119 :     i_reloftype = PQfnumber(res, "reloftype");
    6580             119 :     i_foreignserver = PQfnumber(res, "foreignserver");
    6581 GIC         119 :     i_amname = PQfnumber(res, "amname");
    6582             119 :     i_is_identity_sequence = PQfnumber(res, "is_identity_sequence");
    6583 GBC         119 :     i_relacl = PQfnumber(res, "relacl");
    6584 GIC         119 :     i_acldefault = PQfnumber(res, "acldefault");
    6585             119 :     i_ispartition = PQfnumber(res, "ispartition");
    6586 ECB             : 
    6587 CBC         119 :     if (dopt->lockWaitTimeout)
    6588                 :     {
    6589                 :         /*
    6590 EUB             :          * Arrange to fail instead of waiting forever for a table lock.
    6591                 :          *
    6592                 :          * NB: this coding assumes that the only queries issued within the
    6593                 :          * following loop are LOCK TABLEs; else the timeout may be undesirably
    6594 ECB             :          * applied to other things too.
    6595                 :          */
    6596 GIC           2 :         resetPQExpBuffer(query);
    6597               2 :         appendPQExpBufferStr(query, "SET statement_timeout = ");
    6598 GBC           2 :         appendStringLiteralConn(query, dopt->lockWaitTimeout, GetConnection(fout));
    6599 GIC           2 :         ExecuteSqlStatement(fout, query->data);
    6600                 :     }
    6601 ECB             : 
    6602 GNC         119 :     resetPQExpBuffer(query);
    6603                 : 
    6604 CBC       30724 :     for (i = 0; i < ntups; i++)
    6605                 :     {
    6606 GIC       30605 :         tblinfo[i].dobj.objType = DO_TABLE;
    6607           30605 :         tblinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_reltableoid));
    6608           30605 :         tblinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_reloid));
    6609 GBC       30605 :         AssignDumpId(&tblinfo[i].dobj);
    6610 GIC       30605 :         tblinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_relname));
    6611           61210 :         tblinfo[i].dobj.namespace =
    6612 CBC       30605 :             findNamespace(atooid(PQgetvalue(res, i, i_relnamespace)));
    6613           30605 :         tblinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_relacl));
    6614 GIC       30605 :         tblinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
    6615           30605 :         tblinfo[i].dacl.privtype = 0;
    6616 GBC       30605 :         tblinfo[i].dacl.initprivs = NULL;
    6617 GIC       30605 :         tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind));
    6618           30605 :         tblinfo[i].reltype = atooid(PQgetvalue(res, i, i_reltype));
    6619 CBC       30605 :         tblinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_relowner));
    6620           30605 :         tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks));
    6621 GIC       30605 :         tblinfo[i].hasindex = (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0);
    6622           30605 :         tblinfo[i].hasrules = (strcmp(PQgetvalue(res, i, i_relhasrules), "t") == 0);
    6623 GBC       30605 :         tblinfo[i].relpages = atoi(PQgetvalue(res, i, i_relpages));
    6624 GIC       30605 :         if (PQgetisnull(res, i, i_toastpages))
    6625           24303 :             tblinfo[i].toastpages = 0;
    6626 ECB             :         else
    6627 CBC        6302 :             tblinfo[i].toastpages = atoi(PQgetvalue(res, i, i_toastpages));
    6628 GIC       30605 :         if (PQgetisnull(res, i, i_owning_tab))
    6629                 :         {
    6630 GBC       30330 :             tblinfo[i].owning_tab = InvalidOid;
    6631 GIC       30330 :             tblinfo[i].owning_col = 0;
    6632                 :         }
    6633                 :         else
    6634                 :         {
    6635             275 :             tblinfo[i].owning_tab = atooid(PQgetvalue(res, i, i_owning_tab));
    6636             275 :             tblinfo[i].owning_col = atoi(PQgetvalue(res, i, i_owning_col));
    6637                 :         }
    6638           30605 :         tblinfo[i].reltablespace = pg_strdup(PQgetvalue(res, i, i_reltablespace));
    6639 CBC       30605 :         tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
    6640 GIC       30605 :         tblinfo[i].hastriggers = (strcmp(PQgetvalue(res, i, i_relhastriggers), "t") == 0);
    6641           30605 :         tblinfo[i].relpersistence = *(PQgetvalue(res, i, i_relpersistence));
    6642           30605 :         tblinfo[i].relispopulated = (strcmp(PQgetvalue(res, i, i_relispopulated), "t") == 0);
    6643           30605 :         tblinfo[i].relreplident = *(PQgetvalue(res, i, i_relreplident));
    6644           30605 :         tblinfo[i].rowsec = (strcmp(PQgetvalue(res, i, i_relrowsec), "t") == 0);
    6645           30605 :         tblinfo[i].forcerowsec = (strcmp(PQgetvalue(res, i, i_relforcerowsec), "t") == 0);
    6646           30605 :         tblinfo[i].frozenxid = atooid(PQgetvalue(res, i, i_relfrozenxid));
    6647           30605 :         tblinfo[i].toast_frozenxid = atooid(PQgetvalue(res, i, i_toastfrozenxid));
    6648           30605 :         tblinfo[i].toast_oid = atooid(PQgetvalue(res, i, i_toastoid));
    6649           30605 :         tblinfo[i].minmxid = atooid(PQgetvalue(res, i, i_relminmxid));
    6650           30605 :         tblinfo[i].toast_minmxid = atooid(PQgetvalue(res, i, i_toastminmxid));
    6651 CBC       30605 :         tblinfo[i].reloptions = pg_strdup(PQgetvalue(res, i, i_reloptions));
    6652           30605 :         if (PQgetisnull(res, i, i_checkoption))
    6653 GIC       30559 :             tblinfo[i].checkoption = NULL;
    6654                 :         else
    6655              46 :             tblinfo[i].checkoption = pg_strdup(PQgetvalue(res, i, i_checkoption));
    6656           30605 :         tblinfo[i].toast_reloptions = pg_strdup(PQgetvalue(res, i, i_toastreloptions));
    6657           30605 :         tblinfo[i].reloftype = atooid(PQgetvalue(res, i, i_reloftype));
    6658           30605 :         tblinfo[i].foreign_server = atooid(PQgetvalue(res, i, i_foreignserver));
    6659           30605 :         if (PQgetisnull(res, i, i_amname))
    6660 CBC       18182 :             tblinfo[i].amname = NULL;
    6661                 :         else
    6662 GIC       12423 :             tblinfo[i].amname = pg_strdup(PQgetvalue(res, i, i_amname));
    6663           30605 :         tblinfo[i].is_identity_sequence = (strcmp(PQgetvalue(res, i, i_is_identity_sequence), "t") == 0);
    6664           30605 :         tblinfo[i].ispartition = (strcmp(PQgetvalue(res, i, i_ispartition), "t") == 0);
    6665                 : 
    6666                 :         /* other fields were zeroed above */
    6667                 : 
    6668                 :         /*
    6669                 :          * Decide whether we want to dump this table.
    6670                 :          */
    6671           30605 :         if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
    6672             138 :             tblinfo[i].dobj.dump = DUMP_COMPONENT_NONE;
    6673                 :         else
    6674           30467 :             selectDumpableTable(&tblinfo[i], fout);
    6675 ECB             : 
    6676                 :         /*
    6677                 :          * Now, consider the table "interesting" if we need to dump its
    6678                 :          * definition or its data.  Later on, we'll skip a lot of data
    6679                 :          * collection for uninteresting tables.
    6680                 :          *
    6681                 :          * Note: the "interesting" flag will also be set by flagInhTables for
    6682                 :          * parents of interesting tables, so that we collect necessary
    6683                 :          * inheritance info even when the parents are not themselves being
    6684                 :          * dumped.  This is the main reason why we need an "interesting" flag
    6685                 :          * that's separate from the components-to-dump bitmask.
    6686                 :          */
    6687 GIC       30605 :         tblinfo[i].interesting = (tblinfo[i].dobj.dump &
    6688 ECB             :                                   (DUMP_COMPONENT_DEFINITION |
    6689 GIC       30605 :                                    DUMP_COMPONENT_DATA)) != 0;
    6690 ECB             : 
    6691 GIC       30605 :         tblinfo[i].dummy_view = false;  /* might get set during sort */
    6692           30605 :         tblinfo[i].postponed_def = false;   /* might get set during sort */
    6693                 : 
    6694                 :         /* Tables have data */
    6695           30605 :         tblinfo[i].dobj.components |= DUMP_COMPONENT_DATA;
    6696                 : 
    6697                 :         /* Mark whether table has an ACL */
    6698           30605 :         if (!PQgetisnull(res, i, i_relacl))
    6699           24515 :             tblinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
    6700           30605 :         tblinfo[i].hascolumnACLs = false;   /* may get set later */
    6701 ECB             : 
    6702                 :         /*
    6703                 :          * Read-lock target tables to make sure they aren't DROPPED or altered
    6704                 :          * in schema before we get around to dumping them.
    6705                 :          *
    6706                 :          * Note that we don't explicitly lock parents of the target tables; we
    6707                 :          * assume our lock on the child is enough to prevent schema
    6708                 :          * alterations to parent tables.
    6709                 :          *
    6710                 :          * NOTE: it'd be kinda nice to lock other relations too, not only
    6711                 :          * plain or partitioned tables, but the backend doesn't presently
    6712                 :          * allow that.
    6713                 :          *
    6714                 :          * We only need to lock the table for certain components; see
    6715                 :          * pg_dump.h
    6716                 :          */
    6717 CBC       30605 :         if ((tblinfo[i].dobj.dump & DUMP_COMPONENTS_REQUIRING_LOCK) &&
    6718            5328 :             (tblinfo[i].relkind == RELKIND_RELATION ||
    6719            1563 :              tblinfo[i].relkind == RELKIND_PARTITIONED_TABLE))
    6720 ECB             :         {
    6721                 :             /*
    6722                 :              * Tables are locked in batches.  When dumping from a remote
    6723                 :              * server this can save a significant amount of time by reducing
    6724                 :              * the number of round trips.
    6725                 :              */
    6726 GNC        4239 :             if (query->len == 0)
    6727              76 :                 appendPQExpBuffer(query, "LOCK TABLE %s",
    6728              76 :                                   fmtQualifiedDumpable(&tblinfo[i]));
    6729                 :             else
    6730                 :             {
    6731            4163 :                 appendPQExpBuffer(query, ", %s",
    6732            4163 :                                   fmtQualifiedDumpable(&tblinfo[i]));
    6733                 : 
    6734                 :                 /* Arbitrarily end a batch when query length reaches 100K. */
    6735            4163 :                 if (query->len >= 100000)
    6736                 :                 {
    6737                 :                     /* Lock another batch of tables. */
    6738 UNC           0 :                     appendPQExpBufferStr(query, " IN ACCESS SHARE MODE");
    6739               0 :                     ExecuteSqlStatement(fout, query->data);
    6740               0 :                     resetPQExpBuffer(query);
    6741                 :                 }
    6742                 :             }
    6743 ECB             :         }
    6744                 :     }
    6745                 : 
    6746 GNC         119 :     if (query->len != 0)
    6747                 :     {
    6748                 :         /* Lock the tables in the last batch. */
    6749              76 :         appendPQExpBufferStr(query, " IN ACCESS SHARE MODE");
    6750              76 :         ExecuteSqlStatement(fout, query->data);
    6751                 :     }
    6752                 : 
    6753 CBC         118 :     if (dopt->lockWaitTimeout)
    6754 ECB             :     {
    6755 CBC           2 :         ExecuteSqlStatement(fout, "SET statement_timeout = 0");
    6756 ECB             :     }
    6757                 : 
    6758 CBC         118 :     PQclear(res);
    6759 ECB             : 
    6760 CBC         118 :     destroyPQExpBuffer(query);
    6761 ECB             : 
    6762 CBC         118 :     return tblinfo;
    6763 ECB             : }
    6764                 : 
    6765                 : /*
    6766                 :  * getOwnedSeqs
    6767                 :  *    identify owned sequences and mark them as dumpable if owning table is
    6768                 :  *
    6769                 :  * We used to do this in getTables(), but it's better to do it after the
    6770                 :  * index used by findTableByOid() has been set up.
    6771                 :  */
    6772                 : void
    6773 GIC         118 : getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables)
    6774 ECB             : {
    6775                 :     int         i;
    6776                 : 
    6777                 :     /*
    6778                 :      * Force sequences that are "owned" by table columns to be dumped whenever
    6779                 :      * their owning table is being dumped.
    6780                 :      */
    6781 GIC       30474 :     for (i = 0; i < numTables; i++)
    6782 ECB             :     {
    6783 GIC       30356 :         TableInfo  *seqinfo = &tblinfo[i];
    6784 ECB             :         TableInfo  *owning_tab;
    6785                 : 
    6786 CBC       30356 :         if (!OidIsValid(seqinfo->owning_tab))
    6787           30084 :             continue;           /* not an owned sequence */
    6788 ECB             : 
    6789 CBC         272 :         owning_tab = findTableByOid(seqinfo->owning_tab);
    6790             272 :         if (owning_tab == NULL)
    6791 LBC           0 :             pg_fatal("failed sanity check, parent table with OID %u of sequence with OID %u not found",
    6792 ECB             :                      seqinfo->owning_tab, seqinfo->dobj.catId.oid);
    6793                 : 
    6794                 :         /*
    6795                 :          * Only dump identity sequences if we're going to dump the table that
    6796                 :          * it belongs to.
    6797                 :          */
    6798 CBC         272 :         if (owning_tab->dobj.dump == DUMP_COMPONENT_NONE &&
    6799              21 :             seqinfo->is_identity_sequence)
    6800 ECB             :         {
    6801 CBC           6 :             seqinfo->dobj.dump = DUMP_COMPONENT_NONE;
    6802               6 :             continue;
    6803 ECB             :         }
    6804                 : 
    6805                 :         /*
    6806                 :          * Otherwise we need to dump the components that are being dumped for
    6807                 :          * the table and any components which the sequence is explicitly
    6808                 :          * marked with.
    6809                 :          *
    6810                 :          * We can't simply use the set of components which are being dumped
    6811                 :          * for the table as the table might be in an extension (and only the
    6812                 :          * non-extension components, eg: ACLs if changed, security labels, and
    6813                 :          * policies, are being dumped) while the sequence is not (and
    6814                 :          * therefore the definition and other components should also be
    6815                 :          * dumped).
    6816                 :          *
    6817                 :          * If the sequence is part of the extension then it should be properly
    6818                 :          * marked by checkExtensionMembership() and this will be a no-op as
    6819                 :          * the table will be equivalently marked.
    6820                 :          */
    6821 CBC         266 :         seqinfo->dobj.dump = seqinfo->dobj.dump | owning_tab->dobj.dump;
    6822 ECB             : 
    6823 CBC         266 :         if (seqinfo->dobj.dump != DUMP_COMPONENT_NONE)
    6824             253 :             seqinfo->interesting = true;
    6825 ECB             :     }
    6826 CBC         118 : }
    6827 ECB             : 
    6828                 : /*
    6829                 :  * getInherits
    6830                 :  *    read all the inheritance information
    6831                 :  * from the system catalogs return them in the InhInfo* structure
    6832                 :  *
    6833                 :  * numInherits is set to the number of pairs read in
    6834                 :  */
    6835                 : InhInfo *
    6836 CBC         118 : getInherits(Archive *fout, int *numInherits)
    6837 ECB             : {
    6838                 :     PGresult   *res;
    6839                 :     int         ntups;
    6840                 :     int         i;
    6841 CBC         118 :     PQExpBuffer query = createPQExpBuffer();
    6842 ECB             :     InhInfo    *inhinfo;
    6843                 : 
    6844                 :     int         i_inhrelid;
    6845                 :     int         i_inhparent;
    6846                 : 
    6847                 :     /* find all the inheritance information */
    6848 GIC         118 :     appendPQExpBufferStr(query, "SELECT inhrelid, inhparent FROM pg_inherits");
    6849 ECB             : 
    6850 CBC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    6851                 : 
    6852             118 :     ntups = PQntuples(res);
    6853                 : 
    6854 GIC         118 :     *numInherits = ntups;
    6855                 : 
    6856             118 :     inhinfo = (InhInfo *) pg_malloc(ntups * sizeof(InhInfo));
    6857                 : 
    6858             118 :     i_inhrelid = PQfnumber(res, "inhrelid");
    6859             118 :     i_inhparent = PQfnumber(res, "inhparent");
    6860                 : 
    6861            2272 :     for (i = 0; i < ntups; i++)
    6862                 :     {
    6863            2154 :         inhinfo[i].inhrelid = atooid(PQgetvalue(res, i, i_inhrelid));
    6864            2154 :         inhinfo[i].inhparent = atooid(PQgetvalue(res, i, i_inhparent));
    6865 ECB             :     }
    6866                 : 
    6867 CBC         118 :     PQclear(res);
    6868                 : 
    6869             118 :     destroyPQExpBuffer(query);
    6870 ECB             : 
    6871 GIC         118 :     return inhinfo;
    6872                 : }
    6873 ECB             : 
    6874                 : /*
    6875                 :  * getPartitioningInfo
    6876                 :  *    get information about partitioning
    6877                 :  *
    6878                 :  * For the most part, we only collect partitioning info about tables we
    6879                 :  * intend to dump.  However, this function has to consider all partitioned
    6880                 :  * tables in the database, because we need to know about parents of partitions
    6881                 :  * we are going to dump even if the parents themselves won't be dumped.
    6882                 :  *
    6883                 :  * Specifically, what we need to know is whether each partitioned table
    6884                 :  * has an "unsafe" partitioning scheme that requires us to force
    6885                 :  * load-via-partition-root mode for its children.  Currently the only case
    6886                 :  * for which we force that is hash partitioning on enum columns, since the
    6887                 :  * hash codes depend on enum value OIDs which won't be replicated across
    6888                 :  * dump-and-reload.  There are other cases in which load-via-partition-root
    6889                 :  * might be necessary, but we expect users to cope with them.
    6890                 :  */
    6891                 : void
    6892 GIC         118 : getPartitioningInfo(Archive *fout)
    6893                 : {
    6894                 :     PQExpBuffer query;
    6895 ECB             :     PGresult   *res;
    6896                 :     int         ntups;
    6897                 : 
    6898                 :     /* hash partitioning didn't exist before v11 */
    6899 GIC         118 :     if (fout->remoteVersion < 110000)
    6900 UIC           0 :         return;
    6901                 :     /* needn't bother if schema-only dump */
    6902 GIC         118 :     if (fout->dopt->schemaOnly)
    6903              10 :         return;
    6904 ECB             : 
    6905 CBC         108 :     query = createPQExpBuffer();
    6906 ECB             : 
    6907                 :     /*
    6908                 :      * Unsafe partitioning schemes are exactly those for which hash enum_ops
    6909                 :      * appears among the partition opclasses.  We needn't check partstrat.
    6910                 :      *
    6911                 :      * Note that this query may well retrieve info about tables we aren't
    6912                 :      * going to dump and hence have no lock on.  That's okay since we need not
    6913                 :      * invoke any unsafe server-side functions.
    6914                 :      */
    6915 GIC         108 :     appendPQExpBufferStr(query,
    6916 EUB             :                          "SELECT partrelid FROM pg_partitioned_table WHERE\n"
    6917                 :                          "(SELECT c.oid FROM pg_opclass c JOIN pg_am a "
    6918                 :                          "ON c.opcmethod = a.oid\n"
    6919                 :                          "WHERE opcname = 'enum_ops' "
    6920                 :                          "AND opcnamespace = 'pg_catalog'::regnamespace "
    6921                 :                          "AND amname = 'hash') = ANY(partclass)");
    6922                 : 
    6923 GIC         108 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    6924 ECB             : 
    6925 GIC         108 :     ntups = PQntuples(res);
    6926                 : 
    6927 CBC         110 :     for (int i = 0; i < ntups; i++)
    6928 ECB             :     {
    6929 GIC           2 :         Oid         tabrelid = atooid(PQgetvalue(res, i, 0));
    6930                 :         TableInfo  *tbinfo;
    6931 ECB             : 
    6932 GIC           2 :         tbinfo = findTableByOid(tabrelid);
    6933 CBC           2 :         if (tbinfo == NULL)
    6934 UIC           0 :             pg_fatal("failed sanity check, table OID %u appearing in pg_partitioned_table not found",
    6935                 :                      tabrelid);
    6936 CBC           2 :         tbinfo->unsafe_partitions = true;
    6937                 :     }
    6938 ECB             : 
    6939 GIC         108 :     PQclear(res);
    6940 ECB             : 
    6941 GIC         108 :     destroyPQExpBuffer(query);
    6942                 : }
    6943                 : 
    6944                 : /*
    6945                 :  * getIndexes
    6946                 :  *    get information about every index on a dumpable table
    6947                 :  *
    6948                 :  * Note: index data is not returned directly to the caller, but it
    6949                 :  * does get entered into the DumpableObject tables.
    6950                 :  */
    6951 ECB             : void
    6952 GIC         118 : getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
    6953                 : {
    6954             118 :     PQExpBuffer query = createPQExpBuffer();
    6955             118 :     PQExpBuffer tbloids = createPQExpBuffer();
    6956                 :     PGresult   *res;
    6957                 :     int         ntups;
    6958                 :     int         curtblindx;
    6959 ECB             :     IndxInfo   *indxinfo;
    6960                 :     int         i_tableoid,
    6961                 :                 i_oid,
    6962                 :                 i_indrelid,
    6963                 :                 i_indexname,
    6964                 :                 i_parentidx,
    6965                 :                 i_indexdef,
    6966                 :                 i_indnkeyatts,
    6967                 :                 i_indnatts,
    6968                 :                 i_indkey,
    6969 EUB             :                 i_indisclustered,
    6970                 :                 i_indisreplident,
    6971                 :                 i_indnullsnotdistinct,
    6972                 :                 i_contype,
    6973                 :                 i_conname,
    6974                 :                 i_condeferrable,
    6975                 :                 i_condeferred,
    6976 ECB             :                 i_contableoid,
    6977                 :                 i_conoid,
    6978                 :                 i_condef,
    6979                 :                 i_tablespace,
    6980                 :                 i_indreloptions,
    6981                 :                 i_indstatcols,
    6982                 :                 i_indstatvals;
    6983                 : 
    6984                 :     /*
    6985                 :      * We want to perform just one query against pg_index.  However, we
    6986                 :      * mustn't try to select every row of the catalog and then sort it out on
    6987                 :      * the client side, because some of the server-side functions we need
    6988                 :      * would be unsafe to apply to tables we don't have lock on.  Hence, we
    6989                 :      * build an array of the OIDs of tables we care about (and now have lock
    6990                 :      * on!), and use a WHERE clause to constrain which rows are selected.
    6991                 :      */
    6992 GIC         118 :     appendPQExpBufferChar(tbloids, '{');
    6993           30474 :     for (int i = 0; i < numTables; i++)
    6994                 :     {
    6995           30356 :         TableInfo  *tbinfo = &tblinfo[i];
    6996                 : 
    6997           30356 :         if (!tbinfo->hasindex)
    6998           21320 :             continue;
    6999 ECB             : 
    7000                 :         /*
    7001                 :          * We can ignore indexes of uninteresting tables.
    7002                 :          */
    7003 GIC        9036 :         if (!tbinfo->interesting)
    7004 CBC        7606 :             continue;
    7005                 : 
    7006                 :         /* OK, we need info for this table */
    7007 GIC        1430 :         if (tbloids->len > 1) /* do we have more than the '{'? */
    7008            1358 :             appendPQExpBufferChar(tbloids, ',');
    7009            1430 :         appendPQExpBuffer(tbloids, "%u", tbinfo->dobj.catId.oid);
    7010                 :     }
    7011             118 :     appendPQExpBufferChar(tbloids, '}');
    7012                 : 
    7013 GNC         118 :     appendPQExpBufferStr(query,
    7014                 :                          "SELECT t.tableoid, t.oid, i.indrelid, "
    7015                 :                          "t.relname AS indexname, "
    7016                 :                          "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
    7017                 :                          "i.indkey, i.indisclustered, "
    7018                 :                          "c.contype, c.conname, "
    7019                 :                          "c.condeferrable, c.condeferred, "
    7020                 :                          "c.tableoid AS contableoid, "
    7021                 :                          "c.oid AS conoid, "
    7022                 :                          "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
    7023                 :                          "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
    7024                 :                          "t.reloptions AS indreloptions, ");
    7025                 : 
    7026 ECB             : 
    7027 GIC         118 :     if (fout->remoteVersion >= 90400)
    7028 GNC         118 :         appendPQExpBufferStr(query,
    7029                 :                              "i.indisreplident, ");
    7030 ECB             :     else
    7031 UNC           0 :         appendPQExpBufferStr(query,
    7032                 :                              "false AS indisreplident, ");
    7033                 : 
    7034 CBC         118 :     if (fout->remoteVersion >= 110000)
    7035 GNC         118 :         appendPQExpBufferStr(query,
    7036                 :                              "inh.inhparent AS parentidx, "
    7037                 :                              "i.indnkeyatts AS indnkeyatts, "
    7038                 :                              "i.indnatts AS indnatts, "
    7039                 :                              "(SELECT pg_catalog.array_agg(attnum ORDER BY attnum) "
    7040                 :                              "  FROM pg_catalog.pg_attribute "
    7041                 :                              "  WHERE attrelid = i.indexrelid AND "
    7042                 :                              "    attstattarget >= 0) AS indstatcols, "
    7043                 :                              "(SELECT pg_catalog.array_agg(attstattarget ORDER BY attnum) "
    7044                 :                              "  FROM pg_catalog.pg_attribute "
    7045                 :                              "  WHERE attrelid = i.indexrelid AND "
    7046                 :                              "    attstattarget >= 0) AS indstatvals, ");
    7047 ECB             :     else
    7048 UNC           0 :         appendPQExpBufferStr(query,
    7049                 :                              "0 AS parentidx, "
    7050                 :                              "i.indnatts AS indnkeyatts, "
    7051                 :                              "i.indnatts AS indnatts, "
    7052                 :                              "'' AS indstatcols, "
    7053                 :                              "'' AS indstatvals, ");
    7054                 : 
    7055 GIC         118 :     if (fout->remoteVersion >= 150000)
    7056 GNC         118 :         appendPQExpBufferStr(query,
    7057                 :                              "i.indnullsnotdistinct ");
    7058                 :     else
    7059 UNC           0 :         appendPQExpBufferStr(query,
    7060                 :                              "false AS indnullsnotdistinct ");
    7061                 : 
    7062                 :     /*
    7063                 :      * The point of the messy-looking outer join is to find a constraint that
    7064                 :      * is related by an internal dependency link to the index. If we find one,
    7065                 :      * create a CONSTRAINT entry linked to the INDEX entry.  We assume an
    7066                 :      * index won't have more than one internal dependency.
    7067                 :      *
    7068                 :      * Note: the check on conrelid is redundant, but useful because that
    7069                 :      * column is indexed while conindid is not.
    7070 ECB             :      */
    7071 GIC         118 :     if (fout->remoteVersion >= 110000)
    7072                 :     {
    7073             118 :         appendPQExpBuffer(query,
    7074                 :                           "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
    7075                 :                           "JOIN pg_catalog.pg_index i ON (src.tbloid = i.indrelid) "
    7076                 :                           "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
    7077 ECB             :                           "JOIN pg_catalog.pg_class t2 ON (t2.oid = i.indrelid) "
    7078 EUB             :                           "LEFT JOIN pg_catalog.pg_constraint c "
    7079                 :                           "ON (i.indrelid = c.conrelid AND "
    7080 ECB             :                           "i.indexrelid = c.conindid AND "
    7081                 :                           "c.contype IN ('p','u','x')) "
    7082                 :                           "LEFT JOIN pg_catalog.pg_inherits inh "
    7083                 :                           "ON (inh.inhrelid = indexrelid) "
    7084                 :                           "WHERE (i.indisvalid OR t2.relkind = 'p') "
    7085                 :                           "AND i.indisready "
    7086                 :                           "ORDER BY i.indrelid, indexname",
    7087                 :                           tbloids->data);
    7088                 :     }
    7089                 :     else
    7090                 :     {
    7091                 :         /*
    7092                 :          * the test on indisready is necessary in 9.2, and harmless in
    7093                 :          * earlier/later versions
    7094                 :          */
    7095 UIC           0 :         appendPQExpBuffer(query,
    7096                 :                           "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
    7097                 :                           "JOIN pg_catalog.pg_index i ON (src.tbloid = i.indrelid) "
    7098                 :                           "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
    7099                 :                           "LEFT JOIN pg_catalog.pg_constraint c "
    7100                 :                           "ON (i.indrelid = c.conrelid AND "
    7101 ECB             :                           "i.indexrelid = c.conindid AND "
    7102                 :                           "c.contype IN ('p','u','x')) "
    7103                 :                           "WHERE i.indisvalid AND i.indisready "
    7104                 :                           "ORDER BY i.indrelid, indexname",
    7105                 :                           tbloids->data);
    7106                 :     }
    7107                 : 
    7108 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    7109                 : 
    7110 CBC         118 :     ntups = PQntuples(res);
    7111 ECB             : 
    7112 GBC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    7113 GIC         118 :     i_oid = PQfnumber(res, "oid");
    7114 CBC         118 :     i_indrelid = PQfnumber(res, "indrelid");
    7115 GIC         118 :     i_indexname = PQfnumber(res, "indexname");
    7116             118 :     i_parentidx = PQfnumber(res, "parentidx");
    7117 CBC         118 :     i_indexdef = PQfnumber(res, "indexdef");
    7118 GIC         118 :     i_indnkeyatts = PQfnumber(res, "indnkeyatts");
    7119 CBC         118 :     i_indnatts = PQfnumber(res, "indnatts");
    7120 GIC         118 :     i_indkey = PQfnumber(res, "indkey");
    7121             118 :     i_indisclustered = PQfnumber(res, "indisclustered");
    7122             118 :     i_indisreplident = PQfnumber(res, "indisreplident");
    7123             118 :     i_indnullsnotdistinct = PQfnumber(res, "indnullsnotdistinct");
    7124             118 :     i_contype = PQfnumber(res, "contype");
    7125             118 :     i_conname = PQfnumber(res, "conname");
    7126             118 :     i_condeferrable = PQfnumber(res, "condeferrable");
    7127             118 :     i_condeferred = PQfnumber(res, "condeferred");
    7128             118 :     i_contableoid = PQfnumber(res, "contableoid");
    7129             118 :     i_conoid = PQfnumber(res, "conoid");
    7130 CBC         118 :     i_condef = PQfnumber(res, "condef");
    7131 GIC         118 :     i_tablespace = PQfnumber(res, "tablespace");
    7132 CBC         118 :     i_indreloptions = PQfnumber(res, "indreloptions");
    7133             118 :     i_indstatcols = PQfnumber(res, "indstatcols");
    7134 GIC         118 :     i_indstatvals = PQfnumber(res, "indstatvals");
    7135                 : 
    7136             118 :     indxinfo = (IndxInfo *) pg_malloc(ntups * sizeof(IndxInfo));
    7137                 : 
    7138                 :     /*
    7139                 :      * Outer loop iterates once per table, not once per row.  Incrementing of
    7140                 :      * j is handled by the inner loop.
    7141                 :      */
    7142             118 :     curtblindx = -1;
    7143            1544 :     for (int j = 0; j < ntups;)
    7144                 :     {
    7145            1426 :         Oid         indrelid = atooid(PQgetvalue(res, j, i_indrelid));
    7146            1426 :         TableInfo  *tbinfo = NULL;
    7147                 :         int         numinds;
    7148                 : 
    7149                 :         /* Count rows for this table */
    7150            1848 :         for (numinds = 1; numinds < ntups - j; numinds++)
    7151            1776 :             if (atooid(PQgetvalue(res, j + numinds, i_indrelid)) != indrelid)
    7152            1354 :                 break;
    7153                 : 
    7154                 :         /*
    7155                 :          * Locate the associated TableInfo; we rely on tblinfo[] being in OID
    7156                 :          * order.
    7157                 :          */
    7158           20553 :         while (++curtblindx < numTables)
    7159                 :         {
    7160           20553 :             tbinfo = &tblinfo[curtblindx];
    7161           20553 :             if (tbinfo->dobj.catId.oid == indrelid)
    7162            1426 :                 break;
    7163                 :         }
    7164            1426 :         if (curtblindx >= numTables)
    7165 UIC           0 :             pg_fatal("unrecognized table OID %u", indrelid);
    7166                 :         /* cross-check that we only got requested tables */
    7167 GIC        1426 :         if (!tbinfo->hasindex ||
    7168            1426 :             !tbinfo->interesting)
    7169 UIC           0 :             pg_fatal("unexpected index data for table \"%s\"",
    7170 ECB             :                      tbinfo->dobj.name);
    7171                 : 
    7172                 :         /* Save data for this table */
    7173 CBC        1426 :         tbinfo->indexes = indxinfo + j;
    7174 GIC        1426 :         tbinfo->numIndexes = numinds;
    7175 ECB             : 
    7176 CBC        3274 :         for (int c = 0; c < numinds; c++, j++)
    7177                 :         {
    7178                 :             char        contype;
    7179                 : 
    7180 GIC        1848 :             indxinfo[j].dobj.objType = DO_INDEX;
    7181 CBC        1848 :             indxinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
    7182            1848 :             indxinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
    7183 GIC        1848 :             AssignDumpId(&indxinfo[j].dobj);
    7184            1848 :             indxinfo[j].dobj.dump = tbinfo->dobj.dump;
    7185 CBC        1848 :             indxinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_indexname));
    7186            1848 :             indxinfo[j].dobj.namespace = tbinfo->dobj.namespace;
    7187            1848 :             indxinfo[j].indextable = tbinfo;
    7188 GIC        1848 :             indxinfo[j].indexdef = pg_strdup(PQgetvalue(res, j, i_indexdef));
    7189 CBC        1848 :             indxinfo[j].indnkeyattrs = atoi(PQgetvalue(res, j, i_indnkeyatts));
    7190 GIC        1848 :             indxinfo[j].indnattrs = atoi(PQgetvalue(res, j, i_indnatts));
    7191 CBC        1848 :             indxinfo[j].tablespace = pg_strdup(PQgetvalue(res, j, i_tablespace));
    7192 GIC        1848 :             indxinfo[j].indreloptions = pg_strdup(PQgetvalue(res, j, i_indreloptions));
    7193            1848 :             indxinfo[j].indstatcols = pg_strdup(PQgetvalue(res, j, i_indstatcols));
    7194            1848 :             indxinfo[j].indstatvals = pg_strdup(PQgetvalue(res, j, i_indstatvals));
    7195            1848 :             indxinfo[j].indkeys = (Oid *) pg_malloc(indxinfo[j].indnattrs * sizeof(Oid));
    7196            1848 :             parseOidArray(PQgetvalue(res, j, i_indkey),
    7197            1848 :                           indxinfo[j].indkeys, indxinfo[j].indnattrs);
    7198            1848 :             indxinfo[j].indisclustered = (PQgetvalue(res, j, i_indisclustered)[0] == 't');
    7199            1848 :             indxinfo[j].indisreplident = (PQgetvalue(res, j, i_indisreplident)[0] == 't');
    7200            1848 :             indxinfo[j].indnullsnotdistinct = (PQgetvalue(res, j, i_indnullsnotdistinct)[0] == 't');
    7201            1848 :             indxinfo[j].parentidx = atooid(PQgetvalue(res, j, i_parentidx));
    7202            1848 :             indxinfo[j].partattaches = (SimplePtrList)
    7203                 :             {
    7204                 :                 NULL, NULL
    7205 ECB             :             };
    7206 CBC        1848 :             contype = *(PQgetvalue(res, j, i_contype));
    7207                 : 
    7208 GIC        1848 :             if (contype == 'p' || contype == 'u' || contype == 'x')
    7209 GBC         887 :             {
    7210                 :                 /*
    7211                 :                  * If we found a constraint matching the index, create an
    7212 ECB             :                  * entry for it.
    7213                 :                  */
    7214                 :                 ConstraintInfo *constrinfo;
    7215                 : 
    7216 GIC         887 :                 constrinfo = (ConstraintInfo *) pg_malloc(sizeof(ConstraintInfo));
    7217             887 :                 constrinfo->dobj.objType = DO_CONSTRAINT;
    7218             887 :                 constrinfo->dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid));
    7219             887 :                 constrinfo->dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
    7220             887 :                 AssignDumpId(&constrinfo->dobj);
    7221             887 :                 constrinfo->dobj.dump = tbinfo->dobj.dump;
    7222             887 :                 constrinfo->dobj.name = pg_strdup(PQgetvalue(res, j, i_conname));
    7223             887 :                 constrinfo->dobj.namespace = tbinfo->dobj.namespace;
    7224             887 :                 constrinfo->contable = tbinfo;
    7225             887 :                 constrinfo->condomain = NULL;
    7226 GBC         887 :                 constrinfo->contype = contype;
    7227 GIC         887 :                 if (contype == 'x')
    7228              10 :                     constrinfo->condef = pg_strdup(PQgetvalue(res, j, i_condef));
    7229                 :                 else
    7230             877 :                     constrinfo->condef = NULL;
    7231             887 :                 constrinfo->confrelid = InvalidOid;
    7232             887 :                 constrinfo->conindex = indxinfo[j].dobj.dumpId;
    7233 CBC         887 :                 constrinfo->condeferrable = *(PQgetvalue(res, j, i_condeferrable)) == 't';
    7234             887 :                 constrinfo->condeferred = *(PQgetvalue(res, j, i_condeferred)) == 't';
    7235 GIC         887 :                 constrinfo->conislocal = true;
    7236             887 :                 constrinfo->separate = true;
    7237 EUB             : 
    7238 GIC         887 :                 indxinfo[j].indexconstraint = constrinfo->dobj.dumpId;
    7239                 :             }
    7240                 :             else
    7241                 :             {
    7242                 :                 /* Plain secondary index */
    7243             961 :                 indxinfo[j].indexconstraint = 0;
    7244                 :             }
    7245                 :         }
    7246                 :     }
    7247                 : 
    7248             118 :     PQclear(res);
    7249 ECB             : 
    7250 GIC         118 :     destroyPQExpBuffer(query);
    7251 CBC         118 :     destroyPQExpBuffer(tbloids);
    7252 GIC         118 : }
    7253                 : 
    7254                 : /*
    7255                 :  * getExtendedStatistics
    7256                 :  *    get information about extended-statistics objects.
    7257                 :  *
    7258                 :  * Note: extended statistics data is not returned directly to the caller, but
    7259                 :  * it does get entered into the DumpableObject tables.
    7260                 :  */
    7261                 : void
    7262             118 : getExtendedStatistics(Archive *fout)
    7263                 : {
    7264                 :     PQExpBuffer query;
    7265                 :     PGresult   *res;
    7266                 :     StatsExtInfo *statsextinfo;
    7267                 :     int         ntups;
    7268                 :     int         i_tableoid;
    7269                 :     int         i_oid;
    7270                 :     int         i_stxname;
    7271                 :     int         i_stxnamespace;
    7272                 :     int         i_stxowner;
    7273 EUB             :     int         i_stattarget;
    7274                 :     int         i;
    7275                 : 
    7276                 :     /* Extended statistics were new in v10 */
    7277 GIC         118 :     if (fout->remoteVersion < 100000)
    7278 UIC           0 :         return;
    7279                 : 
    7280 GIC         118 :     query = createPQExpBuffer();
    7281                 : 
    7282             118 :     if (fout->remoteVersion < 130000)
    7283 UNC           0 :         appendPQExpBufferStr(query, "SELECT tableoid, oid, stxname, "
    7284                 :                              "stxnamespace, stxowner, (-1) AS stxstattarget "
    7285                 :                              "FROM pg_catalog.pg_statistic_ext");
    7286 ECB             :     else
    7287 GNC         118 :         appendPQExpBufferStr(query, "SELECT tableoid, oid, stxname, "
    7288                 :                              "stxnamespace, stxowner, stxstattarget "
    7289                 :                              "FROM pg_catalog.pg_statistic_ext");
    7290 ECB             : 
    7291 CBC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    7292 ECB             : 
    7293 CBC         118 :     ntups = PQntuples(res);
    7294 ECB             : 
    7295 CBC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    7296             118 :     i_oid = PQfnumber(res, "oid");
    7297             118 :     i_stxname = PQfnumber(res, "stxname");
    7298             118 :     i_stxnamespace = PQfnumber(res, "stxnamespace");
    7299             118 :     i_stxowner = PQfnumber(res, "stxowner");
    7300             118 :     i_stattarget = PQfnumber(res, "stxstattarget");
    7301 ECB             : 
    7302 CBC         118 :     statsextinfo = (StatsExtInfo *) pg_malloc(ntups * sizeof(StatsExtInfo));
    7303 ECB             : 
    7304 CBC         273 :     for (i = 0; i < ntups; i++)
    7305 ECB             :     {
    7306 CBC         155 :         statsextinfo[i].dobj.objType = DO_STATSEXT;
    7307             155 :         statsextinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    7308             155 :         statsextinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    7309             155 :         AssignDumpId(&statsextinfo[i].dobj);
    7310             155 :         statsextinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_stxname));
    7311             310 :         statsextinfo[i].dobj.namespace =
    7312             155 :             findNamespace(atooid(PQgetvalue(res, i, i_stxnamespace)));
    7313 GIC         155 :         statsextinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_stxowner));
    7314 CBC         155 :         statsextinfo[i].stattarget = atoi(PQgetvalue(res, i, i_stattarget));
    7315                 : 
    7316                 :         /* Decide whether we want to dump it */
    7317 GIC         155 :         selectDumpableObject(&(statsextinfo[i].dobj), fout);
    7318                 :     }
    7319                 : 
    7320 CBC         118 :     PQclear(res);
    7321             118 :     destroyPQExpBuffer(query);
    7322                 : }
    7323 ECB             : 
    7324                 : /*
    7325                 :  * getConstraints
    7326                 :  *
    7327                 :  * Get info about constraints on dumpable tables.
    7328                 :  *
    7329                 :  * Currently handles foreign keys only.
    7330                 :  * Unique and primary key constraints are handled with indexes,
    7331                 :  * while check constraints are processed in getTableAttrs().
    7332                 :  */
    7333                 : void
    7334 GIC         118 : getConstraints(Archive *fout, TableInfo tblinfo[], int numTables)
    7335                 : {
    7336 CBC         118 :     PQExpBuffer query = createPQExpBuffer();
    7337 GIC         118 :     PQExpBuffer tbloids = createPQExpBuffer();
    7338 ECB             :     PGresult   *res;
    7339                 :     int         ntups;
    7340                 :     int         curtblindx;
    7341 GIC         118 :     TableInfo  *tbinfo = NULL;
    7342 ECB             :     ConstraintInfo *constrinfo;
    7343 EUB             :     int         i_contableoid,
    7344                 :                 i_conoid,
    7345 ECB             :                 i_conrelid,
    7346                 :                 i_conname,
    7347 EUB             :                 i_confrelid,
    7348                 :                 i_conindid,
    7349                 :                 i_condef;
    7350                 : 
    7351 ECB             :     /*
    7352                 :      * We want to perform just one query against pg_constraint.  However, we
    7353                 :      * mustn't try to select every row of the catalog and then sort it out on
    7354                 :      * the client side, because some of the server-side functions we need
    7355                 :      * would be unsafe to apply to tables we don't have lock on.  Hence, we
    7356                 :      * build an array of the OIDs of tables we care about (and now have lock
    7357                 :      * on!), and use a WHERE clause to constrain which rows are selected.
    7358                 :      */
    7359 CBC         118 :     appendPQExpBufferChar(tbloids, '{');
    7360           30474 :     for (int i = 0; i < numTables; i++)
    7361 ECB             :     {
    7362 CBC       30356 :         TableInfo  *tinfo = &tblinfo[i];
    7363 ECB             : 
    7364                 :         /*
    7365                 :          * For partitioned tables, foreign keys have no triggers so they must
    7366                 :          * be included anyway in case some foreign keys are defined.
    7367                 :          */
    7368 CBC       30356 :         if ((!tinfo->hastriggers &&
    7369           29516 :              tinfo->relkind != RELKIND_PARTITIONED_TABLE) ||
    7370            1126 :             !(tinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
    7371           29279 :             continue;
    7372 ECB             : 
    7373                 :         /* OK, we need info for this table */
    7374 CBC        1077 :         if (tbloids->len > 1) /* do we have more than the '{'? */
    7375            1025 :             appendPQExpBufferChar(tbloids, ',');
    7376            1077 :         appendPQExpBuffer(tbloids, "%u", tinfo->dobj.catId.oid);
    7377 ECB             :     }
    7378 CBC         118 :     appendPQExpBufferChar(tbloids, '}');
    7379 ECB             : 
    7380 CBC         118 :     appendPQExpBufferStr(query,
    7381                 :                          "SELECT c.tableoid, c.oid, "
    7382                 :                          "conrelid, conname, confrelid, ");
    7383 GIC         118 :     if (fout->remoteVersion >= 110000)
    7384 CBC         118 :         appendPQExpBufferStr(query, "conindid, ");
    7385                 :     else
    7386 LBC           0 :         appendPQExpBufferStr(query, "0 AS conindid, ");
    7387 CBC         118 :     appendPQExpBuffer(query,
    7388                 :                       "pg_catalog.pg_get_constraintdef(c.oid) AS condef\n"
    7389                 :                       "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
    7390                 :                       "JOIN pg_catalog.pg_constraint c ON (src.tbloid = c.conrelid)\n"
    7391                 :                       "WHERE contype = 'f' ",
    7392                 :                       tbloids->data);
    7393 GIC         118 :     if (fout->remoteVersion >= 110000)
    7394 CBC         118 :         appendPQExpBufferStr(query,
    7395 ECB             :                              "AND conparentid = 0 ");
    7396 CBC         118 :     appendPQExpBufferStr(query,
    7397 ECB             :                          "ORDER BY conrelid, conname");
    7398                 : 
    7399 CBC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    7400 ECB             : 
    7401 CBC         118 :     ntups = PQntuples(res);
    7402 ECB             : 
    7403 CBC         118 :     i_contableoid = PQfnumber(res, "tableoid");
    7404             118 :     i_conoid = PQfnumber(res, "oid");
    7405             118 :     i_conrelid = PQfnumber(res, "conrelid");
    7406             118 :     i_conname = PQfnumber(res, "conname");
    7407 GIC         118 :     i_confrelid = PQfnumber(res, "confrelid");
    7408 CBC         118 :     i_conindid = PQfnumber(res, "conindid");
    7409             118 :     i_condef = PQfnumber(res, "condef");
    7410 ECB             : 
    7411 CBC         118 :     constrinfo = (ConstraintInfo *) pg_malloc(ntups * sizeof(ConstraintInfo));
    7412 ECB             : 
    7413 CBC         118 :     curtblindx = -1;
    7414             276 :     for (int j = 0; j < ntups; j++)
    7415                 :     {
    7416             158 :         Oid         conrelid = atooid(PQgetvalue(res, j, i_conrelid));
    7417                 :         TableInfo  *reftable;
    7418                 : 
    7419                 :         /*
    7420                 :          * Locate the associated TableInfo; we rely on tblinfo[] being in OID
    7421 ECB             :          * order.
    7422                 :          */
    7423 GIC         158 :         if (tbinfo == NULL || tbinfo->dobj.catId.oid != conrelid)
    7424                 :         {
    7425           12809 :             while (++curtblindx < numTables)
    7426 ECB             :             {
    7427 GIC       12809 :                 tbinfo = &tblinfo[curtblindx];
    7428 CBC       12809 :                 if (tbinfo->dobj.catId.oid == conrelid)
    7429             148 :                     break;
    7430 ECB             :             }
    7431 GIC         148 :             if (curtblindx >= numTables)
    7432 UIC           0 :                 pg_fatal("unrecognized table OID %u", conrelid);
    7433                 :         }
    7434                 : 
    7435 GIC         158 :         constrinfo[j].dobj.objType = DO_FK_CONSTRAINT;
    7436             158 :         constrinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid));
    7437             158 :         constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
    7438             158 :         AssignDumpId(&constrinfo[j].dobj);
    7439             158 :         constrinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname));
    7440 CBC         158 :         constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
    7441 GIC         158 :         constrinfo[j].contable = tbinfo;
    7442             158 :         constrinfo[j].condomain = NULL;
    7443             158 :         constrinfo[j].contype = 'f';
    7444             158 :         constrinfo[j].condef = pg_strdup(PQgetvalue(res, j, i_condef));
    7445             158 :         constrinfo[j].confrelid = atooid(PQgetvalue(res, j, i_confrelid));
    7446             158 :         constrinfo[j].conindex = 0;
    7447             158 :         constrinfo[j].condeferrable = false;
    7448             158 :         constrinfo[j].condeferred = false;
    7449             158 :         constrinfo[j].conislocal = true;
    7450             158 :         constrinfo[j].separate = true;
    7451                 : 
    7452                 :         /*
    7453                 :          * Restoring an FK that points to a partitioned table requires that
    7454                 :          * all partition indexes have been attached beforehand. Ensure that
    7455 ECB             :          * happens by making the constraint depend on each index partition
    7456 EUB             :          * attach object.
    7457                 :          */
    7458 CBC         158 :         reftable = findTableByOid(constrinfo[j].confrelid);
    7459 GIC         158 :         if (reftable && reftable->relkind == RELKIND_PARTITIONED_TABLE)
    7460 ECB             :         {
    7461 GBC          20 :             Oid         indexOid = atooid(PQgetvalue(res, j, i_conindid));
    7462                 : 
    7463 GIC          20 :             if (indexOid != InvalidOid)
    7464                 :             {
    7465 CBC          20 :                 for (int k = 0; k < reftable->numIndexes; k++)
    7466                 :                 {
    7467                 :                     IndxInfo   *refidx;
    7468                 : 
    7469 ECB             :                     /* not our index? */
    7470 GIC          20 :                     if (reftable->indexes[k].dobj.catId.oid != indexOid)
    7471 LBC           0 :                         continue;
    7472                 : 
    7473 CBC          20 :                     refidx = &reftable->indexes[k];
    7474              20 :                     addConstrChildIdxDeps(&constrinfo[j].dobj, refidx);
    7475              20 :                     break;
    7476 ECB             :                 }
    7477                 :             }
    7478                 :         }
    7479                 :     }
    7480                 : 
    7481 GIC         118 :     PQclear(res);
    7482 ECB             : 
    7483 GIC         118 :     destroyPQExpBuffer(query);
    7484 CBC         118 :     destroyPQExpBuffer(tbloids);
    7485             118 : }
    7486 ECB             : 
    7487                 : /*
    7488                 :  * addConstrChildIdxDeps
    7489                 :  *
    7490                 :  * Recursive subroutine for getConstraints
    7491                 :  *
    7492                 :  * Given an object representing a foreign key constraint and an index on the
    7493                 :  * partitioned table it references, mark the constraint object as dependent
    7494                 :  * on the DO_INDEX_ATTACH object of each index partition, recursively
    7495                 :  * drilling down to their partitions if any.  This ensures that the FK is not
    7496                 :  * restored until the index is fully marked valid.
    7497                 :  */
    7498                 : static void
    7499 CBC          45 : addConstrChildIdxDeps(DumpableObject *dobj, const IndxInfo *refidx)
    7500                 : {
    7501                 :     SimplePtrListCell *cell;
    7502                 : 
    7503 GIC          45 :     Assert(dobj->objType == DO_FK_CONSTRAINT);
    7504                 : 
    7505             155 :     for (cell = refidx->partattaches.head; cell; cell = cell->next)
    7506                 :     {
    7507             110 :         IndexAttachInfo *attach = (IndexAttachInfo *) cell->ptr;
    7508                 : 
    7509             110 :         addObjectDependency(dobj, attach->dobj.dumpId);
    7510                 : 
    7511             110 :         if (attach->partitionIdx->partattaches.head != NULL)
    7512 CBC          25 :             addConstrChildIdxDeps(dobj, attach->partitionIdx);
    7513                 :     }
    7514              45 : }
    7515 ECB             : 
    7516                 : /*
    7517                 :  * getDomainConstraints
    7518                 :  *
    7519                 :  * Get info about constraints on a domain.
    7520                 :  */
    7521                 : static void
    7522 GIC         124 : getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
    7523                 : {
    7524                 :     int         i;
    7525                 :     ConstraintInfo *constrinfo;
    7526             124 :     PQExpBuffer query = createPQExpBuffer();
    7527                 :     PGresult   *res;
    7528                 :     int         i_tableoid,
    7529                 :                 i_oid,
    7530                 :                 i_conname,
    7531                 :                 i_consrc;
    7532                 :     int         ntups;
    7533                 : 
    7534             124 :     if (!fout->is_prepared[PREPQUERY_GETDOMAINCONSTRAINTS])
    7535                 :     {
    7536                 :         /* Set up query for constraint-specific details */
    7537 CBC          44 :         appendPQExpBufferStr(query,
    7538 ECB             :                              "PREPARE getDomainConstraints(pg_catalog.oid) AS\n"
    7539                 :                              "SELECT tableoid, oid, conname, "
    7540                 :                              "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
    7541                 :                              "convalidated "
    7542                 :                              "FROM pg_catalog.pg_constraint "
    7543                 :                              "WHERE contypid = $1 "
    7544                 :                              "ORDER BY conname");
    7545                 : 
    7546 CBC          44 :         ExecuteSqlStatement(fout, query->data);
    7547 ECB             : 
    7548 CBC          44 :         fout->is_prepared[PREPQUERY_GETDOMAINCONSTRAINTS] = true;
    7549 ECB             :     }
    7550                 : 
    7551 GIC         124 :     printfPQExpBuffer(query,
    7552 ECB             :                       "EXECUTE getDomainConstraints('%u')",
    7553                 :                       tyinfo->dobj.catId.oid);
    7554                 : 
    7555 GIC         124 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    7556 ECB             : 
    7557 GIC         124 :     ntups = PQntuples(res);
    7558 ECB             : 
    7559 GIC         124 :     i_tableoid = PQfnumber(res, "tableoid");
    7560             124 :     i_oid = PQfnumber(res, "oid");
    7561 CBC         124 :     i_conname = PQfnumber(res, "conname");
    7562             124 :     i_consrc = PQfnumber(res, "consrc");
    7563                 : 
    7564 GBC         124 :     constrinfo = (ConstraintInfo *) pg_malloc(ntups * sizeof(ConstraintInfo));
    7565 ECB             : 
    7566 GIC         124 :     tyinfo->nDomChecks = ntups;
    7567             124 :     tyinfo->domChecks = constrinfo;
    7568                 : 
    7569             208 :     for (i = 0; i < ntups; i++)
    7570                 :     {
    7571 CBC          84 :         bool        validated = PQgetvalue(res, i, 4)[0] == 't';
    7572 ECB             : 
    7573 GIC          84 :         constrinfo[i].dobj.objType = DO_CONSTRAINT;
    7574 CBC          84 :         constrinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    7575 GIC          84 :         constrinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    7576              84 :         AssignDumpId(&constrinfo[i].dobj);
    7577 CBC          84 :         constrinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
    7578 GIC          84 :         constrinfo[i].dobj.namespace = tyinfo->dobj.namespace;
    7579 CBC          84 :         constrinfo[i].contable = NULL;
    7580 GIC          84 :         constrinfo[i].condomain = tyinfo;
    7581 CBC          84 :         constrinfo[i].contype = 'c';
    7582              84 :         constrinfo[i].condef = pg_strdup(PQgetvalue(res, i, i_consrc));
    7583              84 :         constrinfo[i].confrelid = InvalidOid;
    7584              84 :         constrinfo[i].conindex = 0;
    7585              84 :         constrinfo[i].condeferrable = false;
    7586              84 :         constrinfo[i].condeferred = false;
    7587              84 :         constrinfo[i].conislocal = true;
    7588                 : 
    7589              84 :         constrinfo[i].separate = !validated;
    7590                 : 
    7591 ECB             :         /*
    7592                 :          * Make the domain depend on the constraint, ensuring it won't be
    7593                 :          * output till any constraint dependencies are OK.  If the constraint
    7594                 :          * has not been validated, it's going to be dumped after the domain
    7595                 :          * anyway, so this doesn't matter.
    7596                 :          */
    7597 GIC          84 :         if (validated)
    7598              84 :             addObjectDependency(&tyinfo->dobj,
    7599              84 :                                 constrinfo[i].dobj.dumpId);
    7600                 :     }
    7601 ECB             : 
    7602 GIC         124 :     PQclear(res);
    7603 ECB             : 
    7604 GIC         124 :     destroyPQExpBuffer(query);
    7605 CBC         124 : }
    7606 ECB             : 
    7607                 : /*
    7608                 :  * getRules
    7609                 :  *    get basic information about every rule in the system
    7610 EUB             :  *
    7611                 :  * numRules is set to the number of rules read in
    7612                 :  */
    7613 ECB             : RuleInfo *
    7614 CBC         118 : getRules(Archive *fout, int *numRules)
    7615 ECB             : {
    7616                 :     PGresult   *res;
    7617                 :     int         ntups;
    7618                 :     int         i;
    7619 CBC         118 :     PQExpBuffer query = createPQExpBuffer();
    7620 ECB             :     RuleInfo   *ruleinfo;
    7621                 :     int         i_tableoid;
    7622                 :     int         i_oid;
    7623                 :     int         i_rulename;
    7624                 :     int         i_ruletable;
    7625                 :     int         i_ev_type;
    7626                 :     int         i_is_instead;
    7627                 :     int         i_ev_enabled;
    7628                 : 
    7629 GIC         118 :     appendPQExpBufferStr(query, "SELECT "
    7630                 :                          "tableoid, oid, rulename, "
    7631                 :                          "ev_class AS ruletable, ev_type, is_instead, "
    7632                 :                          "ev_enabled "
    7633                 :                          "FROM pg_rewrite "
    7634                 :                          "ORDER BY oid");
    7635                 : 
    7636 CBC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    7637 ECB             : 
    7638 GIC         118 :     ntups = PQntuples(res);
    7639 ECB             : 
    7640 GIC         118 :     *numRules = ntups;
    7641 ECB             : 
    7642 GIC         118 :     ruleinfo = (RuleInfo *) pg_malloc(ntups * sizeof(RuleInfo));
    7643 ECB             : 
    7644 GIC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    7645             118 :     i_oid = PQfnumber(res, "oid");
    7646             118 :     i_rulename = PQfnumber(res, "rulename");
    7647             118 :     i_ruletable = PQfnumber(res, "ruletable");
    7648 CBC         118 :     i_ev_type = PQfnumber(res, "ev_type");
    7649 GBC         118 :     i_is_instead = PQfnumber(res, "is_instead");
    7650 GIC         118 :     i_ev_enabled = PQfnumber(res, "ev_enabled");
    7651 ECB             : 
    7652 CBC       17867 :     for (i = 0; i < ntups; i++)
    7653 ECB             :     {
    7654                 :         Oid         ruletableoid;
    7655                 : 
    7656 GIC       17749 :         ruleinfo[i].dobj.objType = DO_RULE;
    7657           17749 :         ruleinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    7658           17749 :         ruleinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    7659 CBC       17749 :         AssignDumpId(&ruleinfo[i].dobj);
    7660 GIC       17749 :         ruleinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_rulename));
    7661 CBC       17749 :         ruletableoid = atooid(PQgetvalue(res, i, i_ruletable));
    7662           17749 :         ruleinfo[i].ruletable = findTableByOid(ruletableoid);
    7663           17749 :         if (ruleinfo[i].ruletable == NULL)
    7664 UIC           0 :             pg_fatal("failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found",
    7665                 :                      ruletableoid, ruleinfo[i].dobj.catId.oid);
    7666 GIC       17749 :         ruleinfo[i].dobj.namespace = ruleinfo[i].ruletable->dobj.namespace;
    7667           17749 :         ruleinfo[i].dobj.dump = ruleinfo[i].ruletable->dobj.dump;
    7668           17749 :         ruleinfo[i].ev_type = *(PQgetvalue(res, i, i_ev_type));
    7669           17749 :         ruleinfo[i].is_instead = *(PQgetvalue(res, i, i_is_instead)) == 't';
    7670           17749 :         ruleinfo[i].ev_enabled = *(PQgetvalue(res, i, i_ev_enabled));
    7671           17749 :         if (ruleinfo[i].ruletable)
    7672                 :         {
    7673                 :             /*
    7674                 :              * If the table is a view or materialized view, force its ON
    7675                 :              * SELECT rule to be sorted before the view itself --- this
    7676                 :              * ensures that any dependencies for the rule affect the table's
    7677 ECB             :              * positioning. Other rules are forced to appear after their
    7678                 :              * table.
    7679                 :              */
    7680 GIC       17749 :             if ((ruleinfo[i].ruletable->relkind == RELKIND_VIEW ||
    7681 CBC         565 :                  ruleinfo[i].ruletable->relkind == RELKIND_MATVIEW) &&
    7682 GIC       17584 :                 ruleinfo[i].ev_type == '1' && ruleinfo[i].is_instead)
    7683 ECB             :             {
    7684 GIC       17318 :                 addObjectDependency(&ruleinfo[i].ruletable->dobj,
    7685 CBC       17318 :                                     ruleinfo[i].dobj.dumpId);
    7686                 :                 /* We'll merge the rule into CREATE VIEW, if possible */
    7687           17318 :                 ruleinfo[i].separate = false;
    7688                 :             }
    7689 ECB             :             else
    7690                 :             {
    7691 GIC         431 :                 addObjectDependency(&ruleinfo[i].dobj,
    7692 CBC         431 :                                     ruleinfo[i].ruletable->dobj.dumpId);
    7693 GIC         431 :                 ruleinfo[i].separate = true;
    7694                 :             }
    7695                 :         }
    7696                 :         else
    7697 UIC           0 :             ruleinfo[i].separate = true;
    7698                 :     }
    7699                 : 
    7700 CBC         118 :     PQclear(res);
    7701                 : 
    7702 GIC         118 :     destroyPQExpBuffer(query);
    7703                 : 
    7704 CBC         118 :     return ruleinfo;
    7705                 : }
    7706                 : 
    7707                 : /*
    7708                 :  * getTriggers
    7709                 :  *    get information about every trigger on a dumpable table
    7710                 :  *
    7711                 :  * Note: trigger data is not returned directly to the caller, but it
    7712 ECB             :  * does get entered into the DumpableObject tables.
    7713                 :  */
    7714                 : void
    7715 CBC         118 : getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
    7716                 : {
    7717 GIC         118 :     PQExpBuffer query = createPQExpBuffer();
    7718             118 :     PQExpBuffer tbloids = createPQExpBuffer();
    7719                 :     PGresult   *res;
    7720                 :     int         ntups;
    7721                 :     int         curtblindx;
    7722                 :     TriggerInfo *tginfo;
    7723                 :     int         i_tableoid,
    7724 ECB             :                 i_oid,
    7725                 :                 i_tgrelid,
    7726                 :                 i_tgname,
    7727                 :                 i_tgfname,
    7728                 :                 i_tgtype,
    7729                 :                 i_tgnargs,
    7730                 :                 i_tgargs,
    7731                 :                 i_tgisconstraint,
    7732                 :                 i_tgconstrname,
    7733                 :                 i_tgconstrrelid,
    7734                 :                 i_tgconstrrelname,
    7735                 :                 i_tgenabled,
    7736                 :                 i_tgispartition,
    7737                 :                 i_tgdeferrable,
    7738                 :                 i_tginitdeferred,
    7739                 :                 i_tgdef;
    7740                 : 
    7741                 :     /*
    7742                 :      * We want to perform just one query against pg_trigger.  However, we
    7743                 :      * mustn't try to select every row of the catalog and then sort it out on
    7744                 :      * the client side, because some of the server-side functions we need
    7745                 :      * would be unsafe to apply to tables we don't have lock on.  Hence, we
    7746                 :      * build an array of the OIDs of tables we care about (and now have lock
    7747                 :      * on!), and use a WHERE clause to constrain which rows are selected.
    7748                 :      */
    7749 CBC         118 :     appendPQExpBufferChar(tbloids, '{');
    7750 GIC       30474 :     for (int i = 0; i < numTables; i++)
    7751 ECB             :     {
    7752 CBC       30356 :         TableInfo  *tbinfo = &tblinfo[i];
    7753 ECB             : 
    7754 CBC       30356 :         if (!tbinfo->hastriggers ||
    7755             840 :             !(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
    7756           29565 :             continue;
    7757 ECB             : 
    7758                 :         /* OK, we need info for this table */
    7759 CBC         791 :         if (tbloids->len > 1) /* do we have more than the '{'? */
    7760             741 :             appendPQExpBufferChar(tbloids, ',');
    7761             791 :         appendPQExpBuffer(tbloids, "%u", tbinfo->dobj.catId.oid);
    7762 ECB             :     }
    7763 CBC         118 :     appendPQExpBufferChar(tbloids, '}');
    7764 ECB             : 
    7765 CBC         118 :     if (fout->remoteVersion >= 150000)
    7766                 :     {
    7767 ECB             :         /*
    7768                 :          * NB: think not to use pretty=true in pg_get_triggerdef.  It could
    7769                 :          * result in non-forward-compatible dumps of WHEN clauses due to
    7770                 :          * under-parenthesization.
    7771                 :          *
    7772                 :          * NB: We need to see partition triggers in case the tgenabled flag
    7773                 :          * has been changed from the parent.
    7774                 :          */
    7775 CBC         118 :         appendPQExpBuffer(query,
    7776 ECB             :                           "SELECT t.tgrelid, t.tgname, "
    7777                 :                           "t.tgfoid::pg_catalog.regproc AS tgfname, "
    7778                 :                           "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, "
    7779                 :                           "t.tgenabled, t.tableoid, t.oid, "
    7780                 :                           "t.tgparentid <> 0 AS tgispartition\n"
    7781                 :                           "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
    7782                 :                           "JOIN pg_catalog.pg_trigger t ON (src.tbloid = t.tgrelid) "
    7783                 :                           "LEFT JOIN pg_catalog.pg_trigger u ON (u.oid = t.tgparentid) "
    7784                 :                           "WHERE ((NOT t.tgisinternal AND t.tgparentid = 0) "
    7785                 :                           "OR t.tgenabled != u.tgenabled) "
    7786                 :                           "ORDER BY t.tgrelid, t.tgname",
    7787                 :                           tbloids->data);
    7788                 :     }
    7789 UIC           0 :     else if (fout->remoteVersion >= 130000)
    7790                 :     {
    7791                 :         /*
    7792 ECB             :          * NB: think not to use pretty=true in pg_get_triggerdef.  It could
    7793                 :          * result in non-forward-compatible dumps of WHEN clauses due to
    7794                 :          * under-parenthesization.
    7795                 :          *
    7796                 :          * NB: We need to see tgisinternal triggers in partitions, in case the
    7797                 :          * tgenabled flag has been changed from the parent.
    7798                 :          */
    7799 UIC           0 :         appendPQExpBuffer(query,
    7800                 :                           "SELECT t.tgrelid, t.tgname, "
    7801                 :                           "t.tgfoid::pg_catalog.regproc AS tgfname, "
    7802                 :                           "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, "
    7803                 :                           "t.tgenabled, t.tableoid, t.oid, t.tgisinternal as tgispartition\n"
    7804                 :                           "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
    7805                 :                           "JOIN pg_catalog.pg_trigger t ON (src.tbloid = t.tgrelid) "
    7806                 :                           "LEFT JOIN pg_catalog.pg_trigger u ON (u.oid = t.tgparentid) "
    7807 ECB             :                           "WHERE (NOT t.tgisinternal OR t.tgenabled != u.tgenabled) "
    7808                 :                           "ORDER BY t.tgrelid, t.tgname",
    7809                 :                           tbloids->data);
    7810                 :     }
    7811 UIC           0 :     else if (fout->remoteVersion >= 110000)
    7812                 :     {
    7813                 :         /*
    7814 ECB             :          * NB: We need to see tgisinternal triggers in partitions, in case the
    7815                 :          * tgenabled flag has been changed from the parent. No tgparentid in
    7816                 :          * version 11-12, so we have to match them via pg_depend.
    7817                 :          *
    7818                 :          * See above about pretty=true in pg_get_triggerdef.
    7819                 :          */
    7820 LBC           0 :         appendPQExpBuffer(query,
    7821                 :                           "SELECT t.tgrelid, t.tgname, "
    7822 ECB             :                           "t.tgfoid::pg_catalog.regproc AS tgfname, "
    7823                 :                           "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, "
    7824                 :                           "t.tgenabled, t.tableoid, t.oid, t.tgisinternal as tgispartition "
    7825                 :                           "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
    7826                 :                           "JOIN pg_catalog.pg_trigger t ON (src.tbloid = t.tgrelid) "
    7827                 :                           "LEFT JOIN pg_catalog.pg_depend AS d ON "
    7828                 :                           " d.classid = 'pg_catalog.pg_trigger'::pg_catalog.regclass AND "
    7829                 :                           " d.refclassid = 'pg_catalog.pg_trigger'::pg_catalog.regclass AND "
    7830                 :                           " d.objid = t.oid "
    7831                 :                           "LEFT JOIN pg_catalog.pg_trigger AS pt ON pt.oid = refobjid "
    7832                 :                           "WHERE (NOT t.tgisinternal OR t.tgenabled != pt.tgenabled) "
    7833                 :                           "ORDER BY t.tgrelid, t.tgname",
    7834                 :                           tbloids->data);
    7835                 :     }
    7836                 :     else
    7837                 :     {
    7838                 :         /* See above about pretty=true in pg_get_triggerdef */
    7839 LBC           0 :         appendPQExpBuffer(query,
    7840 ECB             :                           "SELECT t.tgrelid, t.tgname, "
    7841                 :                           "t.tgfoid::pg_catalog.regproc AS tgfname, "
    7842 EUB             :                           "pg_catalog.pg_get_triggerdef(t.oid, false) AS tgdef, "
    7843                 :                           "t.tgenabled, false as tgispartition, "
    7844 ECB             :                           "t.tableoid, t.oid "
    7845                 :                           "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
    7846                 :                           "JOIN pg_catalog.pg_trigger t ON (src.tbloid = t.tgrelid) "
    7847                 :                           "WHERE NOT tgisinternal "
    7848                 :                           "ORDER BY t.tgrelid, t.tgname",
    7849                 :                           tbloids->data);
    7850                 :     }
    7851                 : 
    7852 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    7853                 : 
    7854             118 :     ntups = PQntuples(res);
    7855                 : 
    7856             118 :     i_tableoid = PQfnumber(res, "tableoid");
    7857             118 :     i_oid = PQfnumber(res, "oid");
    7858 CBC         118 :     i_tgrelid = PQfnumber(res, "tgrelid");
    7859             118 :     i_tgname = PQfnumber(res, "tgname");
    7860             118 :     i_tgfname = PQfnumber(res, "tgfname");
    7861 GIC         118 :     i_tgtype = PQfnumber(res, "tgtype");
    7862 CBC         118 :     i_tgnargs = PQfnumber(res, "tgnargs");
    7863             118 :     i_tgargs = PQfnumber(res, "tgargs");
    7864 GIC         118 :     i_tgisconstraint = PQfnumber(res, "tgisconstraint");
    7865 CBC         118 :     i_tgconstrname = PQfnumber(res, "tgconstrname");
    7866 GIC         118 :     i_tgconstrrelid = PQfnumber(res, "tgconstrrelid");
    7867             118 :     i_tgconstrrelname = PQfnumber(res, "tgconstrrelname");
    7868             118 :     i_tgenabled = PQfnumber(res, "tgenabled");
    7869 CBC         118 :     i_tgispartition = PQfnumber(res, "tgispartition");
    7870             118 :     i_tgdeferrable = PQfnumber(res, "tgdeferrable");
    7871             118 :     i_tginitdeferred = PQfnumber(res, "tginitdeferred");
    7872 GIC         118 :     i_tgdef = PQfnumber(res, "tgdef");
    7873                 : 
    7874             118 :     tginfo = (TriggerInfo *) pg_malloc(ntups * sizeof(TriggerInfo));
    7875 EUB             : 
    7876                 :     /*
    7877                 :      * Outer loop iterates once per table, not once per row.  Incrementing of
    7878 ECB             :      * j is handled by the inner loop.
    7879                 :      */
    7880 CBC         118 :     curtblindx = -1;
    7881 GIC         422 :     for (int j = 0; j < ntups;)
    7882 ECB             :     {
    7883 GIC         304 :         Oid         tgrelid = atooid(PQgetvalue(res, j, i_tgrelid));
    7884             304 :         TableInfo  *tbinfo = NULL;
    7885                 :         int         numtrigs;
    7886                 : 
    7887                 :         /* Count rows for this table */
    7888             504 :         for (numtrigs = 1; numtrigs < ntups - j; numtrigs++)
    7889             454 :             if (atooid(PQgetvalue(res, j + numtrigs, i_tgrelid)) != tgrelid)
    7890             254 :                 break;
    7891                 : 
    7892                 :         /*
    7893 ECB             :          * Locate the associated TableInfo; we rely on tblinfo[] being in OID
    7894                 :          * order.
    7895                 :          */
    7896 CBC       14801 :         while (++curtblindx < numTables)
    7897                 :         {
    7898 GIC       14801 :             tbinfo = &tblinfo[curtblindx];
    7899           14801 :             if (tbinfo->dobj.catId.oid == tgrelid)
    7900             304 :                 break;
    7901                 :         }
    7902             304 :         if (curtblindx >= numTables)
    7903 UIC           0 :             pg_fatal("unrecognized table OID %u", tgrelid);
    7904                 : 
    7905                 :         /* Save data for this table */
    7906 GIC         304 :         tbinfo->triggers = tginfo + j;
    7907             304 :         tbinfo->numTriggers = numtrigs;
    7908                 : 
    7909             808 :         for (int c = 0; c < numtrigs; c++, j++)
    7910                 :         {
    7911             504 :             tginfo[j].dobj.objType = DO_TRIGGER;
    7912             504 :             tginfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
    7913             504 :             tginfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
    7914             504 :             AssignDumpId(&tginfo[j].dobj);
    7915             504 :             tginfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_tgname));
    7916             504 :             tginfo[j].dobj.namespace = tbinfo->dobj.namespace;
    7917             504 :             tginfo[j].tgtable = tbinfo;
    7918             504 :             tginfo[j].tgenabled = *(PQgetvalue(res, j, i_tgenabled));
    7919             504 :             tginfo[j].tgispartition = *(PQgetvalue(res, j, i_tgispartition)) == 't';
    7920             504 :             if (i_tgdef >= 0)
    7921                 :             {
    7922             504 :                 tginfo[j].tgdef = pg_strdup(PQgetvalue(res, j, i_tgdef));
    7923                 : 
    7924                 :                 /* remaining fields are not valid if we have tgdef */
    7925             504 :                 tginfo[j].tgfname = NULL;
    7926             504 :                 tginfo[j].tgtype = 0;
    7927 CBC         504 :                 tginfo[j].tgnargs = 0;
    7928             504 :                 tginfo[j].tgargs = NULL;
    7929 GIC         504 :                 tginfo[j].tgisconstraint = false;
    7930 CBC         504 :                 tginfo[j].tgdeferrable = false;
    7931 GIC         504 :                 tginfo[j].tginitdeferred = false;
    7932 CBC         504 :                 tginfo[j].tgconstrname = NULL;
    7933             504 :                 tginfo[j].tgconstrrelid = InvalidOid;
    7934             504 :                 tginfo[j].tgconstrrelname = NULL;
    7935                 :             }
    7936                 :             else
    7937 ECB             :             {
    7938 LBC           0 :                 tginfo[j].tgdef = NULL;
    7939 ECB             : 
    7940 UIC           0 :                 tginfo[j].tgfname = pg_strdup(PQgetvalue(res, j, i_tgfname));
    7941 LBC           0 :                 tginfo[j].tgtype = atoi(PQgetvalue(res, j, i_tgtype));
    7942 UIC           0 :                 tginfo[j].tgnargs = atoi(PQgetvalue(res, j, i_tgnargs));
    7943 LBC           0 :                 tginfo[j].tgargs = pg_strdup(PQgetvalue(res, j, i_tgargs));
    7944 UIC           0 :                 tginfo[j].tgisconstraint = *(PQgetvalue(res, j, i_tgisconstraint)) == 't';
    7945               0 :                 tginfo[j].tgdeferrable = *(PQgetvalue(res, j, i_tgdeferrable)) == 't';
    7946               0 :                 tginfo[j].tginitdeferred = *(PQgetvalue(res, j, i_tginitdeferred)) == 't';
    7947                 : 
    7948               0 :                 if (tginfo[j].tgisconstraint)
    7949                 :                 {
    7950               0 :                     tginfo[j].tgconstrname = pg_strdup(PQgetvalue(res, j, i_tgconstrname));
    7951               0 :                     tginfo[j].tgconstrrelid = atooid(PQgetvalue(res, j, i_tgconstrrelid));
    7952               0 :                     if (OidIsValid(tginfo[j].tgconstrrelid))
    7953 ECB             :                     {
    7954 UIC           0 :                         if (PQgetisnull(res, j, i_tgconstrrelname))
    7955               0 :                             pg_fatal("query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)",
    7956                 :                                      tginfo[j].dobj.name,
    7957                 :                                      tbinfo->dobj.name,
    7958                 :                                      tginfo[j].tgconstrrelid);
    7959               0 :                         tginfo[j].tgconstrrelname = pg_strdup(PQgetvalue(res, j, i_tgconstrrelname));
    7960                 :                     }
    7961                 :                     else
    7962               0 :                         tginfo[j].tgconstrrelname = NULL;
    7963                 :                 }
    7964                 :                 else
    7965                 :                 {
    7966               0 :                     tginfo[j].tgconstrname = NULL;
    7967 UBC           0 :                     tginfo[j].tgconstrrelid = InvalidOid;
    7968 UIC           0 :                     tginfo[j].tgconstrrelname = NULL;
    7969                 :                 }
    7970                 :             }
    7971                 :         }
    7972                 :     }
    7973                 : 
    7974 GIC         118 :     PQclear(res);
    7975                 : 
    7976             118 :     destroyPQExpBuffer(query);
    7977 GBC         118 :     destroyPQExpBuffer(tbloids);
    7978 GIC         118 : }
    7979                 : 
    7980                 : /*
    7981                 :  * getEventTriggers
    7982                 :  *    get information about event triggers
    7983                 :  */
    7984                 : EventTriggerInfo *
    7985             118 : getEventTriggers(Archive *fout, int *numEventTriggers)
    7986                 : {
    7987                 :     int         i;
    7988                 :     PQExpBuffer query;
    7989 EUB             :     PGresult   *res;
    7990                 :     EventTriggerInfo *evtinfo;
    7991                 :     int         i_tableoid,
    7992                 :                 i_oid,
    7993                 :                 i_evtname,
    7994                 :                 i_evtevent,
    7995                 :                 i_evtowner,
    7996                 :                 i_evttags,
    7997                 :                 i_evtfname,
    7998                 :                 i_evtenabled;
    7999                 :     int         ntups;
    8000                 : 
    8001                 :     /* Before 9.3, there are no event triggers */
    8002 GIC         118 :     if (fout->remoteVersion < 90300)
    8003                 :     {
    8004 UIC           0 :         *numEventTriggers = 0;
    8005               0 :         return NULL;
    8006                 :     }
    8007                 : 
    8008 GIC         118 :     query = createPQExpBuffer();
    8009                 : 
    8010 GNC         118 :     appendPQExpBufferStr(query,
    8011                 :                          "SELECT e.tableoid, e.oid, evtname, evtenabled, "
    8012                 :                          "evtevent, evtowner, "
    8013                 :                          "array_to_string(array("
    8014                 :                          "select quote_literal(x) "
    8015                 :                          " from unnest(evttags) as t(x)), ', ') as evttags, "
    8016                 :                          "e.evtfoid::regproc as evtfname "
    8017                 :                          "FROM pg_event_trigger e "
    8018                 :                          "ORDER BY e.oid");
    8019                 : 
    8020 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    8021                 : 
    8022             118 :     ntups = PQntuples(res);
    8023                 : 
    8024             118 :     *numEventTriggers = ntups;
    8025                 : 
    8026             118 :     evtinfo = (EventTriggerInfo *) pg_malloc(ntups * sizeof(EventTriggerInfo));
    8027                 : 
    8028             118 :     i_tableoid = PQfnumber(res, "tableoid");
    8029             118 :     i_oid = PQfnumber(res, "oid");
    8030 CBC         118 :     i_evtname = PQfnumber(res, "evtname");
    8031 GIC         118 :     i_evtevent = PQfnumber(res, "evtevent");
    8032 CBC         118 :     i_evtowner = PQfnumber(res, "evtowner");
    8033 GIC         118 :     i_evttags = PQfnumber(res, "evttags");
    8034 CBC         118 :     i_evtfname = PQfnumber(res, "evtfname");
    8035             118 :     i_evtenabled = PQfnumber(res, "evtenabled");
    8036 ECB             : 
    8037 CBC         163 :     for (i = 0; i < ntups; i++)
    8038 ECB             :     {
    8039 CBC          45 :         evtinfo[i].dobj.objType = DO_EVENT_TRIGGER;
    8040              45 :         evtinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    8041              45 :         evtinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    8042              45 :         AssignDumpId(&evtinfo[i].dobj);
    8043              45 :         evtinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_evtname));
    8044              45 :         evtinfo[i].evtname = pg_strdup(PQgetvalue(res, i, i_evtname));
    8045              45 :         evtinfo[i].evtevent = pg_strdup(PQgetvalue(res, i, i_evtevent));
    8046              45 :         evtinfo[i].evtowner = getRoleName(PQgetvalue(res, i, i_evtowner));
    8047              45 :         evtinfo[i].evttags = pg_strdup(PQgetvalue(res, i, i_evttags));
    8048              45 :         evtinfo[i].evtfname = pg_strdup(PQgetvalue(res, i, i_evtfname));
    8049              45 :         evtinfo[i].evtenabled = *(PQgetvalue(res, i, i_evtenabled));
    8050 ECB             : 
    8051                 :         /* Decide whether we want to dump it */
    8052 CBC          45 :         selectDumpableObject(&(evtinfo[i].dobj), fout);
    8053                 :     }
    8054                 : 
    8055 GIC         118 :     PQclear(res);
    8056                 : 
    8057             118 :     destroyPQExpBuffer(query);
    8058 ECB             : 
    8059 CBC         118 :     return evtinfo;
    8060                 : }
    8061 ECB             : 
    8062                 : /*
    8063                 :  * getProcLangs
    8064                 :  *    get basic information about every procedural language in the system
    8065                 :  *
    8066                 :  * numProcLangs is set to the number of langs read in
    8067                 :  *
    8068                 :  * NB: this must run after getFuncs() because we assume we can do
    8069                 :  * findFuncByOid().
    8070                 :  */
    8071                 : ProcLangInfo *
    8072 GIC         118 : getProcLangs(Archive *fout, int *numProcLangs)
    8073                 : {
    8074 ECB             :     PGresult   *res;
    8075                 :     int         ntups;
    8076                 :     int         i;
    8077 CBC         118 :     PQExpBuffer query = createPQExpBuffer();
    8078 ECB             :     ProcLangInfo *planginfo;
    8079                 :     int         i_tableoid;
    8080                 :     int         i_oid;
    8081 EUB             :     int         i_lanname;
    8082                 :     int         i_lanpltrusted;
    8083                 :     int         i_lanplcallfoid;
    8084 ECB             :     int         i_laninline;
    8085                 :     int         i_lanvalidator;
    8086                 :     int         i_lanacl;
    8087                 :     int         i_acldefault;
    8088                 :     int         i_lanowner;
    8089                 : 
    8090 GNC         118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, "
    8091                 :                          "lanname, lanpltrusted, lanplcallfoid, "
    8092                 :                          "laninline, lanvalidator, "
    8093                 :                          "lanacl, "
    8094                 :                          "acldefault('l', lanowner) AS acldefault, "
    8095                 :                          "lanowner "
    8096                 :                          "FROM pg_language "
    8097                 :                          "WHERE lanispl "
    8098                 :                          "ORDER BY oid");
    8099                 : 
    8100 CBC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    8101                 : 
    8102 GIC         118 :     ntups = PQntuples(res);
    8103 ECB             : 
    8104 CBC         118 :     *numProcLangs = ntups;
    8105 ECB             : 
    8106 CBC         118 :     planginfo = (ProcLangInfo *) pg_malloc(ntups * sizeof(ProcLangInfo));
    8107 ECB             : 
    8108 CBC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    8109             118 :     i_oid = PQfnumber(res, "oid");
    8110             118 :     i_lanname = PQfnumber(res, "lanname");
    8111             118 :     i_lanpltrusted = PQfnumber(res, "lanpltrusted");
    8112             118 :     i_lanplcallfoid = PQfnumber(res, "lanplcallfoid");
    8113 GIC         118 :     i_laninline = PQfnumber(res, "laninline");
    8114             118 :     i_lanvalidator = PQfnumber(res, "lanvalidator");
    8115             118 :     i_lanacl = PQfnumber(res, "lanacl");
    8116 GBC         118 :     i_acldefault = PQfnumber(res, "acldefault");
    8117 GIC         118 :     i_lanowner = PQfnumber(res, "lanowner");
    8118 EUB             : 
    8119 GBC         281 :     for (i = 0; i < ntups; i++)
    8120 EUB             :     {
    8121 GBC         163 :         planginfo[i].dobj.objType = DO_PROCLANG;
    8122             163 :         planginfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    8123             163 :         planginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    8124             163 :         AssignDumpId(&planginfo[i].dobj);
    8125                 : 
    8126             163 :         planginfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_lanname));
    8127 GIC         163 :         planginfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_lanacl));
    8128 GBC         163 :         planginfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
    8129             163 :         planginfo[i].dacl.privtype = 0;
    8130             163 :         planginfo[i].dacl.initprivs = NULL;
    8131 GIC         163 :         planginfo[i].lanpltrusted = *(PQgetvalue(res, i, i_lanpltrusted)) == 't';
    8132 GBC         163 :         planginfo[i].lanplcallfoid = atooid(PQgetvalue(res, i, i_lanplcallfoid));
    8133             163 :         planginfo[i].laninline = atooid(PQgetvalue(res, i, i_laninline));
    8134 GIC         163 :         planginfo[i].lanvalidator = atooid(PQgetvalue(res, i, i_lanvalidator));
    8135             163 :         planginfo[i].lanowner = getRoleName(PQgetvalue(res, i, i_lanowner));
    8136                 : 
    8137 EUB             :         /* Decide whether we want to dump it */
    8138 GIC         163 :         selectDumpableProcLang(&(planginfo[i]), fout);
    8139                 : 
    8140 EUB             :         /* Mark whether language has an ACL */
    8141 GIC         163 :         if (!PQgetisnull(res, i, i_lanacl))
    8142              45 :             planginfo[i].dobj.components |= DUMP_COMPONENT_ACL;
    8143                 :     }
    8144 EUB             : 
    8145 GBC         118 :     PQclear(res);
    8146 EUB             : 
    8147 GIC         118 :     destroyPQExpBuffer(query);
    8148                 : 
    8149             118 :     return planginfo;
    8150                 : }
    8151                 : 
    8152 ECB             : /*
    8153                 :  * getCasts
    8154                 :  *    get basic information about most casts in the system
    8155                 :  *
    8156                 :  * numCasts is set to the number of casts read in
    8157                 :  *
    8158                 :  * Skip casts from a range to its multirange, since we'll create those
    8159                 :  * automatically.
    8160                 :  */
    8161                 : CastInfo *
    8162 GIC         118 : getCasts(Archive *fout, int *numCasts)
    8163 ECB             : {
    8164                 :     PGresult   *res;
    8165                 :     int         ntups;
    8166                 :     int         i;
    8167 GIC         118 :     PQExpBuffer query = createPQExpBuffer();
    8168                 :     CastInfo   *castinfo;
    8169                 :     int         i_tableoid;
    8170                 :     int         i_oid;
    8171                 :     int         i_castsource;
    8172                 :     int         i_casttarget;
    8173                 :     int         i_castfunc;
    8174                 :     int         i_castcontext;
    8175                 :     int         i_castmethod;
    8176                 : 
    8177             118 :     if (fout->remoteVersion >= 140000)
    8178                 :     {
    8179             118 :         appendPQExpBufferStr(query, "SELECT tableoid, oid, "
    8180 ECB             :                              "castsource, casttarget, castfunc, castcontext, "
    8181                 :                              "castmethod "
    8182 EUB             :                              "FROM pg_cast c "
    8183                 :                              "WHERE NOT EXISTS ( "
    8184                 :                              "SELECT 1 FROM pg_range r "
    8185                 :                              "WHERE c.castsource = r.rngtypid "
    8186 ECB             :                              "AND c.casttarget = r.rngmultitypid "
    8187                 :                              ") "
    8188                 :                              "ORDER BY 3,4");
    8189                 :     }
    8190                 :     else
    8191                 :     {
    8192 UIC           0 :         appendPQExpBufferStr(query, "SELECT tableoid, oid, "
    8193                 :                              "castsource, casttarget, castfunc, castcontext, "
    8194                 :                              "castmethod "
    8195                 :                              "FROM pg_cast ORDER BY 3,4");
    8196                 :     }
    8197                 : 
    8198 CBC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    8199                 : 
    8200             118 :     ntups = PQntuples(res);
    8201                 : 
    8202             118 :     *numCasts = ntups;
    8203                 : 
    8204             118 :     castinfo = (CastInfo *) pg_malloc(ntups * sizeof(CastInfo));
    8205                 : 
    8206             118 :     i_tableoid = PQfnumber(res, "tableoid");
    8207             118 :     i_oid = PQfnumber(res, "oid");
    8208             118 :     i_castsource = PQfnumber(res, "castsource");
    8209             118 :     i_casttarget = PQfnumber(res, "casttarget");
    8210             118 :     i_castfunc = PQfnumber(res, "castfunc");
    8211             118 :     i_castcontext = PQfnumber(res, "castcontext");
    8212             118 :     i_castmethod = PQfnumber(res, "castmethod");
    8213 ECB             : 
    8214 GIC       26507 :     for (i = 0; i < ntups; i++)
    8215 ECB             :     {
    8216                 :         PQExpBufferData namebuf;
    8217                 :         TypeInfo   *sTypeInfo;
    8218                 :         TypeInfo   *tTypeInfo;
    8219                 : 
    8220 CBC       26389 :         castinfo[i].dobj.objType = DO_CAST;
    8221           26389 :         castinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    8222           26389 :         castinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    8223           26389 :         AssignDumpId(&castinfo[i].dobj);
    8224           26389 :         castinfo[i].castsource = atooid(PQgetvalue(res, i, i_castsource));
    8225           26389 :         castinfo[i].casttarget = atooid(PQgetvalue(res, i, i_casttarget));
    8226           26389 :         castinfo[i].castfunc = atooid(PQgetvalue(res, i, i_castfunc));
    8227           26389 :         castinfo[i].castcontext = *(PQgetvalue(res, i, i_castcontext));
    8228 GIC       26389 :         castinfo[i].castmethod = *(PQgetvalue(res, i, i_castmethod));
    8229                 : 
    8230 ECB             :         /*
    8231                 :          * Try to name cast as concatenation of typnames.  This is only used
    8232                 :          * for purposes of sorting.  If we fail to find either type, the name
    8233                 :          * will be an empty string.
    8234                 :          */
    8235 CBC       26389 :         initPQExpBuffer(&namebuf);
    8236 GIC       26389 :         sTypeInfo = findTypeByOid(castinfo[i].castsource);
    8237 CBC       26389 :         tTypeInfo = findTypeByOid(castinfo[i].casttarget);
    8238 GIC       26389 :         if (sTypeInfo && tTypeInfo)
    8239           26389 :             appendPQExpBuffer(&namebuf, "%s %s",
    8240                 :                               sTypeInfo->dobj.name, tTypeInfo->dobj.name);
    8241           26389 :         castinfo[i].dobj.name = namebuf.data;
    8242                 : 
    8243                 :         /* Decide whether we want to dump it */
    8244           26389 :         selectDumpableCast(&(castinfo[i]), fout);
    8245                 :     }
    8246                 : 
    8247             118 :     PQclear(res);
    8248                 : 
    8249             118 :     destroyPQExpBuffer(query);
    8250 ECB             : 
    8251 GIC         118 :     return castinfo;
    8252                 : }
    8253                 : 
    8254                 : static char *
    8255 CBC          90 : get_language_name(Archive *fout, Oid langid)
    8256                 : {
    8257                 :     PQExpBuffer query;
    8258                 :     PGresult   *res;
    8259                 :     char       *lanname;
    8260                 : 
    8261 GIC          90 :     query = createPQExpBuffer();
    8262              90 :     appendPQExpBuffer(query, "SELECT lanname FROM pg_language WHERE oid = %u", langid);
    8263              90 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
    8264              90 :     lanname = pg_strdup(fmtId(PQgetvalue(res, 0, 0)));
    8265              90 :     destroyPQExpBuffer(query);
    8266              90 :     PQclear(res);
    8267                 : 
    8268 CBC          90 :     return lanname;
    8269                 : }
    8270                 : 
    8271                 : /*
    8272                 :  * getTransforms
    8273                 :  *    get basic information about every transform in the system
    8274                 :  *
    8275                 :  * numTransforms is set to the number of transforms read in
    8276                 :  */
    8277                 : TransformInfo *
    8278             118 : getTransforms(Archive *fout, int *numTransforms)
    8279                 : {
    8280 ECB             :     PGresult   *res;
    8281                 :     int         ntups;
    8282                 :     int         i;
    8283                 :     PQExpBuffer query;
    8284                 :     TransformInfo *transforminfo;
    8285                 :     int         i_tableoid;
    8286                 :     int         i_oid;
    8287                 :     int         i_trftype;
    8288                 :     int         i_trflang;
    8289                 :     int         i_trffromsql;
    8290                 :     int         i_trftosql;
    8291                 : 
    8292                 :     /* Transforms didn't exist pre-9.5 */
    8293 CBC         118 :     if (fout->remoteVersion < 90500)
    8294 ECB             :     {
    8295 LBC           0 :         *numTransforms = 0;
    8296 UIC           0 :         return NULL;
    8297 ECB             :     }
    8298                 : 
    8299 CBC         118 :     query = createPQExpBuffer();
    8300 ECB             : 
    8301 CBC         118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, "
    8302 ECB             :                          "trftype, trflang, trffromsql::oid, trftosql::oid "
    8303                 :                          "FROM pg_transform "
    8304                 :                          "ORDER BY 3,4");
    8305                 : 
    8306 CBC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    8307 ECB             : 
    8308 CBC         118 :     ntups = PQntuples(res);
    8309 ECB             : 
    8310 CBC         118 :     *numTransforms = ntups;
    8311 ECB             : 
    8312 CBC         118 :     transforminfo = (TransformInfo *) pg_malloc(ntups * sizeof(TransformInfo));
    8313 ECB             : 
    8314 GIC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    8315             118 :     i_oid = PQfnumber(res, "oid");
    8316 CBC         118 :     i_trftype = PQfnumber(res, "trftype");
    8317 GIC         118 :     i_trflang = PQfnumber(res, "trflang");
    8318             118 :     i_trffromsql = PQfnumber(res, "trffromsql");
    8319 CBC         118 :     i_trftosql = PQfnumber(res, "trftosql");
    8320 ECB             : 
    8321 GIC         168 :     for (i = 0; i < ntups; i++)
    8322                 :     {
    8323 ECB             :         PQExpBufferData namebuf;
    8324                 :         TypeInfo   *typeInfo;
    8325                 :         char       *lanname;
    8326                 : 
    8327 CBC          50 :         transforminfo[i].dobj.objType = DO_TRANSFORM;
    8328 GIC          50 :         transforminfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    8329              50 :         transforminfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    8330              50 :         AssignDumpId(&transforminfo[i].dobj);
    8331              50 :         transforminfo[i].trftype = atooid(PQgetvalue(res, i, i_trftype));
    8332              50 :         transforminfo[i].trflang = atooid(PQgetvalue(res, i, i_trflang));
    8333              50 :         transforminfo[i].trffromsql = atooid(PQgetvalue(res, i, i_trffromsql));
    8334              50 :         transforminfo[i].trftosql = atooid(PQgetvalue(res, i, i_trftosql));
    8335                 : 
    8336                 :         /*
    8337                 :          * Try to name transform as concatenation of type and language name.
    8338                 :          * This is only used for purposes of sorting.  If we fail to find
    8339                 :          * either, the name will be an empty string.
    8340 ECB             :          */
    8341 GIC          50 :         initPQExpBuffer(&namebuf);
    8342              50 :         typeInfo = findTypeByOid(transforminfo[i].trftype);
    8343              50 :         lanname = get_language_name(fout, transforminfo[i].trflang);
    8344              50 :         if (typeInfo && lanname)
    8345 CBC          50 :             appendPQExpBuffer(&namebuf, "%s %s",
    8346                 :                               typeInfo->dobj.name, lanname);
    8347 GIC          50 :         transforminfo[i].dobj.name = namebuf.data;
    8348              50 :         free(lanname);
    8349                 : 
    8350                 :         /* Decide whether we want to dump it */
    8351              50 :         selectDumpableObject(&(transforminfo[i].dobj), fout);
    8352                 :     }
    8353                 : 
    8354             118 :     PQclear(res);
    8355 ECB             : 
    8356 GIC         118 :     destroyPQExpBuffer(query);
    8357 ECB             : 
    8358 GIC         118 :     return transforminfo;
    8359                 : }
    8360                 : 
    8361                 : /*
    8362                 :  * getTableAttrs -
    8363                 :  *    for each interesting table, read info about its attributes
    8364                 :  *    (names, types, default values, CHECK constraints, etc)
    8365                 :  *
    8366                 :  *  modifies tblinfo
    8367                 :  */
    8368                 : void
    8369             118 : getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
    8370 EUB             : {
    8371 GIC         118 :     DumpOptions *dopt = fout->dopt;
    8372             118 :     PQExpBuffer q = createPQExpBuffer();
    8373             118 :     PQExpBuffer tbloids = createPQExpBuffer();
    8374             118 :     PQExpBuffer checkoids = createPQExpBuffer();
    8375 GNC         118 :     PQExpBuffer defaultoids = createPQExpBuffer();
    8376                 :     PGresult   *res;
    8377 ECB             :     int         ntups;
    8378                 :     int         curtblindx;
    8379                 :     int         i_attrelid;
    8380                 :     int         i_attnum;
    8381                 :     int         i_attname;
    8382                 :     int         i_atttypname;
    8383                 :     int         i_attstattarget;
    8384                 :     int         i_attstorage;
    8385                 :     int         i_typstorage;
    8386                 :     int         i_attidentity;
    8387                 :     int         i_attgenerated;
    8388                 :     int         i_attisdropped;
    8389                 :     int         i_attlen;
    8390                 :     int         i_attalign;
    8391                 :     int         i_attislocal;
    8392                 :     int         i_attnotnull;
    8393                 :     int         i_localnotnull;
    8394                 :     int         i_attoptions;
    8395                 :     int         i_attcollation;
    8396                 :     int         i_attcompression;
    8397                 :     int         i_attfdwoptions;
    8398                 :     int         i_attmissingval;
    8399                 :     int         i_atthasdef;
    8400                 : 
    8401                 :     /*
    8402                 :      * We want to perform just one query against pg_attribute, and then just
    8403                 :      * one against pg_attrdef (for DEFAULTs) and two against pg_constraint
    8404                 :      * (for CHECK constraints and for NOT NULL constraints).  However, we
    8405                 :      * mustn't try to select every row of those catalogs and then sort it out
    8406                 :      * on the client side, because some of the server-side functions we need
    8407                 :      * would be unsafe to apply to tables we don't have lock on.  Hence, we
    8408                 :      * build an array of the OIDs of tables we care about (and now have lock
    8409                 :      * on!), and use a WHERE clause to constrain which rows are selected.
    8410                 :      */
    8411 GIC         118 :     appendPQExpBufferChar(tbloids, '{');
    8412             118 :     appendPQExpBufferChar(checkoids, '{');
    8413 GNC         118 :     appendPQExpBufferChar(defaultoids, '{');
    8414 GIC       30474 :     for (int i = 0; i < numTables; i++)
    8415 ECB             :     {
    8416 CBC       30356 :         TableInfo  *tbinfo = &tblinfo[i];
    8417 ECB             : 
    8418                 :         /* Don't bother to collect info for sequences */
    8419 CBC       30356 :         if (tbinfo->relkind == RELKIND_SEQUENCE)
    8420 GIC         445 :             continue;
    8421 ECB             : 
    8422                 :         /* Don't bother with uninteresting tables, either */
    8423 GIC       29911 :         if (!tbinfo->interesting)
    8424 CBC       25077 :             continue;
    8425                 : 
    8426                 :         /* OK, we need info for this table */
    8427            4834 :         if (tbloids->len > 1) /* do we have more than the '{'? */
    8428 GIC        4756 :             appendPQExpBufferChar(tbloids, ',');
    8429 CBC        4834 :         appendPQExpBuffer(tbloids, "%u", tbinfo->dobj.catId.oid);
    8430                 : 
    8431            4834 :         if (tbinfo->ncheck > 0)
    8432                 :         {
    8433                 :             /* Also make a list of the ones with check constraints */
    8434 GIC         465 :             if (checkoids->len > 1) /* do we have more than the '{'? */
    8435 CBC         397 :                 appendPQExpBufferChar(checkoids, ',');
    8436 GIC         465 :             appendPQExpBuffer(checkoids, "%u", tbinfo->dobj.catId.oid);
    8437                 :         }
    8438                 :     }
    8439             118 :     appendPQExpBufferChar(tbloids, '}');
    8440             118 :     appendPQExpBufferChar(checkoids, '}');
    8441 ECB             : 
    8442                 :     /*
    8443                 :      * Find all the user attributes and their types.
    8444                 :      *
    8445                 :      * Since we only want to dump COLLATE clauses for attributes whose
    8446                 :      * collation is different from their type's default, we use a CASE here to
    8447                 :      * suppress uninteresting attcollations cheaply.
    8448                 :      */
    8449 GIC         118 :     appendPQExpBufferStr(q,
    8450                 :                          "SELECT\n"
    8451                 :                          "a.attrelid,\n"
    8452                 :                          "a.attnum,\n"
    8453                 :                          "a.attname,\n"
    8454                 :                          "a.attstattarget,\n"
    8455                 :                          "a.attstorage,\n"
    8456                 :                          "t.typstorage,\n"
    8457                 :                          "a.atthasdef,\n"
    8458                 :                          "a.attisdropped,\n"
    8459                 :                          "a.attlen,\n"
    8460                 :                          "a.attalign,\n"
    8461                 :                          "a.attislocal,\n"
    8462                 :                          "pg_catalog.format_type(t.oid, a.atttypmod) AS atttypname,\n"
    8463                 :                          "array_to_string(a.attoptions, ', ') AS attoptions,\n"
    8464                 :                          "CASE WHEN a.attcollation <> t.typcollation "
    8465                 :                          "THEN a.attcollation ELSE 0 END AS attcollation,\n"
    8466                 :                          "pg_catalog.array_to_string(ARRAY("
    8467                 :                          "SELECT pg_catalog.quote_ident(option_name) || "
    8468                 :                          "' ' || pg_catalog.quote_literal(option_value) "
    8469                 :                          "FROM pg_catalog.pg_options_to_table(attfdwoptions) "
    8470                 :                          "ORDER BY option_name"
    8471 ECB             :                          "), E',\n    ') AS attfdwoptions,\n");
    8472                 : 
    8473                 :     /*
    8474                 :      * Write out NOT NULL.  In 16 and up we have to read pg_constraint, and we
    8475                 :      * only print it for constraints that aren't connoinherit.  A NULL result
    8476                 :      * means there's no contype='n' row for the column, so we mustn't print
    8477                 :      * anything then either.  We also track conislocal so that we can handle
    8478                 :      * the case of partitioned tables and binary upgrade especially.
    8479                 :      */
    8480 GNC         118 :     if (fout->remoteVersion >= 160000)
    8481             118 :         appendPQExpBufferStr(q,
    8482                 :                              "co.connoinherit IS NOT NULL AS attnotnull,\n"
    8483                 :                              "coalesce(co.conislocal, false) AS local_notnull,\n");
    8484                 :     else
    8485 UNC           0 :         appendPQExpBufferStr(q,
    8486                 :                              "a.attnotnull, false AS local_notnull,\n");
    8487                 : 
    8488 GBC         118 :     if (fout->remoteVersion >= 140000)
    8489             118 :         appendPQExpBufferStr(q,
    8490                 :                              "a.attcompression AS attcompression,\n");
    8491                 :     else
    8492 LBC           0 :         appendPQExpBufferStr(q,
    8493                 :                              "'' AS attcompression,\n");
    8494 ECB             : 
    8495 GIC         118 :     if (fout->remoteVersion >= 100000)
    8496             118 :         appendPQExpBufferStr(q,
    8497                 :                              "a.attidentity,\n");
    8498                 :     else
    8499 LBC           0 :         appendPQExpBufferStr(q,
    8500                 :                              "'' AS attidentity,\n");
    8501 ECB             : 
    8502 GIC         118 :     if (fout->remoteVersion >= 110000)
    8503 CBC         118 :         appendPQExpBufferStr(q,
    8504                 :                              "CASE WHEN a.atthasmissing AND NOT a.attisdropped "
    8505 ECB             :                              "THEN a.attmissingval ELSE null END AS attmissingval,\n");
    8506                 :     else
    8507 LBC           0 :         appendPQExpBufferStr(q,
    8508 ECB             :                              "NULL AS attmissingval,\n");
    8509                 : 
    8510 CBC         118 :     if (fout->remoteVersion >= 120000)
    8511             118 :         appendPQExpBufferStr(q,
    8512 ECB             :                              "a.attgenerated\n");
    8513                 :     else
    8514 LBC           0 :         appendPQExpBufferStr(q,
    8515                 :                              "'' AS attgenerated\n");
    8516                 : 
    8517                 :     /* need left join to pg_type to not fail on dropped columns ... */
    8518 GIC         118 :     appendPQExpBuffer(q,
    8519                 :                       "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
    8520 ECB             :                       "JOIN pg_catalog.pg_attribute a ON (src.tbloid = a.attrelid) "
    8521                 :                       "LEFT JOIN pg_catalog.pg_type t "
    8522                 :                       "ON (a.atttypid = t.oid)\n",
    8523                 :                       tbloids->data);
    8524                 : 
    8525                 :     /* in 16, need pg_constraint for NOT NULLs */
    8526 GNC         118 :     if (fout->remoteVersion >= 160000)
    8527             118 :         appendPQExpBufferStr(q,
    8528                 :                              " LEFT JOIN pg_catalog.pg_constraint co ON "
    8529                 :                              "(a.attrelid = co.conrelid\n"
    8530                 :                              "   AND co.contype = 'n' AND "
    8531                 :                              "co.conkey = array[a.attnum])\n");
    8532             118 :     appendPQExpBufferStr(q,
    8533                 :                          "WHERE a.attnum > 0::pg_catalog.int2\n"
    8534                 :                          "ORDER BY a.attrelid, a.attnum");
    8535                 : 
    8536 CBC         118 :     res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
    8537                 : 
    8538 GIC         118 :     ntups = PQntuples(res);
    8539                 : 
    8540             118 :     i_attrelid = PQfnumber(res, "attrelid");
    8541             118 :     i_attnum = PQfnumber(res, "attnum");
    8542             118 :     i_attname = PQfnumber(res, "attname");
    8543 CBC         118 :     i_atttypname = PQfnumber(res, "atttypname");
    8544             118 :     i_attstattarget = PQfnumber(res, "attstattarget");
    8545             118 :     i_attstorage = PQfnumber(res, "attstorage");
    8546             118 :     i_typstorage = PQfnumber(res, "typstorage");
    8547 GIC         118 :     i_attidentity = PQfnumber(res, "attidentity");
    8548 CBC         118 :     i_attgenerated = PQfnumber(res, "attgenerated");
    8549             118 :     i_attisdropped = PQfnumber(res, "attisdropped");
    8550 GIC         118 :     i_attlen = PQfnumber(res, "attlen");
    8551             118 :     i_attalign = PQfnumber(res, "attalign");
    8552 CBC         118 :     i_attislocal = PQfnumber(res, "attislocal");
    8553 GIC         118 :     i_attnotnull = PQfnumber(res, "attnotnull");
    8554 GNC         118 :     i_localnotnull = PQfnumber(res, "local_notnull");
    8555 GIC         118 :     i_attoptions = PQfnumber(res, "attoptions");
    8556 CBC         118 :     i_attcollation = PQfnumber(res, "attcollation");
    8557 GIC         118 :     i_attcompression = PQfnumber(res, "attcompression");
    8558 CBC         118 :     i_attfdwoptions = PQfnumber(res, "attfdwoptions");
    8559 GIC         118 :     i_attmissingval = PQfnumber(res, "attmissingval");
    8560 CBC         118 :     i_atthasdef = PQfnumber(res, "atthasdef");
    8561                 : 
    8562                 :     /* Within the next loop, we'll accumulate OIDs of tables with defaults */
    8563 GNC         118 :     resetPQExpBuffer(defaultoids);
    8564             118 :     appendPQExpBufferChar(defaultoids, '{');
    8565                 : 
    8566                 :     /*
    8567                 :      * Outer loop iterates once per table, not once per row.  Incrementing of
    8568                 :      * r is handled by the inner loop.
    8569                 :      */
    8570 GIC         118 :     curtblindx = -1;
    8571 CBC        4816 :     for (int r = 0; r < ntups;)
    8572                 :     {
    8573            4698 :         Oid         attrelid = atooid(PQgetvalue(res, r, i_attrelid));
    8574            4698 :         TableInfo  *tbinfo = NULL;
    8575 ECB             :         int         numatts;
    8576                 :         bool        hasdefaults;
    8577                 : 
    8578                 :         /* Count rows for this table */
    8579 GIC       17438 :         for (numatts = 1; numatts < ntups - r; numatts++)
    8580           17363 :             if (atooid(PQgetvalue(res, r + numatts, i_attrelid)) != attrelid)
    8581            4623 :                 break;
    8582                 : 
    8583                 :         /*
    8584                 :          * Locate the associated TableInfo; we rely on tblinfo[] being in OID
    8585                 :          * order.
    8586                 :          */
    8587           21275 :         while (++curtblindx < numTables)
    8588                 :         {
    8589           21275 :             tbinfo = &tblinfo[curtblindx];
    8590           21275 :             if (tbinfo->dobj.catId.oid == attrelid)
    8591            4698 :                 break;
    8592                 :         }
    8593            4698 :         if (curtblindx >= numTables)
    8594 UIC           0 :             pg_fatal("unrecognized table OID %u", attrelid);
    8595                 :         /* cross-check that we only got requested tables */
    8596 GIC        4698 :         if (tbinfo->relkind == RELKIND_SEQUENCE ||
    8597            4698 :             !tbinfo->interesting)
    8598 UIC           0 :             pg_fatal("unexpected column data for table \"%s\"",
    8599                 :                      tbinfo->dobj.name);
    8600                 : 
    8601                 :         /* Save data for this table */
    8602 GIC        4698 :         tbinfo->numatts = numatts;
    8603            4698 :         tbinfo->attnames = (char **) pg_malloc(numatts * sizeof(char *));
    8604            4698 :         tbinfo->atttypnames = (char **) pg_malloc(numatts * sizeof(char *));
    8605            4698 :         tbinfo->attstattarget = (int *) pg_malloc(numatts * sizeof(int));
    8606            4698 :         tbinfo->attstorage = (char *) pg_malloc(numatts * sizeof(char));
    8607            4698 :         tbinfo->typstorage = (char *) pg_malloc(numatts * sizeof(char));
    8608            4698 :         tbinfo->attidentity = (char *) pg_malloc(numatts * sizeof(char));
    8609            4698 :         tbinfo->attgenerated = (char *) pg_malloc(numatts * sizeof(char));
    8610            4698 :         tbinfo->attisdropped = (bool *) pg_malloc(numatts * sizeof(bool));
    8611            4698 :         tbinfo->attlen = (int *) pg_malloc(numatts * sizeof(int));
    8612 CBC        4698 :         tbinfo->attalign = (char *) pg_malloc(numatts * sizeof(char));
    8613            4698 :         tbinfo->attislocal = (bool *) pg_malloc(numatts * sizeof(bool));
    8614            4698 :         tbinfo->attoptions = (char **) pg_malloc(numatts * sizeof(char *));
    8615            4698 :         tbinfo->attcollation = (Oid *) pg_malloc(numatts * sizeof(Oid));
    8616 GIC        4698 :         tbinfo->attcompression = (char *) pg_malloc(numatts * sizeof(char));
    8617 CBC        4698 :         tbinfo->attfdwoptions = (char **) pg_malloc(numatts * sizeof(char *));
    8618 GIC        4698 :         tbinfo->attmissingval = (char **) pg_malloc(numatts * sizeof(char *));
    8619            4698 :         tbinfo->notnull = (bool *) pg_malloc(numatts * sizeof(bool));
    8620 GNC        4698 :         tbinfo->localNotNull = (bool *) pg_malloc(numatts * sizeof(bool));
    8621 CBC        4698 :         tbinfo->attrdefs = (AttrDefInfo **) pg_malloc(numatts * sizeof(AttrDefInfo *));
    8622 GIC        4698 :         hasdefaults = false;
    8623                 : 
    8624 CBC       22136 :         for (int j = 0; j < numatts; j++, r++)
    8625 ECB             :         {
    8626 GIC       17438 :             if (j + 1 != atoi(PQgetvalue(res, r, i_attnum)))
    8627 UIC           0 :                 pg_fatal("invalid column numbering in table \"%s\"",
    8628 ECB             :                          tbinfo->dobj.name);
    8629 CBC       17438 :             tbinfo->attnames[j] = pg_strdup(PQgetvalue(res, r, i_attname));
    8630           17438 :             tbinfo->atttypnames[j] = pg_strdup(PQgetvalue(res, r, i_atttypname));
    8631           17438 :             tbinfo->attstattarget[j] = atoi(PQgetvalue(res, r, i_attstattarget));
    8632 GIC       17438 :             tbinfo->attstorage[j] = *(PQgetvalue(res, r, i_attstorage));
    8633           17438 :             tbinfo->typstorage[j] = *(PQgetvalue(res, r, i_typstorage));
    8634 CBC       17438 :             tbinfo->attidentity[j] = *(PQgetvalue(res, r, i_attidentity));
    8635           17438 :             tbinfo->attgenerated[j] = *(PQgetvalue(res, r, i_attgenerated));
    8636           17438 :             tbinfo->needs_override = tbinfo->needs_override || (tbinfo->attidentity[j] == ATTRIBUTE_IDENTITY_ALWAYS);
    8637 GIC       17438 :             tbinfo->attisdropped[j] = (PQgetvalue(res, r, i_attisdropped)[0] == 't');
    8638           17438 :             tbinfo->attlen[j] = atoi(PQgetvalue(res, r, i_attlen));
    8639 CBC       17438 :             tbinfo->attalign[j] = *(PQgetvalue(res, r, i_attalign));
    8640           17438 :             tbinfo->attislocal[j] = (PQgetvalue(res, r, i_attislocal)[0] == 't');
    8641 GIC       17438 :             tbinfo->notnull[j] = (PQgetvalue(res, r, i_attnotnull)[0] == 't');
    8642 GNC       17438 :             tbinfo->localNotNull[j] = (PQgetvalue(res, r, i_localnotnull)[0] == 't');
    8643 GIC       17438 :             tbinfo->attoptions[j] = pg_strdup(PQgetvalue(res, r, i_attoptions));
    8644           17438 :             tbinfo->attcollation[j] = atooid(PQgetvalue(res, r, i_attcollation));
    8645           17438 :             tbinfo->attcompression[j] = *(PQgetvalue(res, r, i_attcompression));
    8646           17438 :             tbinfo->attfdwoptions[j] = pg_strdup(PQgetvalue(res, r, i_attfdwoptions));
    8647           17438 :             tbinfo->attmissingval[j] = pg_strdup(PQgetvalue(res, r, i_attmissingval));
    8648           17438 :             tbinfo->attrdefs[j] = NULL; /* fix below */
    8649           17438 :             if (PQgetvalue(res, r, i_atthasdef)[0] == 't')
    8650 CBC         882 :                 hasdefaults = true;
    8651                 :         }
    8652                 : 
    8653 GIC        4698 :         if (hasdefaults)
    8654                 :         {
    8655                 :             /* Collect OIDs of interesting tables that have defaults */
    8656 GNC         728 :             if (defaultoids->len > 1) /* do we have more than the '{'? */
    8657             677 :                 appendPQExpBufferChar(defaultoids, ',');
    8658             728 :             appendPQExpBuffer(defaultoids, "%u", tbinfo->dobj.catId.oid);
    8659                 :         }
    8660                 :     }
    8661                 : 
    8662 GIC         118 :     PQclear(res);
    8663                 : 
    8664                 :     /*
    8665                 :      * Now get info about column defaults.  This is skipped for a data-only
    8666                 :      * dump, as it is only needed for table schemas.
    8667                 :      */
    8668 GNC         118 :     if (!dopt->dataOnly && defaultoids->len > 1)
    8669                 :     {
    8670                 :         AttrDefInfo *attrdefs;
    8671                 :         int         numDefaults;
    8672 GIC          47 :         TableInfo  *tbinfo = NULL;
    8673                 : 
    8674              47 :         pg_log_info("finding table default expressions");
    8675                 : 
    8676 GNC          47 :         appendPQExpBufferChar(defaultoids, '}');
    8677                 : 
    8678 GIC          47 :         printfPQExpBuffer(q, "SELECT a.tableoid, a.oid, adrelid, adnum, "
    8679 ECB             :                           "pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc\n"
    8680                 :                           "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
    8681                 :                           "JOIN pg_catalog.pg_attrdef a ON (src.tbloid = a.adrelid)\n"
    8682                 :                           "ORDER BY a.adrelid, a.adnum",
    8683                 :                           defaultoids->data);
    8684 EUB             : 
    8685 GIC          47 :         res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
    8686                 : 
    8687 CBC          47 :         numDefaults = PQntuples(res);
    8688              47 :         attrdefs = (AttrDefInfo *) pg_malloc(numDefaults * sizeof(AttrDefInfo));
    8689                 : 
    8690 GIC          47 :         curtblindx = -1;
    8691 GBC         889 :         for (int j = 0; j < numDefaults; j++)
    8692                 :         {
    8693 GIC         842 :             Oid         adtableoid = atooid(PQgetvalue(res, j, 0));
    8694 CBC         842 :             Oid         adoid = atooid(PQgetvalue(res, j, 1));
    8695             842 :             Oid         adrelid = atooid(PQgetvalue(res, j, 2));
    8696 GIC         842 :             int         adnum = atoi(PQgetvalue(res, j, 3));
    8697             842 :             char       *adsrc = PQgetvalue(res, j, 4);
    8698 EUB             : 
    8699                 :             /*
    8700                 :              * Locate the associated TableInfo; we rely on tblinfo[] being in
    8701 ECB             :              * OID order.
    8702                 :              */
    8703 GIC         842 :             if (tbinfo == NULL || tbinfo->dobj.catId.oid != adrelid)
    8704                 :             {
    8705           14977 :                 while (++curtblindx < numTables)
    8706 EUB             :                 {
    8707 GIC       14977 :                     tbinfo = &tblinfo[curtblindx];
    8708           14977 :                     if (tbinfo->dobj.catId.oid == adrelid)
    8709 CBC         694 :                         break;
    8710 ECB             :                 }
    8711 GIC         694 :                 if (curtblindx >= numTables)
    8712 UIC           0 :                     pg_fatal("unrecognized table OID %u", adrelid);
    8713 EUB             :             }
    8714                 : 
    8715 GIC         842 :             if (adnum <= 0 || adnum > tbinfo->numatts)
    8716 UIC           0 :                 pg_fatal("invalid adnum value %d for table \"%s\"",
    8717 ECB             :                          adnum, tbinfo->dobj.name);
    8718                 : 
    8719                 :             /*
    8720                 :              * dropped columns shouldn't have defaults, but just in case,
    8721                 :              * ignore 'em
    8722                 :              */
    8723 GIC         842 :             if (tbinfo->attisdropped[adnum - 1])
    8724 UIC           0 :                 continue;
    8725 ECB             : 
    8726 CBC         842 :             attrdefs[j].dobj.objType = DO_ATTRDEF;
    8727 GIC         842 :             attrdefs[j].dobj.catId.tableoid = adtableoid;
    8728             842 :             attrdefs[j].dobj.catId.oid = adoid;
    8729             842 :             AssignDumpId(&attrdefs[j].dobj);
    8730             842 :             attrdefs[j].adtable = tbinfo;
    8731 CBC         842 :             attrdefs[j].adnum = adnum;
    8732 GIC         842 :             attrdefs[j].adef_expr = pg_strdup(adsrc);
    8733                 : 
    8734             842 :             attrdefs[j].dobj.name = pg_strdup(tbinfo->dobj.name);
    8735 CBC         842 :             attrdefs[j].dobj.namespace = tbinfo->dobj.namespace;
    8736                 : 
    8737             842 :             attrdefs[j].dobj.dump = tbinfo->dobj.dump;
    8738                 : 
    8739 ECB             :             /*
    8740                 :              * Figure out whether the default/generation expression should be
    8741                 :              * dumped as part of the main CREATE TABLE (or similar) command or
    8742                 :              * as a separate ALTER TABLE (or similar) command. The preference
    8743                 :              * is to put it into the CREATE command, but in some cases that's
    8744                 :              * not possible.
    8745                 :              */
    8746 CBC         842 :             if (tbinfo->attgenerated[adnum - 1])
    8747 ECB             :             {
    8748                 :                 /*
    8749                 :                  * Column generation expressions cannot be dumped separately,
    8750                 :                  * because there is no syntax for it.  By setting separate to
    8751                 :                  * false here we prevent the "default" from being processed as
    8752                 :                  * its own dumpable object.  Later, flagInhAttrs() will mark
    8753                 :                  * it as not to be dumped at all, if possible (that is, if it
    8754                 :                  * can be inherited from a parent).
    8755                 :                  */
    8756 CBC         360 :                 attrdefs[j].separate = false;
    8757 ECB             :             }
    8758 GIC         482 :             else if (tbinfo->relkind == RELKIND_VIEW)
    8759                 :             {
    8760                 :                 /*
    8761                 :                  * Defaults on a VIEW must always be dumped as separate ALTER
    8762                 :                  * TABLE commands.
    8763 ECB             :                  */
    8764 CBC          36 :                 attrdefs[j].separate = true;
    8765                 :             }
    8766             446 :             else if (!shouldPrintColumn(dopt, tbinfo, adnum - 1))
    8767 ECB             :             {
    8768                 :                 /* column will be suppressed, print default separately */
    8769 GIC           4 :                 attrdefs[j].separate = true;
    8770                 :             }
    8771                 :             else
    8772 ECB             :             {
    8773 CBC         442 :                 attrdefs[j].separate = false;
    8774 ECB             :             }
    8775                 : 
    8776 GIC         842 :             if (!attrdefs[j].separate)
    8777                 :             {
    8778                 :                 /*
    8779                 :                  * Mark the default as needing to appear before the table, so
    8780 ECB             :                  * that any dependencies it has must be emitted before the
    8781                 :                  * CREATE TABLE.  If this is not possible, we'll change to
    8782                 :                  * "separate" mode while sorting dependencies.
    8783                 :                  */
    8784 CBC         802 :                 addObjectDependency(&tbinfo->dobj,
    8785 GIC         802 :                                     attrdefs[j].dobj.dumpId);
    8786 ECB             :             }
    8787 EUB             : 
    8788 GIC         842 :             tbinfo->attrdefs[adnum - 1] = &attrdefs[j];
    8789 ECB             :         }
    8790                 : 
    8791 GBC          47 :         PQclear(res);
    8792                 :     }
    8793                 : 
    8794                 :     /*
    8795 ECB             :      * Get info about table CHECK constraints.  This is skipped for a
    8796                 :      * data-only dump, as it is only needed for table schemas.
    8797                 :      */
    8798 CBC         118 :     if (!dopt->dataOnly && checkoids->len > 2)
    8799 ECB             :     {
    8800                 :         ConstraintInfo *constrs;
    8801                 :         int         numConstrs;
    8802                 :         int         i_tableoid;
    8803                 :         int         i_oid;
    8804                 :         int         i_conrelid;
    8805                 :         int         i_conname;
    8806                 :         int         i_consrc;
    8807                 :         int         i_conislocal;
    8808                 :         int         i_convalidated;
    8809                 : 
    8810 CBC          63 :         pg_log_info("finding table check constraints");
    8811 ECB             : 
    8812 CBC          63 :         resetPQExpBuffer(q);
    8813              63 :         appendPQExpBuffer(q,
    8814 ECB             :                           "SELECT c.tableoid, c.oid, conrelid, conname, "
    8815                 :                           "pg_catalog.pg_get_constraintdef(c.oid) AS consrc, "
    8816                 :                           "conislocal, convalidated "
    8817                 :                           "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
    8818                 :                           "JOIN pg_catalog.pg_constraint c ON (src.tbloid = c.conrelid)\n"
    8819                 :                           "WHERE contype = 'c' "
    8820 EUB             :                           "ORDER BY c.conrelid, c.conname",
    8821                 :                           checkoids->data);
    8822 ECB             : 
    8823 CBC          63 :         res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
    8824 ECB             : 
    8825 CBC          63 :         numConstrs = PQntuples(res);
    8826              63 :         constrs = (ConstraintInfo *) pg_malloc(numConstrs * sizeof(ConstraintInfo));
    8827 ECB             : 
    8828 CBC          63 :         i_tableoid = PQfnumber(res, "tableoid");
    8829              63 :         i_oid = PQfnumber(res, "oid");
    8830              63 :         i_conrelid = PQfnumber(res, "conrelid");
    8831              63 :         i_conname = PQfnumber(res, "conname");
    8832              63 :         i_consrc = PQfnumber(res, "consrc");
    8833              63 :         i_conislocal = PQfnumber(res, "conislocal");
    8834              63 :         i_convalidated = PQfnumber(res, "convalidated");
    8835 ECB             : 
    8836                 :         /* As above, this loop iterates once per table, not once per row */
    8837 CBC          63 :         curtblindx = -1;
    8838             502 :         for (int j = 0; j < numConstrs;)
    8839 ECB             :         {
    8840 CBC         439 :             Oid         conrelid = atooid(PQgetvalue(res, j, i_conrelid));
    8841             439 :             TableInfo  *tbinfo = NULL;
    8842 ECB             :             int         numcons;
    8843                 : 
    8844                 :             /* Count rows for this table */
    8845 GIC         577 :             for (numcons = 1; numcons < numConstrs - j; numcons++)
    8846 CBC         514 :                 if (atooid(PQgetvalue(res, j + numcons, i_conrelid)) != conrelid)
    8847 GIC         376 :                     break;
    8848                 : 
    8849 ECB             :             /*
    8850                 :              * Locate the associated TableInfo; we rely on tblinfo[] being in
    8851                 :              * OID order.
    8852                 :              */
    8853 GIC       17496 :             while (++curtblindx < numTables)
    8854                 :             {
    8855 CBC       17496 :                 tbinfo = &tblinfo[curtblindx];
    8856 GIC       17496 :                 if (tbinfo->dobj.catId.oid == conrelid)
    8857             439 :                     break;
    8858                 :             }
    8859             439 :             if (curtblindx >= numTables)
    8860 UIC           0 :                 pg_fatal("unrecognized table OID %u", conrelid);
    8861 ECB             : 
    8862 GIC         439 :             if (numcons != tbinfo->ncheck)
    8863                 :             {
    8864 UIC           0 :                 pg_log_error(ngettext("expected %d check constraint on table \"%s\" but found %d",
    8865 ECB             :                                       "expected %d check constraints on table \"%s\" but found %d",
    8866                 :                                       tbinfo->ncheck),
    8867                 :                              tbinfo->ncheck, tbinfo->dobj.name, numcons);
    8868 UIC           0 :                 pg_log_error_hint("The system catalogs might be corrupted.");
    8869 LBC           0 :                 exit_nicely(1);
    8870                 :             }
    8871 ECB             : 
    8872 GIC         439 :             tbinfo->checkexprs = constrs + j;
    8873                 : 
    8874            1016 :             for (int c = 0; c < numcons; c++, j++)
    8875                 :             {
    8876             577 :                 bool        validated = PQgetvalue(res, j, i_convalidated)[0] == 't';
    8877                 : 
    8878 CBC         577 :                 constrs[j].dobj.objType = DO_CONSTRAINT;
    8879 GIC         577 :                 constrs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
    8880 CBC         577 :                 constrs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
    8881             577 :                 AssignDumpId(&constrs[j].dobj);
    8882 GIC         577 :                 constrs[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname));
    8883 CBC         577 :                 constrs[j].dobj.namespace = tbinfo->dobj.namespace;
    8884             577 :                 constrs[j].contable = tbinfo;
    8885 GIC         577 :                 constrs[j].condomain = NULL;
    8886 CBC         577 :                 constrs[j].contype = 'c';
    8887             577 :                 constrs[j].condef = pg_strdup(PQgetvalue(res, j, i_consrc));
    8888             577 :                 constrs[j].confrelid = InvalidOid;
    8889             577 :                 constrs[j].conindex = 0;
    8890             577 :                 constrs[j].condeferrable = false;
    8891 GIC         577 :                 constrs[j].condeferred = false;
    8892             577 :                 constrs[j].conislocal = (PQgetvalue(res, j, i_conislocal)[0] == 't');
    8893                 : 
    8894                 :                 /*
    8895                 :                  * An unvalidated constraint needs to be dumped separately, so
    8896 ECB             :                  * that potentially-violating existing data is loaded before
    8897                 :                  * the constraint.
    8898                 :                  */
    8899 GIC         577 :                 constrs[j].separate = !validated;
    8900 ECB             : 
    8901 CBC         577 :                 constrs[j].dobj.dump = tbinfo->dobj.dump;
    8902 ECB             : 
    8903                 :                 /*
    8904                 :                  * Mark the constraint as needing to appear before the table
    8905 EUB             :                  * --- this is so that any other dependencies of the
    8906                 :                  * constraint will be emitted before we try to create the
    8907                 :                  * table.  If the constraint is to be dumped separately, it
    8908 ECB             :                  * will be dumped after data is loaded anyway, so don't do it.
    8909 EUB             :                  * (There's an automatic dependency in the opposite direction
    8910                 :                  * anyway, so don't need to add one manually here.)
    8911                 :                  */
    8912 GIC         577 :                 if (!constrs[j].separate)
    8913             542 :                     addObjectDependency(&tbinfo->dobj,
    8914             542 :                                         constrs[j].dobj.dumpId);
    8915                 : 
    8916 ECB             :                 /*
    8917 EUB             :                  * We will detect later whether the constraint must be split
    8918                 :                  * out from the table definition.
    8919 ECB             :                  */
    8920                 :             }
    8921                 :         }
    8922                 : 
    8923 CBC          63 :         PQclear(res);
    8924 ECB             :     }
    8925                 : 
    8926                 :     /*
    8927                 :      * Get info about table NOT NULL constraints.  This is skipped for a
    8928                 :      * data-only dump, as it is only needed for table schemas.
    8929                 :      *
    8930                 :      * Optimizing for tables that have no NOT NULL constraint seems
    8931                 :      * pointless, so we don't try.
    8932                 :      */
    8933 GNC         118 :     if (!dopt->dataOnly)
    8934                 :     {
    8935                 :         ConstraintInfo *constrs;
    8936                 :         int         numConstrs;
    8937                 :         int         i_tableoid;
    8938                 :         int         i_oid;
    8939                 :         int         i_conrelid;
    8940                 :         int         i_conname;
    8941                 :         int         i_condef;
    8942                 :         int         i_conislocal;
    8943                 : 
    8944             112 :         pg_log_info("finding table not null constraints");
    8945                 : 
    8946                 :         /*
    8947                 :          * Only constraints marked connoinherit need to be handled here;
    8948                 :          * the normal constraints are instead handled by writing NOT NULL
    8949                 :          * when each column is defined.
    8950                 :          */
    8951             112 :         resetPQExpBuffer(q);
    8952             112 :         appendPQExpBuffer(q,
    8953                 :                           "SELECT co.tableoid, co.oid, conrelid, conname, "
    8954                 :                           "pg_catalog.pg_get_constraintdef(co.oid) AS condef,\n"
    8955                 :                           "  conislocal, coninhcount, connoinherit "
    8956                 :                           "FROM unnest('%s'::pg_catalog.oid[]) AS src(tbloid)\n"
    8957                 :                           "JOIN pg_catalog.pg_constraint co ON (src.tbloid = co.conrelid)\n"
    8958                 :                           "JOIN pg_catalog.pg_class c ON (conrelid = c.oid)\n"
    8959                 :                           "WHERE contype = 'n' AND connoinherit\n"
    8960                 :                           "ORDER BY co.conrelid, co.conname",
    8961                 :                           tbloids->data);
    8962                 : 
    8963             112 :         res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
    8964                 : 
    8965             112 :         numConstrs = PQntuples(res);
    8966             112 :         constrs = (ConstraintInfo *) pg_malloc(numConstrs * sizeof(ConstraintInfo));
    8967                 : 
    8968             112 :         i_tableoid = PQfnumber(res, "tableoid");
    8969             112 :         i_oid = PQfnumber(res, "oid");
    8970             112 :         i_conrelid = PQfnumber(res, "conrelid");
    8971             112 :         i_conname = PQfnumber(res, "conname");
    8972             112 :         i_condef = PQfnumber(res, "condef");
    8973             112 :         i_conislocal = PQfnumber(res, "conislocal");
    8974                 : 
    8975                 :         /* As above, this loop iterates once per table, not once per row */
    8976             112 :         curtblindx = -1;
    8977             112 :         for (int j = 0; j < numConstrs;)
    8978                 :         {
    8979 UNC           0 :             Oid         conrelid = atooid(PQgetvalue(res, j, i_conrelid));
    8980               0 :             TableInfo  *tbinfo = NULL;
    8981                 :             int         numcons;
    8982                 : 
    8983                 :             /* Count rows for this table */
    8984               0 :             for (numcons = 1; numcons < numConstrs - j; numcons++)
    8985               0 :                 if (atooid(PQgetvalue(res, j + numcons, i_conrelid)) != conrelid)
    8986               0 :                     break;
    8987                 : 
    8988                 :             /*
    8989                 :              * Locate the associated TableInfo; we rely on tblinfo[] being in
    8990                 :              * OID order.
    8991                 :              */
    8992               0 :             while (++curtblindx < numTables)
    8993                 :             {
    8994               0 :                 tbinfo = &tblinfo[curtblindx];
    8995               0 :                 if (tbinfo->dobj.catId.oid == conrelid)
    8996               0 :                     break;
    8997                 :             }
    8998               0 :             if (curtblindx >= numTables)
    8999               0 :                 pg_fatal("unrecognized table OID %u", conrelid);
    9000                 : 
    9001               0 :             for (int c = 0; c < numcons; c++, j++)
    9002                 :             {
    9003               0 :                 constrs[j].dobj.objType = DO_CONSTRAINT;
    9004               0 :                 constrs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
    9005               0 :                 constrs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
    9006               0 :                 AssignDumpId(&constrs[j].dobj);
    9007               0 :                 constrs[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname));
    9008               0 :                 constrs[j].dobj.namespace = tbinfo->dobj.namespace;
    9009               0 :                 constrs[j].contable = tbinfo;
    9010               0 :                 constrs[j].condomain = NULL;
    9011               0 :                 constrs[j].contype = 'n';
    9012               0 :                 constrs[j].condef = pg_strdup(PQgetvalue(res, j, i_condef));
    9013               0 :                 constrs[j].confrelid = InvalidOid;
    9014               0 :                 constrs[j].conindex = 0;
    9015               0 :                 constrs[j].condeferrable = false;
    9016               0 :                 constrs[j].condeferred = false;
    9017               0 :                 constrs[j].conislocal = (PQgetvalue(res, j, i_conislocal)[0] == 't');
    9018                 : 
    9019               0 :                 constrs[j].separate = true;
    9020                 : 
    9021               0 :                 constrs[j].dobj.dump = tbinfo->dobj.dump;
    9022                 :             }
    9023                 :         }
    9024                 : 
    9025 GNC         112 :         PQclear(res);
    9026                 :     }
    9027                 : 
    9028 GIC         118 :     destroyPQExpBuffer(q);
    9029 CBC         118 :     destroyPQExpBuffer(tbloids);
    9030             118 :     destroyPQExpBuffer(checkoids);
    9031 GNC         118 :     destroyPQExpBuffer(defaultoids);
    9032 GIC         118 : }
    9033 ECB             : 
    9034                 : /*
    9035                 :  * Test whether a column should be printed as part of table's CREATE TABLE.
    9036                 :  * Column number is zero-based.
    9037                 :  *
    9038                 :  * Normally this is always true, but it's false for dropped columns, as well
    9039                 :  * as those that were inherited without any local definition.  (If we print
    9040                 :  * such a column it will mistakenly get pg_attribute.attislocal set to true.)
    9041                 :  * For partitions, it's always true, because we want the partitions to be
    9042                 :  * created independently and ATTACH PARTITION used afterwards.
    9043                 :  *
    9044                 :  * In binary_upgrade mode, we must print all columns and fix the attislocal/
    9045                 :  * attisdropped state later, so as to keep control of the physical column
    9046                 :  * order.
    9047                 :  *
    9048                 :  * This function exists because there are scattered nonobvious places that
    9049                 :  * must be kept in sync with this decision.
    9050                 :  */
    9051                 : bool
    9052 CBC       32712 : shouldPrintColumn(const DumpOptions *dopt, const TableInfo *tbinfo, int colno)
    9053                 : {
    9054           32712 :     if (dopt->binary_upgrade)
    9055 GIC        5634 :         return true;
    9056           27078 :     if (tbinfo->attisdropped[colno])
    9057             347 :         return false;
    9058           26731 :     return (tbinfo->attislocal[colno] || tbinfo->ispartition);
    9059                 : }
    9060 ECB             : 
    9061                 : 
    9062                 : /*
    9063                 :  * getTSParsers:
    9064                 :  *    read all text search parsers in the system catalogs and return them
    9065                 :  *    in the TSParserInfo* structure
    9066                 :  *
    9067                 :  *  numTSParsers is set to the number of parsers read in
    9068                 :  */
    9069                 : TSParserInfo *
    9070 GIC         118 : getTSParsers(Archive *fout, int *numTSParsers)
    9071                 : {
    9072 ECB             :     PGresult   *res;
    9073                 :     int         ntups;
    9074                 :     int         i;
    9075                 :     PQExpBuffer query;
    9076                 :     TSParserInfo *prsinfo;
    9077                 :     int         i_tableoid;
    9078                 :     int         i_oid;
    9079                 :     int         i_prsname;
    9080                 :     int         i_prsnamespace;
    9081                 :     int         i_prsstart;
    9082                 :     int         i_prstoken;
    9083                 :     int         i_prsend;
    9084                 :     int         i_prsheadline;
    9085                 :     int         i_prslextype;
    9086                 : 
    9087 CBC         118 :     query = createPQExpBuffer();
    9088                 : 
    9089                 :     /*
    9090                 :      * find all text search objects, including builtin ones; we filter out
    9091                 :      * system-defined objects at dump-out time.
    9092                 :      */
    9093                 : 
    9094             118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, prsname, prsnamespace, "
    9095                 :                          "prsstart::oid, prstoken::oid, "
    9096                 :                          "prsend::oid, prsheadline::oid, prslextype::oid "
    9097                 :                          "FROM pg_ts_parser");
    9098                 : 
    9099 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    9100                 : 
    9101             118 :     ntups = PQntuples(res);
    9102             118 :     *numTSParsers = ntups;
    9103                 : 
    9104             118 :     prsinfo = (TSParserInfo *) pg_malloc(ntups * sizeof(TSParserInfo));
    9105                 : 
    9106 CBC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    9107 GIC         118 :     i_oid = PQfnumber(res, "oid");
    9108 CBC         118 :     i_prsname = PQfnumber(res, "prsname");
    9109             118 :     i_prsnamespace = PQfnumber(res, "prsnamespace");
    9110 GIC         118 :     i_prsstart = PQfnumber(res, "prsstart");
    9111             118 :     i_prstoken = PQfnumber(res, "prstoken");
    9112             118 :     i_prsend = PQfnumber(res, "prsend");
    9113             118 :     i_prsheadline = PQfnumber(res, "prsheadline");
    9114             118 :     i_prslextype = PQfnumber(res, "prslextype");
    9115                 : 
    9116             281 :     for (i = 0; i < ntups; i++)
    9117                 :     {
    9118             163 :         prsinfo[i].dobj.objType = DO_TSPARSER;
    9119 CBC         163 :         prsinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    9120 GIC         163 :         prsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    9121 CBC         163 :         AssignDumpId(&prsinfo[i].dobj);
    9122             163 :         prsinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_prsname));
    9123 GIC         326 :         prsinfo[i].dobj.namespace =
    9124 CBC         163 :             findNamespace(atooid(PQgetvalue(res, i, i_prsnamespace)));
    9125             163 :         prsinfo[i].prsstart = atooid(PQgetvalue(res, i, i_prsstart));
    9126             163 :         prsinfo[i].prstoken = atooid(PQgetvalue(res, i, i_prstoken));
    9127             163 :         prsinfo[i].prsend = atooid(PQgetvalue(res, i, i_prsend));
    9128             163 :         prsinfo[i].prsheadline = atooid(PQgetvalue(res, i, i_prsheadline));
    9129             163 :         prsinfo[i].prslextype = atooid(PQgetvalue(res, i, i_prslextype));
    9130 ECB             : 
    9131                 :         /* Decide whether we want to dump it */
    9132 GIC         163 :         selectDumpableObject(&(prsinfo[i].dobj), fout);
    9133 ECB             :     }
    9134                 : 
    9135 GIC         118 :     PQclear(res);
    9136 ECB             : 
    9137 CBC         118 :     destroyPQExpBuffer(query);
    9138                 : 
    9139 GIC         118 :     return prsinfo;
    9140                 : }
    9141 ECB             : 
    9142                 : /*
    9143                 :  * getTSDictionaries:
    9144                 :  *    read all text search dictionaries in the system catalogs and return them
    9145                 :  *    in the TSDictInfo* structure
    9146                 :  *
    9147                 :  *  numTSDicts is set to the number of dictionaries read in
    9148                 :  */
    9149                 : TSDictInfo *
    9150 GIC         118 : getTSDictionaries(Archive *fout, int *numTSDicts)
    9151 ECB             : {
    9152                 :     PGresult   *res;
    9153                 :     int         ntups;
    9154                 :     int         i;
    9155                 :     PQExpBuffer query;
    9156 EUB             :     TSDictInfo *dictinfo;
    9157                 :     int         i_tableoid;
    9158 ECB             :     int         i_oid;
    9159                 :     int         i_dictname;
    9160 EUB             :     int         i_dictnamespace;
    9161                 :     int         i_dictowner;
    9162                 :     int         i_dicttemplate;
    9163                 :     int         i_dictinitoption;
    9164                 : 
    9165 GBC         118 :     query = createPQExpBuffer();
    9166                 : 
    9167 GNC         118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, dictname, "
    9168                 :                          "dictnamespace, dictowner, "
    9169                 :                          "dicttemplate, dictinitoption "
    9170                 :                          "FROM pg_ts_dict");
    9171                 : 
    9172 CBC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    9173                 : 
    9174             118 :     ntups = PQntuples(res);
    9175             118 :     *numTSDicts = ntups;
    9176 ECB             : 
    9177 CBC         118 :     dictinfo = (TSDictInfo *) pg_malloc(ntups * sizeof(TSDictInfo));
    9178 ECB             : 
    9179 CBC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    9180             118 :     i_oid = PQfnumber(res, "oid");
    9181             118 :     i_dictname = PQfnumber(res, "dictname");
    9182             118 :     i_dictnamespace = PQfnumber(res, "dictnamespace");
    9183             118 :     i_dictowner = PQfnumber(res, "dictowner");
    9184             118 :     i_dictinitoption = PQfnumber(res, "dictinitoption");
    9185             118 :     i_dicttemplate = PQfnumber(res, "dicttemplate");
    9186 ECB             : 
    9187 CBC        3630 :     for (i = 0; i < ntups; i++)
    9188 ECB             :     {
    9189 GIC        3512 :         dictinfo[i].dobj.objType = DO_TSDICT;
    9190            3512 :         dictinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    9191            3512 :         dictinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    9192            3512 :         AssignDumpId(&dictinfo[i].dobj);
    9193            3512 :         dictinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_dictname));
    9194            7024 :         dictinfo[i].dobj.namespace =
    9195 CBC        3512 :             findNamespace(atooid(PQgetvalue(res, i, i_dictnamespace)));
    9196 GIC        3512 :         dictinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_dictowner));
    9197 CBC        3512 :         dictinfo[i].dicttemplate = atooid(PQgetvalue(res, i, i_dicttemplate));
    9198 GIC        3512 :         if (PQgetisnull(res, i, i_dictinitoption))
    9199             163 :             dictinfo[i].dictinitoption = NULL;
    9200                 :         else
    9201            3349 :             dictinfo[i].dictinitoption = pg_strdup(PQgetvalue(res, i, i_dictinitoption));
    9202                 : 
    9203                 :         /* Decide whether we want to dump it */
    9204            3512 :         selectDumpableObject(&(dictinfo[i].dobj), fout);
    9205                 :     }
    9206                 : 
    9207             118 :     PQclear(res);
    9208 ECB             : 
    9209 CBC         118 :     destroyPQExpBuffer(query);
    9210 ECB             : 
    9211 GIC         118 :     return dictinfo;
    9212                 : }
    9213                 : 
    9214                 : /*
    9215                 :  * getTSTemplates:
    9216                 :  *    read all text search templates in the system catalogs and return them
    9217                 :  *    in the TSTemplateInfo* structure
    9218                 :  *
    9219 ECB             :  *  numTSTemplates is set to the number of templates read in
    9220                 :  */
    9221                 : TSTemplateInfo *
    9222 GIC         118 : getTSTemplates(Archive *fout, int *numTSTemplates)
    9223                 : {
    9224                 :     PGresult   *res;
    9225                 :     int         ntups;
    9226                 :     int         i;
    9227                 :     PQExpBuffer query;
    9228                 :     TSTemplateInfo *tmplinfo;
    9229 ECB             :     int         i_tableoid;
    9230                 :     int         i_oid;
    9231                 :     int         i_tmplname;
    9232                 :     int         i_tmplnamespace;
    9233                 :     int         i_tmplinit;
    9234                 :     int         i_tmpllexize;
    9235                 : 
    9236 GIC         118 :     query = createPQExpBuffer();
    9237                 : 
    9238             118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, tmplname, "
    9239                 :                          "tmplnamespace, tmplinit::oid, tmpllexize::oid "
    9240 ECB             :                          "FROM pg_ts_template");
    9241                 : 
    9242 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    9243                 : 
    9244             118 :     ntups = PQntuples(res);
    9245             118 :     *numTSTemplates = ntups;
    9246                 : 
    9247 CBC         118 :     tmplinfo = (TSTemplateInfo *) pg_malloc(ntups * sizeof(TSTemplateInfo));
    9248 ECB             : 
    9249 GIC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    9250             118 :     i_oid = PQfnumber(res, "oid");
    9251             118 :     i_tmplname = PQfnumber(res, "tmplname");
    9252             118 :     i_tmplnamespace = PQfnumber(res, "tmplnamespace");
    9253             118 :     i_tmplinit = PQfnumber(res, "tmplinit");
    9254             118 :     i_tmpllexize = PQfnumber(res, "tmpllexize");
    9255                 : 
    9256             753 :     for (i = 0; i < ntups; i++)
    9257                 :     {
    9258             635 :         tmplinfo[i].dobj.objType = DO_TSTEMPLATE;
    9259 CBC         635 :         tmplinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    9260 GIC         635 :         tmplinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    9261 CBC         635 :         AssignDumpId(&tmplinfo[i].dobj);
    9262             635 :         tmplinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_tmplname));
    9263 GIC        1270 :         tmplinfo[i].dobj.namespace =
    9264 CBC         635 :             findNamespace(atooid(PQgetvalue(res, i, i_tmplnamespace)));
    9265             635 :         tmplinfo[i].tmplinit = atooid(PQgetvalue(res, i, i_tmplinit));
    9266             635 :         tmplinfo[i].tmpllexize = atooid(PQgetvalue(res, i, i_tmpllexize));
    9267 ECB             : 
    9268                 :         /* Decide whether we want to dump it */
    9269 CBC         635 :         selectDumpableObject(&(tmplinfo[i].dobj), fout);
    9270                 :     }
    9271                 : 
    9272             118 :     PQclear(res);
    9273 ECB             : 
    9274 GIC         118 :     destroyPQExpBuffer(query);
    9275 EUB             : 
    9276 GBC         118 :     return tmplinfo;
    9277                 : }
    9278                 : 
    9279                 : /*
    9280 EUB             :  * getTSConfigurations:
    9281                 :  *    read all text search configurations in the system catalogs and return
    9282                 :  *    them in the TSConfigInfo* structure
    9283                 :  *
    9284                 :  *  numTSConfigs is set to the number of configurations read in
    9285                 :  */
    9286                 : TSConfigInfo *
    9287 GIC         118 : getTSConfigurations(Archive *fout, int *numTSConfigs)
    9288 EUB             : {
    9289                 :     PGresult   *res;
    9290                 :     int         ntups;
    9291                 :     int         i;
    9292                 :     PQExpBuffer query;
    9293                 :     TSConfigInfo *cfginfo;
    9294                 :     int         i_tableoid;
    9295                 :     int         i_oid;
    9296                 :     int         i_cfgname;
    9297                 :     int         i_cfgnamespace;
    9298                 :     int         i_cfgowner;
    9299                 :     int         i_cfgparser;
    9300                 : 
    9301 GBC         118 :     query = createPQExpBuffer();
    9302 EUB             : 
    9303 GNC         118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, cfgname, "
    9304                 :                          "cfgnamespace, cfgowner, cfgparser "
    9305                 :                          "FROM pg_ts_config");
    9306 EUB             : 
    9307 GBC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    9308 EUB             : 
    9309 GBC         118 :     ntups = PQntuples(res);
    9310             118 :     *numTSConfigs = ntups;
    9311 EUB             : 
    9312 GBC         118 :     cfginfo = (TSConfigInfo *) pg_malloc(ntups * sizeof(TSConfigInfo));
    9313 EUB             : 
    9314 GIC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    9315 GBC         118 :     i_oid = PQfnumber(res, "oid");
    9316 GIC         118 :     i_cfgname = PQfnumber(res, "cfgname");
    9317 GBC         118 :     i_cfgnamespace = PQfnumber(res, "cfgnamespace");
    9318 GIC         118 :     i_cfgowner = PQfnumber(res, "cfgowner");
    9319             118 :     i_cfgparser = PQfnumber(res, "cfgparser");
    9320                 : 
    9321 CBC        3605 :     for (i = 0; i < ntups; i++)
    9322                 :     {
    9323 GIC        3487 :         cfginfo[i].dobj.objType = DO_TSCONFIG;
    9324 CBC        3487 :         cfginfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    9325            3487 :         cfginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    9326            3487 :         AssignDumpId(&cfginfo[i].dobj);
    9327            3487 :         cfginfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_cfgname));
    9328            6974 :         cfginfo[i].dobj.namespace =
    9329 GIC        3487 :             findNamespace(atooid(PQgetvalue(res, i, i_cfgnamespace)));
    9330            3487 :         cfginfo[i].rolname = getRoleName(PQgetvalue(res, i, i_cfgowner));
    9331            3487 :         cfginfo[i].cfgparser = atooid(PQgetvalue(res, i, i_cfgparser));
    9332                 : 
    9333                 :         /* Decide whether we want to dump it */
    9334            3487 :         selectDumpableObject(&(cfginfo[i].dobj), fout);
    9335                 :     }
    9336                 : 
    9337             118 :     PQclear(res);
    9338                 : 
    9339             118 :     destroyPQExpBuffer(query);
    9340                 : 
    9341             118 :     return cfginfo;
    9342                 : }
    9343                 : 
    9344                 : /*
    9345                 :  * getForeignDataWrappers:
    9346                 :  *    read all foreign-data wrappers in the system catalogs and return
    9347                 :  *    them in the FdwInfo* structure
    9348 ECB             :  *
    9349                 :  *  numForeignDataWrappers is set to the number of fdws read in
    9350                 :  */
    9351                 : FdwInfo *
    9352 CBC         118 : getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
    9353 ECB             : {
    9354                 :     PGresult   *res;
    9355                 :     int         ntups;
    9356                 :     int         i;
    9357                 :     PQExpBuffer query;
    9358                 :     FdwInfo    *fdwinfo;
    9359                 :     int         i_tableoid;
    9360                 :     int         i_oid;
    9361                 :     int         i_fdwname;
    9362                 :     int         i_fdwowner;
    9363                 :     int         i_fdwhandler;
    9364                 :     int         i_fdwvalidator;
    9365                 :     int         i_fdwacl;
    9366                 :     int         i_acldefault;
    9367                 :     int         i_fdwoptions;
    9368                 : 
    9369 GIC         118 :     query = createPQExpBuffer();
    9370                 : 
    9371 GNC         118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, fdwname, "
    9372                 :                          "fdwowner, "
    9373                 :                          "fdwhandler::pg_catalog.regproc, "
    9374                 :                          "fdwvalidator::pg_catalog.regproc, "
    9375                 :                          "fdwacl, "
    9376                 :                          "acldefault('F', fdwowner) AS acldefault, "
    9377                 :                          "array_to_string(ARRAY("
    9378                 :                          "SELECT quote_ident(option_name) || ' ' || "
    9379                 :                          "quote_literal(option_value) "
    9380                 :                          "FROM pg_options_to_table(fdwoptions) "
    9381                 :                          "ORDER BY option_name"
    9382                 :                          "), E',\n    ') AS fdwoptions "
    9383                 :                          "FROM pg_foreign_data_wrapper");
    9384                 : 
    9385 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    9386                 : 
    9387             118 :     ntups = PQntuples(res);
    9388             118 :     *numForeignDataWrappers = ntups;
    9389                 : 
    9390 CBC         118 :     fdwinfo = (FdwInfo *) pg_malloc(ntups * sizeof(FdwInfo));
    9391                 : 
    9392 GIC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    9393             118 :     i_oid = PQfnumber(res, "oid");
    9394             118 :     i_fdwname = PQfnumber(res, "fdwname");
    9395 CBC         118 :     i_fdwowner = PQfnumber(res, "fdwowner");
    9396 GIC         118 :     i_fdwhandler = PQfnumber(res, "fdwhandler");
    9397 CBC         118 :     i_fdwvalidator = PQfnumber(res, "fdwvalidator");
    9398             118 :     i_fdwacl = PQfnumber(res, "fdwacl");
    9399 GIC         118 :     i_acldefault = PQfnumber(res, "acldefault");
    9400 CBC         118 :     i_fdwoptions = PQfnumber(res, "fdwoptions");
    9401                 : 
    9402             170 :     for (i = 0; i < ntups; i++)
    9403 ECB             :     {
    9404 CBC          52 :         fdwinfo[i].dobj.objType = DO_FDW;
    9405              52 :         fdwinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    9406              52 :         fdwinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    9407              52 :         AssignDumpId(&fdwinfo[i].dobj);
    9408              52 :         fdwinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_fdwname));
    9409              52 :         fdwinfo[i].dobj.namespace = NULL;
    9410              52 :         fdwinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_fdwacl));
    9411 GIC          52 :         fdwinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
    9412 CBC          52 :         fdwinfo[i].dacl.privtype = 0;
    9413 GIC          52 :         fdwinfo[i].dacl.initprivs = NULL;
    9414 CBC          52 :         fdwinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_fdwowner));
    9415              52 :         fdwinfo[i].fdwhandler = pg_strdup(PQgetvalue(res, i, i_fdwhandler));
    9416              52 :         fdwinfo[i].fdwvalidator = pg_strdup(PQgetvalue(res, i, i_fdwvalidator));
    9417              52 :         fdwinfo[i].fdwoptions = pg_strdup(PQgetvalue(res, i, i_fdwoptions));
    9418 ECB             : 
    9419                 :         /* Decide whether we want to dump it */
    9420 CBC          52 :         selectDumpableObject(&(fdwinfo[i].dobj), fout);
    9421 ECB             : 
    9422                 :         /* Mark whether FDW has an ACL */
    9423 CBC          52 :         if (!PQgetisnull(res, i, i_fdwacl))
    9424              45 :             fdwinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
    9425 ECB             :     }
    9426                 : 
    9427 GIC         118 :     PQclear(res);
    9428 ECB             : 
    9429 GIC         118 :     destroyPQExpBuffer(query);
    9430                 : 
    9431 CBC         118 :     return fdwinfo;
    9432                 : }
    9433 ECB             : 
    9434                 : /*
    9435                 :  * getForeignServers:
    9436                 :  *    read all foreign servers in the system catalogs and return
    9437                 :  *    them in the ForeignServerInfo * structure
    9438                 :  *
    9439                 :  *  numForeignServers is set to the number of servers read in
    9440                 :  */
    9441                 : ForeignServerInfo *
    9442 GIC         118 : getForeignServers(Archive *fout, int *numForeignServers)
    9443                 : {
    9444                 :     PGresult   *res;
    9445                 :     int         ntups;
    9446 ECB             :     int         i;
    9447                 :     PQExpBuffer query;
    9448                 :     ForeignServerInfo *srvinfo;
    9449                 :     int         i_tableoid;
    9450                 :     int         i_oid;
    9451                 :     int         i_srvname;
    9452                 :     int         i_srvowner;
    9453                 :     int         i_srvfdw;
    9454                 :     int         i_srvtype;
    9455                 :     int         i_srvversion;
    9456                 :     int         i_srvacl;
    9457                 :     int         i_acldefault;
    9458                 :     int         i_srvoptions;
    9459                 : 
    9460 GIC         118 :     query = createPQExpBuffer();
    9461 ECB             : 
    9462 GNC         118 :     appendPQExpBufferStr(query, "SELECT tableoid, oid, srvname, "
    9463                 :                          "srvowner, "
    9464                 :                          "srvfdw, srvtype, srvversion, srvacl, "
    9465                 :                          "acldefault('S', srvowner) AS acldefault, "
    9466                 :                          "array_to_string(ARRAY("
    9467                 :                          "SELECT quote_ident(option_name) || ' ' || "
    9468                 :                          "quote_literal(option_value) "
    9469                 :                          "FROM pg_options_to_table(srvoptions) "
    9470                 :                          "ORDER BY option_name"
    9471                 :                          "), E',\n    ') AS srvoptions "
    9472                 :                          "FROM pg_foreign_server");
    9473 ECB             : 
    9474 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    9475 ECB             : 
    9476 CBC         118 :     ntups = PQntuples(res);
    9477             118 :     *numForeignServers = ntups;
    9478 ECB             : 
    9479 CBC         118 :     srvinfo = (ForeignServerInfo *) pg_malloc(ntups * sizeof(ForeignServerInfo));
    9480 ECB             : 
    9481 CBC         118 :     i_tableoid = PQfnumber(res, "tableoid");
    9482 GIC         118 :     i_oid = PQfnumber(res, "oid");
    9483 CBC         118 :     i_srvname = PQfnumber(res, "srvname");
    9484 GIC         118 :     i_srvowner = PQfnumber(res, "srvowner");
    9485 CBC         118 :     i_srvfdw = PQfnumber(res, "srvfdw");
    9486             118 :     i_srvtype = PQfnumber(res, "srvtype");
    9487             118 :     i_srvversion = PQfnumber(res, "srvversion");
    9488             118 :     i_srvacl = PQfnumber(res, "srvacl");
    9489             118 :     i_acldefault = PQfnumber(res, "acldefault");
    9490             118 :     i_srvoptions = PQfnumber(res, "srvoptions");
    9491 ECB             : 
    9492 CBC         174 :     for (i = 0; i < ntups; i++)
    9493 ECB             :     {
    9494 CBC          56 :         srvinfo[i].dobj.objType = DO_FOREIGN_SERVER;
    9495              56 :         srvinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    9496 GIC          56 :         srvinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    9497 CBC          56 :         AssignDumpId(&srvinfo[i].dobj);
    9498 GIC          56 :         srvinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_srvname));
    9499              56 :         srvinfo[i].dobj.namespace = NULL;
    9500 CBC          56 :         srvinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_srvacl));
    9501 GIC          56 :         srvinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
    9502              56 :         srvinfo[i].dacl.privtype = 0;
    9503 CBC          56 :         srvinfo[i].dacl.initprivs = NULL;
    9504 GIC          56 :         srvinfo[i].rolname = getRoleName(PQgetvalue(res, i, i_srvowner));
    9505 CBC          56 :         srvinfo[i].srvfdw = atooid(PQgetvalue(res, i, i_srvfdw));
    9506 GIC          56 :         srvinfo[i].srvtype = pg_strdup(PQgetvalue(res, i, i_srvtype));
    9507 CBC          56 :         srvinfo[i].srvversion = pg_strdup(PQgetvalue(res, i, i_srvversion));
    9508 GIC          56 :         srvinfo[i].srvoptions = pg_strdup(PQgetvalue(res, i, i_srvoptions));
    9509                 : 
    9510                 :         /* Decide whether we want to dump it */
    9511              56 :         selectDumpableObject(&(srvinfo[i].dobj), fout);
    9512                 : 
    9513                 :         /* Servers have user mappings */
    9514              56 :         srvinfo[i].dobj.components |= DUMP_COMPONENT_USERMAP;
    9515                 : 
    9516                 :         /* Mark whether server has an ACL */
    9517              56 :         if (!PQgetisnull(res, i, i_srvacl))
    9518 CBC          45 :             srvinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
    9519                 :     }
    9520                 : 
    9521 GIC         118 :     PQclear(res);
    9522                 : 
    9523             118 :     destroyPQExpBuffer(query);
    9524                 : 
    9525             118 :     return srvinfo;
    9526                 : }
    9527                 : 
    9528                 : /*
    9529                 :  * getDefaultACLs:
    9530                 :  *    read all default ACL information in the system catalogs and return
    9531                 :  *    them in the DefaultACLInfo structure
    9532 ECB             :  *
    9533                 :  *  numDefaultACLs is set to the number of ACLs read in
    9534                 :  */
    9535                 : DefaultACLInfo *
    9536 GIC         118 : getDefaultACLs(Archive *fout, int *numDefaultACLs)
    9537                 : {
    9538 CBC         118 :     DumpOptions *dopt = fout->dopt;
    9539                 :     DefaultACLInfo *daclinfo;
    9540 ECB             :     PQExpBuffer query;
    9541                 :     PGresult   *res;
    9542                 :     int         i_oid;
    9543                 :     int         i_tableoid;
    9544                 :     int         i_defaclrole;
    9545                 :     int         i_defaclnamespace;
    9546                 :     int         i_defaclobjtype;
    9547                 :     int         i_defaclacl;
    9548                 :     int         i_acldefault;
    9549                 :     int         i,
    9550                 :                 ntups;
    9551                 : 
    9552 CBC         118 :     query = createPQExpBuffer();
    9553                 : 
    9554 ECB             :     /*
    9555                 :      * Global entries (with defaclnamespace=0) replace the hard-wired default
    9556                 :      * ACL for their object type.  We should dump them as deltas from the
    9557                 :      * default ACL, since that will be used as a starting point for
    9558                 :      * interpreting the ALTER DEFAULT PRIVILEGES commands.  On the other hand,
    9559                 :      * non-global entries can only add privileges not revoke them.  We must
    9560                 :      * dump those as-is (i.e., as deltas from an empty ACL).
    9561                 :      *
    9562                 :      * We can use defaclobjtype as the object type for acldefault(), except
    9563                 :      * for the case of 'S' (DEFACLOBJ_SEQUENCE) which must be converted to
    9564                 :      * 's'.
    9565                 :      */
    9566 GNC         118 :     appendPQExpBufferStr(query,
    9567                 :                          "SELECT oid, tableoid, "
    9568                 :                          "defaclrole, "
    9569                 :                          "defaclnamespace, "
    9570                 :                          "defaclobjtype, "
    9571                 :                          "defaclacl, "
    9572                 :                          "CASE WHEN defaclnamespace = 0 THEN "
    9573                 :                          "acldefault(CASE WHEN defaclobjtype = 'S' "
    9574                 :                          "THEN 's'::\"char\" ELSE defaclobjtype END, "
    9575                 :                          "defaclrole) ELSE '{}' END AS acldefault "
    9576                 :                          "FROM pg_default_acl");
    9577                 : 
    9578 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    9579                 : 
    9580             118 :     ntups = PQntuples(res);
    9581             118 :     *numDefaultACLs = ntups;
    9582                 : 
    9583 CBC         118 :     daclinfo = (DefaultACLInfo *) pg_malloc(ntups * sizeof(DefaultACLInfo));
    9584                 : 
    9585 GIC         118 :     i_oid = PQfnumber(res, "oid");
    9586             118 :     i_tableoid = PQfnumber(res, "tableoid");
    9587             118 :     i_defaclrole = PQfnumber(res, "defaclrole");
    9588             118 :     i_defaclnamespace = PQfnumber(res, "defaclnamespace");
    9589             118 :     i_defaclobjtype = PQfnumber(res, "defaclobjtype");
    9590             118 :     i_defaclacl = PQfnumber(res, "defaclacl");
    9591             118 :     i_acldefault = PQfnumber(res, "acldefault");
    9592                 : 
    9593             298 :     for (i = 0; i < ntups; i++)
    9594                 :     {
    9595             180 :         Oid         nspid = atooid(PQgetvalue(res, i, i_defaclnamespace));
    9596                 : 
    9597 CBC         180 :         daclinfo[i].dobj.objType = DO_DEFAULT_ACL;
    9598 GIC         180 :         daclinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
    9599 CBC         180 :         daclinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
    9600 GIC         180 :         AssignDumpId(&daclinfo[i].dobj);
    9601                 :         /* cheesy ... is it worth coming up with a better object name? */
    9602             180 :         daclinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_defaclobjtype));
    9603 ECB             : 
    9604 GIC         180 :         if (nspid != InvalidOid)
    9605 CBC          90 :             daclinfo[i].dobj.namespace = findNamespace(nspid);
    9606 ECB             :         else
    9607 GIC          90 :             daclinfo[i].dobj.namespace = NULL;
    9608 ECB             : 
    9609 GIC         180 :         daclinfo[i].dacl.acl = pg_strdup(PQgetvalue(res, i, i_defaclacl));
    9610 CBC         180 :         daclinfo[i].dacl.acldefault = pg_strdup(PQgetvalue(res, i, i_acldefault));
    9611             180 :         daclinfo[i].dacl.privtype = 0;
    9612             180 :         daclinfo[i].dacl.initprivs = NULL;
    9613             180 :         daclinfo[i].defaclrole = getRoleName(PQgetvalue(res, i, i_defaclrole));
    9614             180 :         daclinfo[i].defaclobjtype = *(PQgetvalue(res, i, i_defaclobjtype));
    9615 ECB             : 
    9616                 :         /* Default ACLs are ACLs, of course */
    9617 CBC         180 :         daclinfo[i].dobj.components |= DUMP_COMPONENT_ACL;
    9618                 : 
    9619 ECB             :         /* Decide whether we want to dump it */
    9620 CBC         180 :         selectDumpableDefaultACL(&(daclinfo[i]), dopt);
    9621 ECB             :     }
    9622                 : 
    9623 CBC         118 :     PQclear(res);
    9624 ECB             : 
    9625 CBC         118 :     destroyPQExpBuffer(query);
    9626 ECB             : 
    9627 CBC         118 :     return daclinfo;
    9628                 : }
    9629                 : 
    9630 ECB             : /*
    9631                 :  * getRoleName -- look up the name of a role, given its OID
    9632                 :  *
    9633                 :  * In current usage, we don't expect failures, so error out for a bad OID.
    9634                 :  */
    9635                 : static const char *
    9636 GIC      447209 : getRoleName(const char *roleoid_str)
    9637 ECB             : {
    9638 GIC      447209 :     Oid         roleoid = atooid(roleoid_str);
    9639                 : 
    9640                 :     /*
    9641                 :      * Do binary search to find the appropriate item.
    9642                 :      */
    9643          447209 :     if (nrolenames > 0)
    9644                 :     {
    9645          447209 :         RoleNameItem *low = &rolenames[0];
    9646          447209 :         RoleNameItem *high = &rolenames[nrolenames - 1];
    9647                 : 
    9648 CBC     1789024 :         while (low <= high)
    9649                 :         {
    9650 GIC     1789024 :             RoleNameItem *middle = low + (high - low) / 2;
    9651                 : 
    9652         1789024 :             if (roleoid < middle->roleoid)
    9653         1340620 :                 high = middle - 1;
    9654          448404 :             else if (roleoid > middle->roleoid)
    9655            1195 :                 low = middle + 1;
    9656                 :             else
    9657          447209 :                 return middle->rolename; /* found a match */
    9658                 :         }
    9659                 :     }
    9660                 : 
    9661 UIC           0 :     pg_fatal("role with OID %u does not exist", roleoid);
    9662                 :     return NULL;                /* keep compiler quiet */
    9663                 : }
    9664                 : 
    9665 ECB             : /*
    9666                 :  * collectRoleNames --
    9667                 :  *
    9668                 :  * Construct a table of all known roles.
    9669                 :  * The table is sorted by OID for speed in lookup.
    9670                 :  */
    9671                 : static void
    9672 GIC         119 : collectRoleNames(Archive *fout)
    9673                 : {
    9674                 :     PGresult   *res;
    9675                 :     const char *query;
    9676                 :     int         i;
    9677                 : 
    9678             119 :     query = "SELECT oid, rolname FROM pg_catalog.pg_roles ORDER BY 1";
    9679                 : 
    9680             119 :     res = ExecuteSqlQuery(fout, query, PGRES_TUPLES_OK);
    9681 ECB             : 
    9682 GIC         119 :     nrolenames = PQntuples(res);
    9683 ECB             : 
    9684 CBC         119 :     rolenames = (RoleNameItem *) pg_malloc(nrolenames * sizeof(RoleNameItem));
    9685                 : 
    9686            2199 :     for (i = 0; i < nrolenames; i++)
    9687                 :     {
    9688            2080 :         rolenames[i].roleoid = atooid(PQgetvalue(res, i, 0));
    9689            2080 :         rolenames[i].rolename = pg_strdup(PQgetvalue(res, i, 1));
    9690 ECB             :     }
    9691                 : 
    9692 CBC         119 :     PQclear(res);
    9693             119 : }
    9694 ECB             : 
    9695                 : /*
    9696                 :  * getAdditionalACLs
    9697                 :  *
    9698                 :  * We have now created all the DumpableObjects, and collected the ACL data
    9699                 :  * that appears in the directly-associated catalog entries.  However, there's
    9700                 :  * more ACL-related info to collect.  If any of a table's columns have ACLs,
    9701                 :  * we must set the TableInfo's DUMP_COMPONENT_ACL components flag, as well as
    9702                 :  * its hascolumnACLs flag (we won't store the ACLs themselves here, though).
    9703                 :  * Also, in versions having the pg_init_privs catalog, read that and load the
    9704                 :  * information into the relevant DumpableObjects.
    9705                 :  */
    9706                 : static void
    9707 CBC         116 : getAdditionalACLs(Archive *fout)
    9708 ECB             : {
    9709 CBC         116 :     PQExpBuffer query = createPQExpBuffer();
    9710 ECB             :     PGresult   *res;
    9711                 :     int         ntups,
    9712                 :                 i;
    9713                 : 
    9714                 :     /* Check for per-column ACLs */
    9715 GIC         116 :     appendPQExpBufferStr(query,
    9716 ECB             :                          "SELECT DISTINCT attrelid FROM pg_attribute "
    9717                 :                          "WHERE attacl IS NOT NULL");
    9718                 : 
    9719 CBC         116 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    9720 ECB             : 
    9721 GIC         116 :     ntups = PQntuples(res);
    9722             351 :     for (i = 0; i < ntups; i++)
    9723 ECB             :     {
    9724 GIC         235 :         Oid         relid = atooid(PQgetvalue(res, i, 0));
    9725 ECB             :         TableInfo  *tblinfo;
    9726                 : 
    9727 CBC         235 :         tblinfo = findTableByOid(relid);
    9728                 :         /* OK to ignore tables we haven't got a DumpableObject for */
    9729 GIC         235 :         if (tblinfo)
    9730                 :         {
    9731             235 :             tblinfo->dobj.components |= DUMP_COMPONENT_ACL;
    9732             235 :             tblinfo->hascolumnACLs = true;
    9733                 :         }
    9734                 :     }
    9735             116 :     PQclear(res);
    9736                 : 
    9737                 :     /* Fetch initial-privileges data */
    9738 CBC         116 :     if (fout->remoteVersion >= 90600)
    9739                 :     {
    9740 GIC         116 :         printfPQExpBuffer(query,
    9741                 :                           "SELECT objoid, classoid, objsubid, privtype, initprivs "
    9742                 :                           "FROM pg_init_privs");
    9743                 : 
    9744             116 :         res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
    9745                 : 
    9746             116 :         ntups = PQntuples(res);
    9747           25863 :         for (i = 0; i < ntups; i++)
    9748                 :         {
    9749           25747 :             Oid         objoid = atooid(PQgetvalue(res, i, 0));
    9750           25747 :             Oid         classoid = atooid(PQgetvalue(res, i, 1));
    9751           25747 :             int         objsubid = atoi(PQgetvalue(res, i, 2));
    9752           25747 :             char        privtype = *(PQgetvalue(res, i, 3));
    9753           25747 :             char       *initprivs = PQgetvalue(res, i, 4);
    9754                 :             CatalogId   objId;
    9755                 :             DumpableObject *dobj;
    9756 ECB             : 
    9757 GIC       25747 :             objId.tableoid = classoid;
    9758 CBC       25747 :             objId.oid = objoid;
    9759 GIC       25747 :             dobj = findObjectByCatalogId(objId);
    9760                 :             /* OK to ignore entries we haven't got a DumpableObject for */
    9761           25747 :             if (dobj)
    9762                 :             {
    9763                 :                 /* Cope with sub-object initprivs */
    9764           18599 :                 if (objsubid != 0)
    9765                 :                 {
    9766            1877 :                     if (dobj->objType == DO_TABLE)
    9767                 :                     {
    9768                 :                         /* For a column initpriv, set the table's ACL flags */
    9769            1877 :                         dobj->components |= DUMP_COMPONENT_ACL;
    9770 CBC        1877 :                         ((TableInfo *) dobj)->hascolumnACLs = true;
    9771                 :                     }
    9772 ECB             :                     else
    9773 LBC           0 :                         pg_log_warning("unsupported pg_init_privs entry: %u %u %d",
    9774                 :                                        classoid, objoid, objsubid);
    9775 CBC        1989 :                     continue;
    9776                 :                 }
    9777 ECB             : 
    9778                 :                 /*
    9779                 :                  * We ignore any pg_init_privs.initprivs entry for the public
    9780                 :                  * schema, as explained in getNamespaces().
    9781                 :                  */
    9782 CBC       16722 :                 if (dobj->objType == DO_NAMESPACE &&
    9783             228 :                     strcmp(dobj->name, "public") == 0)
    9784             112 :                     continue;
    9785 ECB             : 
    9786                 :                 /* Else it had better be of a type we think has ACLs */
    9787 GIC       16610 :                 if (dobj->objType == DO_NAMESPACE ||
    9788 CBC       16494 :                     dobj->objType == DO_TYPE ||
    9789 GIC       16473 :                     dobj->objType == DO_FUNC ||
    9790 CBC       16387 :                     dobj->objType == DO_AGG ||
    9791           16366 :                     dobj->objType == DO_TABLE ||
    9792 LBC           0 :                     dobj->objType == DO_PROCLANG ||
    9793               0 :                     dobj->objType == DO_FDW ||
    9794               0 :                     dobj->objType == DO_FOREIGN_SERVER)
    9795 CBC       16610 :                 {
    9796           16610 :                     DumpableObjectWithAcl *daobj = (DumpableObjectWithAcl *) dobj;
    9797 ECB             : 
    9798 CBC       16610 :                     daobj->dacl.privtype = privtype;
    9799           16610 :                     daobj->dacl.initprivs = pstrdup(initprivs);
    9800 ECB             :                 }
    9801                 :                 else
    9802 LBC           0 :                     pg_log_warning("unsupported pg_init_privs entry: %u %u %d",
    9803 ECB             :                                    classoid, objoid, objsubid);
    9804                 :             }
    9805                 :         }
    9806 GIC         116 :         PQclear(res);
    9807 ECB             :     }
    9808                 : 
    9809 GIC         116 :     destroyPQExpBuffer(query);
    9810 CBC         116 : }
    9811                 : 
    9812                 : /*
    9813 ECB             :  * dumpCommentExtended --
    9814                 :  *
    9815                 :  * This routine is used to dump any comments associated with the
    9816                 :  * object handed to this routine. The routine takes the object type
    9817                 :  * and object name (ready to print, except for schema decoration), plus
    9818                 :  * the namespace and owner of the object (for labeling the ArchiveEntry),
    9819                 :  * plus catalog ID and subid which are the lookup key for pg_description,
    9820                 :  * plus the dump ID for the object (for setting a dependency).
    9821                 :  * If a matching pg_description entry is found, it is dumped.
    9822                 :  *
    9823                 :  * Note: in some cases, such as comments for triggers and rules, the "type"
    9824                 :  * string really looks like, e.g., "TRIGGER name ON".  This is a bit of a hack
    9825                 :  * but it doesn't seem worth complicating the API for all callers to make
    9826                 :  * it cleaner.
    9827                 :  *
    9828                 :  * Note: although this routine takes a dumpId for dependency purposes,
    9829                 :  * that purpose is just to mark the dependency in the emitted dump file
    9830                 :  * for possible future use by pg_restore.  We do NOT use it for determining
    9831                 :  * ordering of the comment in the dump file, because this routine is called
    9832                 :  * after dependency sorting occurs.  This routine should be called just after
    9833                 :  * calling ArchiveEntry() for the specified object.
    9834                 :  */
    9835                 : static void
    9836 GIC         742 : dumpCommentExtended(Archive *fout, const char *type,
    9837                 :                     const char *name, const char *namespace,
    9838                 :                     const char *owner, CatalogId catalogId,
    9839                 :                     int subid, DumpId dumpId,
    9840                 :                     const char *initdb_comment)
    9841                 : {
    9842             742 :     DumpOptions *dopt = fout->dopt;
    9843                 :     CommentItem *comments;
    9844                 :     int         ncomments;
    9845                 : 
    9846                 :     /* do nothing, if --no-comments is supplied */
    9847             742 :     if (dopt->no_comments)
    9848 LBC           0 :         return;
    9849                 : 
    9850                 :     /* Comments are schema not data ... except LO comments are data */
    9851 GIC         742 :     if (strcmp(type, "LARGE OBJECT") != 0)
    9852                 :     {
    9853             695 :         if (dopt->dataOnly)
    9854 UIC           0 :             return;
    9855                 :     }
    9856                 :     else
    9857                 :     {
    9858                 :         /* We do dump LO comments in binary-upgrade mode */
    9859 GIC          47 :         if (dopt->schemaOnly && !dopt->binary_upgrade)
    9860 UIC           0 :             return;
    9861                 :     }
    9862 ECB             : 
    9863                 :     /* Search for comments associated with catalogId, using table */
    9864 GIC         742 :     ncomments = findComments(catalogId.tableoid, catalogId.oid,
    9865                 :                              &comments);
    9866                 : 
    9867                 :     /* Is there one matching the subid? */
    9868             742 :     while (ncomments > 0)
    9869                 :     {
    9870             702 :         if (comments->objsubid == subid)
    9871             702 :             break;
    9872 UIC           0 :         comments++;
    9873               0 :         ncomments--;
    9874 ECB             :     }
    9875                 : 
    9876 CBC         742 :     if (initdb_comment != NULL)
    9877 ECB             :     {
    9878                 :         static CommentItem empty_comment = {.descr = ""};
    9879                 : 
    9880                 :         /*
    9881                 :          * initdb creates this object with a comment.  Skip dumping the
    9882                 :          * initdb-provided comment, which would complicate matters for
    9883                 :          * non-superuser use of pg_dump.  When the DBA has removed initdb's
    9884                 :          * comment, replicate that.
    9885                 :          */
    9886 CBC          93 :         if (ncomments == 0)
    9887 ECB             :         {
    9888 GIC           4 :             comments = &empty_comment;
    9889 CBC           4 :             ncomments = 1;
    9890                 :         }
    9891              89 :         else if (strcmp(comments->descr, initdb_comment) == 0)
    9892 GIC          89 :             ncomments = 0;
    9893 ECB             :     }
    9894                 : 
    9895                 :     /* If a comment exists, build COMMENT ON statement */
    9896 CBC         742 :     if (ncomments > 0)
    9897                 :     {
    9898             617 :         PQExpBuffer query = createPQExpBuffer();
    9899 GIC         617 :         PQExpBuffer tag = createPQExpBuffer();
    9900 ECB             : 
    9901 CBC         617 :         appendPQExpBuffer(query, "COMMENT ON %s ", type);
    9902 GIC         617 :         if (namespace && *namespace)
    9903 CBC         471 :             appendPQExpBuffer(query, "%s.", fmtId(namespace));
    9904 GIC         617 :         appendPQExpBuffer(query, "%s IS ", name);
    9905 CBC         617 :         appendStringLiteralAH(query, comments->descr, fout);
    9906             617 :         appendPQExpBufferStr(query, ";\n");
    9907 ECB             : 
    9908 CBC         617 :         appendPQExpBuffer(tag, "%s %s", type, name);
    9909 ECB             : 
    9910                 :         /*
    9911                 :          * We mark comments as SECTION_NONE because they really belong in the
    9912                 :          * same section as their parent, whether that is pre-data or
    9913                 :          * post-data.
    9914                 :          */
    9915 GIC         617 :         ArchiveEntry(fout, nilCatalogId, createDumpId(),
    9916 CBC         617 :                      ARCHIVE_OPTS(.tag = tag->data,
    9917                 :                                   .namespace = namespace,
    9918                 :                                   .owner = owner,
    9919 ECB             :                                   .description = "COMMENT",
    9920                 :                                   .section = SECTION_NONE,
    9921                 :                                   .createStmt = query->data,
    9922                 :                                   .deps = &dumpId,
    9923                 :                                   .nDeps = 1));
    9924                 : 
    9925 GIC         617 :         destroyPQExpBuffer(query);
    9926             617 :         destroyPQExpBuffer(tag);
    9927                 :     }
    9928                 : }
    9929                 : 
    9930                 : /*
    9931                 :  * dumpComment --
    9932 ECB             :  *
    9933                 :  * Typical simplification of the above function.
    9934                 :  */
    9935                 : static inline void
    9936 GIC         641 : dumpComment(Archive *fout, const char *type,
    9937                 :             const char *name, const char *namespace,
    9938                 :             const char *owner, CatalogId catalogId,
    9939 ECB             :             int subid, DumpId dumpId)
    9940                 : {
    9941 CBC         641 :     dumpCommentExtended(fout, type, name, namespace, owner,
    9942 ECB             :                         catalogId, subid, dumpId, NULL);
    9943 GIC         641 : }
    9944 ECB             : 
    9945                 : /*
    9946                 :  * dumpTableComment --
    9947                 :  *
    9948                 :  * As above, but dump comments for both the specified table (or view)
    9949                 :  * and its columns.
    9950                 :  */
    9951                 : static void
    9952 GIC          82 : dumpTableComment(Archive *fout, const TableInfo *tbinfo,
    9953 ECB             :                  const char *reltypename)
    9954                 : {
    9955 GIC          82 :     DumpOptions *dopt = fout->dopt;
    9956                 :     CommentItem *comments;
    9957 EUB             :     int         ncomments;
    9958                 :     PQExpBuffer query;
    9959                 :     PQExpBuffer tag;
    9960                 : 
    9961                 :     /* do nothing, if --no-comments is supplied */
    9962 GIC          82 :     if (dopt->no_comments)
    9963 UIC           0 :         return;
    9964                 : 
    9965                 :     /* Comments are SCHEMA not data */
    9966 GIC          82 :     if (dopt->dataOnly)
    9967 UIC           0 :         return;
    9968 ECB             : 
    9969                 :     /* Search for comments associated with relation, using table */
    9970 GIC          82 :     ncomments = findComments(tbinfo->dobj.catId.tableoid,
    9971              82 :                              tbinfo->dobj.catId.oid,
    9972                 :                              &comments);
    9973                 : 
    9974 ECB             :     /* If comments exist, build COMMENT ON statements */
    9975 GIC          82 :     if (ncomments <= 0)
    9976 LBC           0 :         return;
    9977                 : 
    9978 CBC          82 :     query = createPQExpBuffer();
    9979 GIC          82 :     tag = createPQExpBuffer();
    9980 ECB             : 
    9981 GIC         236 :     while (ncomments > 0)
    9982 ECB             :     {
    9983 GIC         154 :         const char *descr = comments->descr;
    9984 CBC         154 :         int         objsubid = comments->objsubid;
    9985 ECB             : 
    9986 GIC         154 :         if (objsubid == 0)
    9987                 :         {
    9988 CBC          36 :             resetPQExpBuffer(tag);
    9989              36 :             appendPQExpBuffer(tag, "%s %s", reltypename,
    9990 GIC          36 :                               fmtId(tbinfo->dobj.name));
    9991                 : 
    9992              36 :             resetPQExpBuffer(query);
    9993              36 :             appendPQExpBuffer(query, "COMMENT ON %s %s IS ", reltypename,
    9994              36 :                               fmtQualifiedDumpable(tbinfo));
    9995              36 :             appendStringLiteralAH(query, descr, fout);
    9996              36 :             appendPQExpBufferStr(query, ";\n");
    9997                 : 
    9998              36 :             ArchiveEntry(fout, nilCatalogId, createDumpId(),
    9999              36 :                          ARCHIVE_OPTS(.tag = tag->data,
   10000                 :                                       .namespace = tbinfo->dobj.namespace->dobj.name,
   10001                 :                                       .owner = tbinfo->rolname,
   10002                 :                                       .description = "COMMENT",
   10003 ECB             :                                       .section = SECTION_NONE,
   10004                 :                                       .createStmt = query->data,
   10005                 :                                       .deps = &(tbinfo->dobj.dumpId),
   10006                 :                                       .nDeps = 1));
   10007                 :         }
   10008 GIC         118 :         else if (objsubid > 0 && objsubid <= tbinfo->numatts)
   10009                 :         {
   10010             118 :             resetPQExpBuffer(tag);
   10011 CBC         118 :             appendPQExpBuffer(tag, "COLUMN %s.",
   10012 GIC         118 :                               fmtId(tbinfo->dobj.name));
   10013             118 :             appendPQExpBufferStr(tag, fmtId(tbinfo->attnames[objsubid - 1]));
   10014                 : 
   10015 CBC         118 :             resetPQExpBuffer(query);
   10016 GIC         118 :             appendPQExpBuffer(query, "COMMENT ON COLUMN %s.",
   10017 CBC         118 :                               fmtQualifiedDumpable(tbinfo));
   10018             118 :             appendPQExpBuffer(query, "%s IS ",
   10019 GIC         118 :                               fmtId(tbinfo->attnames[objsubid - 1]));
   10020 CBC         118 :             appendStringLiteralAH(query, descr, fout);
   10021 GIC         118 :             appendPQExpBufferStr(query, ";\n");
   10022                 : 
   10023 CBC         118 :             ArchiveEntry(fout, nilCatalogId, createDumpId(),
   10024 GIC         118 :                          ARCHIVE_OPTS(.tag = tag->data,
   10025 ECB             :                                       .namespace = tbinfo->dobj.namespace->dobj.name,
   10026                 :                                       .owner = tbinfo->rolname,
   10027                 :                                       .description = "COMMENT",
   10028                 :                                       .section = SECTION_NONE,
   10029                 :                                       .createStmt = query->data,
   10030                 :                                       .deps = &(tbinfo->dobj.dumpId),
   10031                 :                                       .nDeps = 1));
   10032                 :         }
   10033                 : 
   10034 CBC         154 :         comments++;
   10035 GIC         154 :         ncomments--;
   10036 ECB             :     }
   10037                 : 
   10038 GIC          82 :     destroyPQExpBuffer(query);
   10039              82 :     destroyPQExpBuffer(tag);
   10040 ECB             : }
   10041                 : 
   10042                 : /*
   10043                 :  * findComments --
   10044                 :  *
   10045                 :  * Find the comment(s), if any, associated with the given object.  All the
   10046                 :  * objsubid values associated with the given classoid/objoid are found with
   10047                 :  * one search.
   10048                 :  */
   10049                 : static int
   10050 GIC         860 : findComments(Oid classoid, Oid objoid, CommentItem **items)
   10051                 : {
   10052             860 :     CommentItem *middle = NULL;
   10053 ECB             :     CommentItem *low;
   10054                 :     CommentItem *high;
   10055                 :     int         nmatch;
   10056                 : 
   10057                 :     /*
   10058                 :      * Do binary search to find some item matching the object.
   10059                 :      */
   10060 CBC         860 :     low = &comments[0];
   10061 GIC         860 :     high = &comments[ncomments - 1];
   10062 CBC        8410 :     while (low <= high)
   10063                 :     {
   10064 GIC        8370 :         middle = low + (high - low) / 2;
   10065 ECB             : 
   10066 CBC        8370 :         if (classoid < middle->classoid)
   10067 GIC        3522 :             high = middle - 1;
   10068            4848 :         else if (classoid > middle->classoid)
   10069 GBC        2370 :             low = middle + 1;
   10070 GIC        2478 :         else if (objoid < middle->objoid)
   10071 CBC         199 :             high = middle - 1;
   10072 GIC        2279 :         else if (objoid > middle->objoid)
   10073            1459 :             low = middle + 1;
   10074                 :         else
   10075             820 :             break;              /* found a match */
   10076                 :     }
   10077                 : 
   10078 CBC         860 :     if (low > high)              /* no matches */
   10079 ECB             :     {
   10080 CBC          40 :         *items = NULL;
   10081 GIC          40 :         return 0;
   10082                 :     }
   10083 ECB             : 
   10084                 :     /*
   10085                 :      * Now determine how many items match the object.  The search loop
   10086                 :      * invariant still holds: only items between low and high inclusive could
   10087                 :      * match.
   10088 EUB             :      */
   10089 GBC         820 :     nmatch = 1;
   10090             820 :     while (middle > low)
   10091 ECB             :     {
   10092 CBC         497 :         if (classoid != middle[-1].classoid ||
   10093 GIC         412 :             objoid != middle[-1].objoid)
   10094 ECB             :             break;
   10095 LBC           0 :         middle--;
   10096 UIC           0 :         nmatch++;
   10097                 :     }
   10098 EUB             : 
   10099 GIC         820 :     *items = middle;
   10100                 : 
   10101             820 :     middle += nmatch;
   10102 CBC         892 :     while (middle <= high)
   10103                 :     {
   10104 GIC         539 :         if (classoid != middle->classoid ||
   10105 CBC         164 :             objoid != middle->objoid)
   10106 ECB             :             break;
   10107 GIC          72 :         middle++;
   10108              72 :         nmatch++;
   10109                 :     }
   10110                 : 
   10111             820 :     return nmatch;
   10112                 : }
   10113                 : 
   10114                 : /*
   10115                 :  * collectComments --
   10116                 :  *
   10117                 :  * Construct a table of all comments available for database objects;
   10118                 :  * also set the has-comment component flag for each relevant object.
   10119                 :  *
   10120                 :  * We used to do per-object queries for the comments, but it's much faster
   10121                 :  * to pull them all over at once, and on most databases the memory cost
   10122                 :  * isn't high.
   10123                 :  *
   10124                 :  * The table is sorted by classoid/objid/objsubid for speed in lookup.
   10125                 :  */
   10126                 : static void
   10127             118 : collectComments(Archive *fout)
   10128                 : {
   10129                 :     PGresult   *res;
   10130                 :     PQExpBuffer query;
   10131                 :     int         i_description;
   10132 ECB             :     int         i_classoid;
   10133                 :     int         i_objoid;
   10134                 :     int         i_objsubid;
   10135                 :     int         ntups;
   10136                 :     int         i;
   10137                 :     DumpableObject *dobj;
   10138                 : 
   10139 GIC         118 :     query = createPQExpBuffer();
   10140                 : 
   10141             118 :     appendPQExpBufferStr(query, "SELECT description, classoid, objoid, objsubid "
   10142                 :                          "FROM pg_catalog.pg_description "
   10143 ECB             :                          "ORDER BY classoid, objoid, objsubid");
   10144 EUB             : 
   10145 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   10146                 : 
   10147 ECB             :     /* Construct lookup table containing OIDs in numeric form */
   10148                 : 
   10149 CBC         118 :     i_description = PQfnumber(res, "description");
   10150 GBC         118 :     i_classoid = PQfnumber(res, "classoid");
   10151 GIC         118 :     i_objoid = PQfnumber(res, "objoid");
   10152             118 :     i_objsubid = PQfnumber(res, "objsubid");
   10153                 : 
   10154             118 :     ntups = PQntuples(res);
   10155 ECB             : 
   10156 GBC         118 :     comments = (CommentItem *) pg_malloc(ntups * sizeof(CommentItem));
   10157 GIC         118 :     ncomments = 0;
   10158             118 :     dobj = NULL;
   10159                 : 
   10160 CBC      614578 :     for (i = 0; i < ntups; i++)
   10161                 :     {
   10162                 :         CatalogId   objId;
   10163                 :         int         subid;
   10164 ECB             : 
   10165 GIC      614460 :         objId.tableoid = atooid(PQgetvalue(res, i, i_classoid));
   10166 CBC      614460 :         objId.oid = atooid(PQgetvalue(res, i, i_objoid));
   10167          614460 :         subid = atoi(PQgetvalue(res, i, i_objsubid));
   10168 EUB             : 
   10169                 :         /* We needn't remember comments that don't match any dumpable object */
   10170 GIC      614460 :         if (dobj == NULL ||
   10171          226096 :             dobj->catId.tableoid != objId.tableoid ||
   10172 CBC      224565 :             dobj->catId.oid != objId.oid)
   10173 GIC      614370 :             dobj = findObjectByCatalogId(objId);
   10174          614460 :         if (dobj == NULL)
   10175          388250 :             continue;
   10176                 : 
   10177                 :         /*
   10178                 :          * Comments on columns of composite types are linked to the type's
   10179                 :          * pg_class entry, but we need to set the DUMP_COMPONENT_COMMENT flag
   10180                 :          * in the type's own DumpableObject.
   10181                 :          */
   10182 CBC      226210 :         if (subid != 0 && dobj->objType == DO_TABLE &&
   10183 GIC         190 :             ((TableInfo *) dobj)->relkind == RELKIND_COMPOSITE_TYPE)
   10184 CBC          45 :         {
   10185 ECB             :             TypeInfo   *cTypeInfo;
   10186                 : 
   10187 CBC          45 :             cTypeInfo = findTypeByOid(((TableInfo *) dobj)->reltype);
   10188              45 :             if (cTypeInfo)
   10189 GIC          45 :                 cTypeInfo->dobj.components |= DUMP_COMPONENT_COMMENT;
   10190                 :         }
   10191                 :         else
   10192 CBC      226165 :             dobj->components |= DUMP_COMPONENT_COMMENT;
   10193                 : 
   10194          226210 :         comments[ncomments].descr = pg_strdup(PQgetvalue(res, i, i_description));
   10195          226210 :         comments[ncomments].classoid = objId.tableoid;
   10196 GIC      226210 :         comments[ncomments].objoid = objId.oid;
   10197 CBC      226210 :         comments[ncomments].objsubid = subid;
   10198          226210 :         ncomments++;
   10199 ECB             :     }
   10200                 : 
   10201 CBC         118 :     PQclear(res);
   10202             118 :     destroyPQExpBuffer(query);
   10203 GIC         118 : }
   10204 ECB             : 
   10205                 : /*
   10206                 :  * dumpDumpableObject
   10207                 :  *
   10208                 :  * This routine and its subsidiaries are responsible for creating
   10209                 :  * ArchiveEntries (TOC objects) for each object to be dumped.
   10210                 :  */
   10211                 : static void
   10212 CBC      510020 : dumpDumpableObject(Archive *fout, DumpableObject *dobj)
   10213                 : {
   10214                 :     /*
   10215                 :      * Clear any dump-request bits for components that don't exist for this
   10216                 :      * object.  (This makes it safe to initially use DUMP_COMPONENT_ALL as the
   10217                 :      * request for every kind of object.)
   10218                 :      */
   10219 GIC      510020 :     dobj->dump &= dobj->components;
   10220                 : 
   10221 ECB             :     /* Now, short-circuit if there's nothing to be done here. */
   10222 CBC      510020 :     if (dobj->dump == 0)
   10223 GIC      462464 :         return;
   10224                 : 
   10225           47556 :     switch (dobj->objType)
   10226                 :     {
   10227             339 :         case DO_NAMESPACE:
   10228             339 :             dumpNamespace(fout, (const NamespaceInfo *) dobj);
   10229             339 :             break;
   10230              18 :         case DO_EXTENSION:
   10231              18 :             dumpExtension(fout, (const ExtensionInfo *) dobj);
   10232 CBC          18 :             break;
   10233 GIC         523 :         case DO_TYPE:
   10234             523 :             dumpType(fout, (const TypeInfo *) dobj);
   10235             523 :             break;
   10236              74 :         case DO_SHELL_TYPE:
   10237 CBC          74 :             dumpShellType(fout, (const ShellTypeInfo *) dobj);
   10238 GIC          74 :             break;
   10239 CBC        1715 :         case DO_FUNC:
   10240 GIC        1715 :             dumpFunc(fout, (const FuncInfo *) dobj);
   10241            1715 :             break;
   10242             292 :         case DO_AGG:
   10243             292 :             dumpAgg(fout, (const AggInfo *) dobj);
   10244             292 :             break;
   10245             108 :         case DO_OPERATOR:
   10246             108 :             dumpOpr(fout, (const OprInfo *) dobj);
   10247             108 :             break;
   10248 CBC          82 :         case DO_ACCESS_METHOD:
   10249 GIC          82 :             dumpAccessMethod(fout, (const AccessMethodInfo *) dobj);
   10250              82 :             break;
   10251 CBC         132 :         case DO_OPCLASS:
   10252 GIC         132 :             dumpOpclass(fout, (const OpclassInfo *) dobj);
   10253             132 :             break;
   10254             113 :         case DO_OPFAMILY:
   10255             113 :             dumpOpfamily(fout, (const OpfamilyInfo *) dobj);
   10256             113 :             break;
   10257              81 :         case DO_COLLATION:
   10258 CBC          81 :             dumpCollation(fout, (const CollInfo *) dobj);
   10259 GBC          81 :             break;
   10260 GIC          39 :         case DO_CONVERSION:
   10261              39 :             dumpConversion(fout, (const ConvInfo *) dobj);
   10262 CBC          39 :             break;
   10263 GBC       20378 :         case DO_TABLE:
   10264 GIC       20378 :             dumpTable(fout, (const TableInfo *) dobj);
   10265           20378 :             break;
   10266 CBC        1166 :         case DO_TABLE_ATTACH:
   10267            1166 :             dumpTableAttach(fout, (const TableAttachInfo *) dobj);
   10268 GIC        1166 :             break;
   10269             793 :         case DO_ATTRDEF:
   10270             793 :             dumpAttrDef(fout, (const AttrDefInfo *) dobj);
   10271 CBC         793 :             break;
   10272 GBC        1842 :         case DO_INDEX:
   10273 GIC        1842 :             dumpIndex(fout, (const IndxInfo *) dobj);
   10274 CBC        1842 :             break;
   10275             567 :         case DO_INDEX_ATTACH:
   10276 GIC         567 :             dumpIndexAttach(fout, (const IndexAttachInfo *) dobj);
   10277 CBC         567 :             break;
   10278 GIC         137 :         case DO_STATSEXT:
   10279 CBC         137 :             dumpStatisticsExt(fout, (const StatsExtInfo *) dobj);
   10280             137 :             break;
   10281 GIC         328 :         case DO_REFRESH_MATVIEW:
   10282 CBC         328 :             refreshMatViewData(fout, (const TableDataInfo *) dobj);
   10283 GIC         328 :             break;
   10284 CBC         821 :         case DO_RULE:
   10285             821 :             dumpRule(fout, (const RuleInfo *) dobj);
   10286             821 :             break;
   10287 GIC         504 :         case DO_TRIGGER:
   10288 CBC         504 :             dumpTrigger(fout, (const TriggerInfo *) dobj);
   10289             504 :             break;
   10290              38 :         case DO_EVENT_TRIGGER:
   10291              38 :             dumpEventTrigger(fout, (const EventTriggerInfo *) dobj);
   10292              38 :             break;
   10293 GIC        1526 :         case DO_CONSTRAINT:
   10294 CBC        1526 :             dumpConstraint(fout, (const ConstraintInfo *) dobj);
   10295            1526 :             break;
   10296 GIC         158 :         case DO_FK_CONSTRAINT:
   10297             158 :             dumpConstraint(fout, (const ConstraintInfo *) dobj);
   10298             158 :             break;
   10299              83 :         case DO_PROCLANG:
   10300              83 :             dumpProcLang(fout, (const ProcLangInfo *) dobj);
   10301              83 :             break;
   10302              68 :         case DO_CAST:
   10303              68 :             dumpCast(fout, (const CastInfo *) dobj);
   10304 CBC          68 :             break;
   10305 GIC          43 :         case DO_TRANSFORM:
   10306 CBC          43 :             dumpTransform(fout, (const TransformInfo *) dobj);
   10307              43 :             break;
   10308             338 :         case DO_SEQUENCE_SET:
   10309             338 :             dumpSequenceData(fout, (const TableDataInfo *) dobj);
   10310 GIC         338 :             break;
   10311 CBC        3095 :         case DO_TABLE_DATA:
   10312            3095 :             dumpTableData(fout, (const TableDataInfo *) dobj);
   10313            3095 :             break;
   10314           10382 :         case DO_DUMMY_TYPE:
   10315 ECB             :             /* table rowtypes and array types are never dumped separately */
   10316 CBC       10382 :             break;
   10317              39 :         case DO_TSPARSER:
   10318 GIC          39 :             dumpTSParser(fout, (const TSParserInfo *) dobj);
   10319 CBC          39 :             break;
   10320              84 :         case DO_TSDICT:
   10321 GIC          84 :             dumpTSDictionary(fout, (const TSDictInfo *) dobj);
   10322              84 :             break;
   10323              39 :         case DO_TSTEMPLATE:
   10324              39 :             dumpTSTemplate(fout, (const TSTemplateInfo *) dobj);
   10325              39 :             break;
   10326              59 :         case DO_TSCONFIG:
   10327              59 :             dumpTSConfig(fout, (const TSConfigInfo *) dobj);
   10328              59 :             break;
   10329              45 :         case DO_FDW:
   10330 CBC          45 :             dumpForeignDataWrapper(fout, (const FdwInfo *) dobj);
   10331              45 :             break;
   10332 GIC          49 :         case DO_FOREIGN_SERVER:
   10333              49 :             dumpForeignServer(fout, (const ForeignServerInfo *) dobj);
   10334 CBC          49 :             break;
   10335             154 :         case DO_DEFAULT_ACL:
   10336 GIC         154 :             dumpDefaultACL(fout, (const DefaultACLInfo *) dobj);
   10337             154 :             break;
   10338 GNC          89 :         case DO_LARGE_OBJECT:
   10339              89 :             dumpLO(fout, (const LoInfo *) dobj);
   10340 GIC          89 :             break;
   10341 GNC          42 :         case DO_LARGE_OBJECT_DATA:
   10342 GIC          42 :             if (dobj->dump & DUMP_COMPONENT_DATA)
   10343                 :             {
   10344                 :                 TocEntry   *te;
   10345                 : 
   10346 CBC          42 :                 te = ArchiveEntry(fout, dobj->catId, dobj->dumpId,
   10347 GIC          42 :                                   ARCHIVE_OPTS(.tag = dobj->name,
   10348 ECB             :                                                .description = "BLOBS",
   10349                 :                                                .section = SECTION_DATA,
   10350                 :                                                .dumpFn = dumpLOs));
   10351                 : 
   10352                 :                 /*
   10353                 :                  * Set the TocEntry's dataLength in case we are doing a
   10354                 :                  * parallel dump and want to order dump jobs by table size.
   10355                 :                  * (We need some size estimate for every TocEntry with a
   10356                 :                  * DataDumper function.)  We don't currently have any cheap
   10357                 :                  * way to estimate the size of LOs, but it doesn't matter;
   10358                 :                  * let's just set the size to a large value so parallel dumps
   10359                 :                  * will launch this job first.  If there's lots of LOs, we
   10360                 :                  * win, and if there aren't, we don't lose much.  (If you want
   10361                 :                  * to improve on this, really what you should be thinking
   10362                 :                  * about is allowing LO dumping to be parallelized, not just
   10363                 :                  * getting a smarter estimate for the single TOC entry.)
   10364                 :                  */
   10365 CBC          42 :                 te->dataLength = INT_MAX;
   10366 ECB             :             }
   10367 CBC          42 :             break;
   10368             340 :         case DO_POLICY:
   10369             340 :             dumpPolicy(fout, (const PolicyInfo *) dobj);
   10370 GIC         340 :             break;
   10371 CBC         152 :         case DO_PUBLICATION:
   10372 GIC         152 :             dumpPublication(fout, (const PublicationInfo *) dobj);
   10373             152 :             break;
   10374 CBC         256 :         case DO_PUBLICATION_REL:
   10375 GIC         256 :             dumpPublicationTable(fout, (const PublicationRelInfo *) dobj);
   10376 CBC         256 :             break;
   10377              75 :         case DO_PUBLICATION_TABLE_IN_SCHEMA:
   10378 GIC          75 :             dumpPublicationNamespace(fout,
   10379                 :                                      (const PublicationSchemaInfo *) dobj);
   10380              75 :             break;
   10381             114 :         case DO_SUBSCRIPTION:
   10382             114 :             dumpSubscription(fout, (const SubscriptionInfo *) dobj);
   10383             114 :             break;
   10384             236 :         case DO_PRE_DATA_BOUNDARY:
   10385 ECB             :         case DO_POST_DATA_BOUNDARY:
   10386                 :             /* never dumped, nothing to do */
   10387 GIC         236 :             break;
   10388 ECB             :     }
   10389                 : }
   10390                 : 
   10391 EUB             : /*
   10392                 :  * dumpNamespace
   10393                 :  *    writes out to fout the queries to recreate a user-defined namespace
   10394                 :  */
   10395 ECB             : static void
   10396 GIC         339 : dumpNamespace(Archive *fout, const NamespaceInfo *nspinfo)
   10397 ECB             : {
   10398 CBC         339 :     DumpOptions *dopt = fout->dopt;
   10399                 :     PQExpBuffer q;
   10400 ECB             :     PQExpBuffer delq;
   10401                 :     char       *qnspname;
   10402                 : 
   10403                 :     /* Do nothing in data-only dump */
   10404 CBC         339 :     if (dopt->dataOnly)
   10405 GIC          16 :         return;
   10406                 : 
   10407 CBC         323 :     q = createPQExpBuffer();
   10408 GIC         323 :     delq = createPQExpBuffer();
   10409                 : 
   10410             323 :     qnspname = pg_strdup(fmtId(nspinfo->dobj.name));
   10411                 : 
   10412             323 :     if (nspinfo->create)
   10413                 :     {
   10414             224 :         appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
   10415             224 :         appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname);
   10416                 :     }
   10417                 :     else
   10418                 :     {
   10419                 :         /* see selectDumpableNamespace() */
   10420              99 :         appendPQExpBufferStr(delq,
   10421                 :                              "-- *not* dropping schema, since initdb creates it\n");
   10422              99 :         appendPQExpBufferStr(q,
   10423 ECB             :                              "-- *not* creating schema, since initdb creates it\n");
   10424                 :     }
   10425                 : 
   10426 GIC         323 :     if (dopt->binary_upgrade)
   10427              28 :         binary_upgrade_extension_member(q, &nspinfo->dobj,
   10428                 :                                         "SCHEMA", qnspname, NULL);
   10429                 : 
   10430             323 :     if (nspinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   10431             160 :         ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
   10432             160 :                      ARCHIVE_OPTS(.tag = nspinfo->dobj.name,
   10433                 :                                   .owner = nspinfo->rolname,
   10434                 :                                   .description = "SCHEMA",
   10435 ECB             :                                   .section = SECTION_PRE_DATA,
   10436                 :                                   .createStmt = q->data,
   10437                 :                                   .dropStmt = delq->data));
   10438                 : 
   10439                 :     /* Dump Schema Comments and Security Labels */
   10440 GIC         323 :     if (nspinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   10441 ECB             :     {
   10442 GIC         101 :         const char *initdb_comment = NULL;
   10443                 : 
   10444             101 :         if (!nspinfo->create && strcmp(qnspname, "public") == 0)
   10445 CBC          93 :             initdb_comment = "standard public schema";
   10446             101 :         dumpCommentExtended(fout, "SCHEMA", qnspname,
   10447             101 :                             NULL, nspinfo->rolname,
   10448             101 :                             nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId,
   10449                 :                             initdb_comment);
   10450 ECB             :     }
   10451                 : 
   10452 CBC         323 :     if (nspinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
   10453 LBC           0 :         dumpSecLabel(fout, "SCHEMA", qnspname,
   10454               0 :                      NULL, nspinfo->rolname,
   10455 UIC           0 :                      nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
   10456 ECB             : 
   10457 GIC         323 :     if (nspinfo->dobj.dump & DUMP_COMPONENT_ACL)
   10458             241 :         dumpACL(fout, nspinfo->dobj.dumpId, InvalidDumpId, "SCHEMA",
   10459                 :                 qnspname, NULL, NULL,
   10460             241 :                 nspinfo->rolname, &nspinfo->dacl);
   10461 ECB             : 
   10462 CBC         323 :     free(qnspname);
   10463 ECB             : 
   10464 GIC         323 :     destroyPQExpBuffer(q);
   10465             323 :     destroyPQExpBuffer(delq);
   10466 ECB             : }
   10467                 : 
   10468                 : /*
   10469                 :  * dumpExtension
   10470                 :  *    writes out to fout the queries to recreate an extension
   10471                 :  */
   10472                 : static void
   10473 GIC          18 : dumpExtension(Archive *fout, const ExtensionInfo *extinfo)
   10474                 : {
   10475              18 :     DumpOptions *dopt = fout->dopt;
   10476                 :     PQExpBuffer q;
   10477                 :     PQExpBuffer delq;
   10478 ECB             :     char       *qextname;
   10479                 : 
   10480                 :     /* Do nothing in data-only dump */
   10481 GIC          18 :     if (dopt->dataOnly)
   10482               1 :         return;
   10483 ECB             : 
   10484 CBC          17 :     q = createPQExpBuffer();
   10485              17 :     delq = createPQExpBuffer();
   10486                 : 
   10487 GIC          17 :     qextname = pg_strdup(fmtId(extinfo->dobj.name));
   10488 ECB             : 
   10489 GIC          17 :     appendPQExpBuffer(delq, "DROP EXTENSION %s;\n", qextname);
   10490 ECB             : 
   10491 CBC          17 :     if (!dopt->binary_upgrade)
   10492 ECB             :     {
   10493                 :         /*
   10494                 :          * In a regular dump, we simply create the extension, intentionally
   10495                 :          * not specifying a version, so that the destination installation's
   10496                 :          * default version is used.
   10497                 :          *
   10498                 :          * Use of IF NOT EXISTS here is unlike our behavior for other object
   10499                 :          * types; but there are various scenarios in which it's convenient to
   10500                 :          * manually create the desired extension before restoring, so we
   10501                 :          * prefer to allow it to exist already.
   10502                 :          */
   10503 GIC          16 :         appendPQExpBuffer(q, "CREATE EXTENSION IF NOT EXISTS %s WITH SCHEMA %s;\n",
   10504              16 :                           qextname, fmtId(extinfo->namespace));
   10505                 :     }
   10506                 :     else
   10507                 :     {
   10508 ECB             :         /*
   10509                 :          * In binary-upgrade mode, it's critical to reproduce the state of the
   10510                 :          * database exactly, so our procedure is to create an empty extension,
   10511                 :          * restore all the contained objects normally, and add them to the
   10512                 :          * extension one by one.  This function performs just the first of
   10513                 :          * those steps.  binary_upgrade_extension_member() takes care of
   10514                 :          * adding member objects as they're created.
   10515                 :          */
   10516                 :         int         i;
   10517                 :         int         n;
   10518                 : 
   10519 CBC           1 :         appendPQExpBufferStr(q, "-- For binary upgrade, create an empty extension and insert objects into it\n");
   10520                 : 
   10521 ECB             :         /*
   10522                 :          * We unconditionally create the extension, so we must drop it if it
   10523                 :          * exists.  This could happen if the user deleted 'plpgsql' and then
   10524                 :          * readded it, causing its oid to be greater than g_last_builtin_oid.
   10525                 :          */
   10526 CBC           1 :         appendPQExpBuffer(q, "DROP EXTENSION IF EXISTS %s;\n", qextname);
   10527 ECB             : 
   10528 CBC           1 :         appendPQExpBufferStr(q,
   10529 ECB             :                              "SELECT pg_catalog.binary_upgrade_create_empty_extension(");
   10530 CBC           1 :         appendStringLiteralAH(q, extinfo->dobj.name, fout);
   10531               1 :         appendPQExpBufferStr(q, ", ");
   10532               1 :         appendStringLiteralAH(q, extinfo->namespace, fout);
   10533               1 :         appendPQExpBufferStr(q, ", ");
   10534               1 :         appendPQExpBuffer(q, "%s, ", extinfo->relocatable ? "true" : "false");
   10535               1 :         appendStringLiteralAH(q, extinfo->extversion, fout);
   10536               1 :         appendPQExpBufferStr(q, ", ");
   10537 ECB             : 
   10538                 :         /*
   10539                 :          * Note that we're pushing extconfig (an OID array) back into
   10540                 :          * pg_extension exactly as-is.  This is OK because pg_class OIDs are
   10541                 :          * preserved in binary upgrade.
   10542                 :          */
   10543 CBC           1 :         if (strlen(extinfo->extconfig) > 2)
   10544               1 :             appendStringLiteralAH(q, extinfo->extconfig, fout);
   10545 ECB             :         else
   10546 LBC           0 :             appendPQExpBufferStr(q, "NULL");
   10547 CBC           1 :         appendPQExpBufferStr(q, ", ");
   10548               1 :         if (strlen(extinfo->extcondition) > 2)
   10549               1 :             appendStringLiteralAH(q, extinfo->extcondition, fout);
   10550 ECB             :         else
   10551 LBC           0 :             appendPQExpBufferStr(q, "NULL");
   10552 CBC           1 :         appendPQExpBufferStr(q, ", ");
   10553               1 :         appendPQExpBufferStr(q, "ARRAY[");
   10554               1 :         n = 0;
   10555               2 :         for (i = 0; i < extinfo->dobj.nDeps; i++)
   10556 ECB             :         {
   10557                 :             DumpableObject *extobj;
   10558                 : 
   10559 CBC           1 :             extobj = findObjectByDumpId(extinfo->dobj.dependencies[i]);
   10560               1 :             if (extobj && extobj->objType == DO_EXTENSION)
   10561 ECB             :             {
   10562 LBC           0 :                 if (n++ > 0)
   10563               0 :                     appendPQExpBufferChar(q, ',');
   10564               0 :                 appendStringLiteralAH(q, extobj->name, fout);
   10565 ECB             :             }
   10566                 :         }
   10567 CBC           1 :         appendPQExpBufferStr(q, "]::pg_catalog.text[]");
   10568               1 :         appendPQExpBufferStr(q, ");\n");
   10569 ECB             :     }
   10570                 : 
   10571 CBC          17 :     if (extinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   10572              17 :         ArchiveEntry(fout, extinfo->dobj.catId, extinfo->dobj.dumpId,
   10573              17 :                      ARCHIVE_OPTS(.tag = extinfo->dobj.name,
   10574 ECB             :                                   .description = "EXTENSION",
   10575                 :                                   .section = SECTION_PRE_DATA,
   10576                 :                                   .createStmt = q->data,
   10577                 :                                   .dropStmt = delq->data));
   10578                 : 
   10579                 :     /* Dump Extension Comments and Security Labels */
   10580 CBC          17 :     if (extinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   10581              17 :         dumpComment(fout, "EXTENSION", qextname,
   10582 ECB             :                     NULL, "",
   10583 CBC          17 :                     extinfo->dobj.catId, 0, extinfo->dobj.dumpId);
   10584 ECB             : 
   10585 CBC          17 :     if (extinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
   10586 LBC           0 :         dumpSecLabel(fout, "EXTENSION", qextname,
   10587 ECB             :                      NULL, "",
   10588 LBC           0 :                      extinfo->dobj.catId, 0, extinfo->dobj.dumpId);
   10589 ECB             : 
   10590 CBC          17 :     free(qextname);
   10591 ECB             : 
   10592 CBC          17 :     destroyPQExpBuffer(q);
   10593              17 :     destroyPQExpBuffer(delq);
   10594 ECB             : }
   10595                 : 
   10596                 : /*
   10597                 :  * dumpType
   10598                 :  *    writes out to fout the queries to recreate a user-defined type
   10599                 :  */
   10600                 : static void
   10601 CBC         523 : dumpType(Archive *fout, const TypeInfo *tyinfo)
   10602 ECB             : {
   10603 CBC         523 :     DumpOptions *dopt = fout->dopt;
   10604 ECB             : 
   10605                 :     /* Do nothing in data-only dump */
   10606 CBC         523 :     if (dopt->dataOnly)
   10607              22 :         return;
   10608 ECB             : 
   10609                 :     /* Dump out in proper style */
   10610 CBC         501 :     if (tyinfo->typtype == TYPTYPE_BASE)
   10611 GIC          71 :         dumpBaseType(fout, tyinfo);
   10612 CBC         430 :     else if (tyinfo->typtype == TYPTYPE_DOMAIN)
   10613             121 :         dumpDomain(fout, tyinfo);
   10614             309 :     else if (tyinfo->typtype == TYPTYPE_COMPOSITE)
   10615             123 :         dumpCompositeType(fout, tyinfo);
   10616             186 :     else if (tyinfo->typtype == TYPTYPE_ENUM)
   10617              53 :         dumpEnumType(fout, tyinfo);
   10618             133 :     else if (tyinfo->typtype == TYPTYPE_RANGE)
   10619              92 :         dumpRangeType(fout, tyinfo);
   10620              41 :     else if (tyinfo->typtype == TYPTYPE_PSEUDO && !tyinfo->isDefined)
   10621              41 :         dumpUndefinedType(fout, tyinfo);
   10622 ECB             :     else
   10623 LBC           0 :         pg_log_warning("typtype of data type \"%s\" appears to be invalid",
   10624 ECB             :                        tyinfo->dobj.name);
   10625                 : }
   10626                 : 
   10627                 : /*
   10628                 :  * dumpEnumType
   10629                 :  *    writes out to fout the queries to recreate a user-defined enum type
   10630                 :  */
   10631                 : static void
   10632 CBC          53 : dumpEnumType(Archive *fout, const TypeInfo *tyinfo)
   10633 ECB             : {
   10634 CBC          53 :     DumpOptions *dopt = fout->dopt;
   10635              53 :     PQExpBuffer q = createPQExpBuffer();
   10636              53 :     PQExpBuffer delq = createPQExpBuffer();
   10637              53 :     PQExpBuffer query = createPQExpBuffer();
   10638 ECB             :     PGresult   *res;
   10639                 :     int         num,
   10640                 :                 i;
   10641                 :     Oid         enum_oid;
   10642                 :     char       *qtypname;
   10643                 :     char       *qualtypname;
   10644                 :     char       *label;
   10645                 :     int         i_enumlabel;
   10646                 :     int         i_oid;
   10647                 : 
   10648 GIC          53 :     if (!fout->is_prepared[PREPQUERY_DUMPENUMTYPE])
   10649                 :     {
   10650                 :         /* Set up query for enum-specific details */
   10651              43 :         appendPQExpBufferStr(query,
   10652                 :                              "PREPARE dumpEnumType(pg_catalog.oid) AS\n"
   10653                 :                              "SELECT oid, enumlabel "
   10654                 :                              "FROM pg_catalog.pg_enum "
   10655                 :                              "WHERE enumtypid = $1 "
   10656                 :                              "ORDER BY enumsortorder");
   10657                 : 
   10658              43 :         ExecuteSqlStatement(fout, query->data);
   10659                 : 
   10660              43 :         fout->is_prepared[PREPQUERY_DUMPENUMTYPE] = true;
   10661 ECB             :     }
   10662                 : 
   10663 CBC          53 :     printfPQExpBuffer(query,
   10664 ECB             :                       "EXECUTE dumpEnumType('%u')",
   10665 CBC          53 :                       tyinfo->dobj.catId.oid);
   10666 ECB             : 
   10667 CBC          53 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   10668 ECB             : 
   10669 CBC          53 :     num = PQntuples(res);
   10670 ECB             : 
   10671 CBC          53 :     qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
   10672              53 :     qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
   10673 ECB             : 
   10674                 :     /*
   10675                 :      * CASCADE shouldn't be required here as for normal types since the I/O
   10676                 :      * functions are generic and do not get dropped.
   10677                 :      */
   10678 CBC          53 :     appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname);
   10679 ECB             : 
   10680 CBC          53 :     if (dopt->binary_upgrade)
   10681 GIC           4 :         binary_upgrade_set_type_oids_by_type_oid(fout, q,
   10682               4 :                                                  tyinfo->dobj.catId.oid,
   10683 ECB             :                                                  false, false);
   10684                 : 
   10685 GIC          53 :     appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (",
   10686                 :                       qualtypname);
   10687                 : 
   10688              53 :     if (!dopt->binary_upgrade)
   10689                 :     {
   10690              49 :         i_enumlabel = PQfnumber(res, "enumlabel");
   10691                 : 
   10692 ECB             :         /* Labels with server-assigned oids */
   10693 GIC         350 :         for (i = 0; i < num; i++)
   10694 ECB             :         {
   10695 GIC         301 :             label = PQgetvalue(res, i, i_enumlabel);
   10696             301 :             if (i > 0)
   10697             252 :                 appendPQExpBufferChar(q, ',');
   10698             301 :             appendPQExpBufferStr(q, "\n    ");
   10699             301 :             appendStringLiteralAH(q, label, fout);
   10700 ECB             :         }
   10701                 :     }
   10702                 : 
   10703 CBC          53 :     appendPQExpBufferStr(q, "\n);\n");
   10704 ECB             : 
   10705 GIC          53 :     if (dopt->binary_upgrade)
   10706 ECB             :     {
   10707 GIC           4 :         i_oid = PQfnumber(res, "oid");
   10708 CBC           4 :         i_enumlabel = PQfnumber(res, "enumlabel");
   10709                 : 
   10710 ECB             :         /* Labels with dump-assigned (preserved) oids */
   10711 CBC          51 :         for (i = 0; i < num; i++)
   10712                 :         {
   10713 GIC          47 :             enum_oid = atooid(PQgetvalue(res, i, i_oid));
   10714              47 :             label = PQgetvalue(res, i, i_enumlabel);
   10715                 : 
   10716 CBC          47 :             if (i == 0)
   10717 GIC           4 :                 appendPQExpBufferStr(q, "\n-- For binary upgrade, must preserve pg_enum oids\n");
   10718 CBC          47 :             appendPQExpBuffer(q,
   10719                 :                               "SELECT pg_catalog.binary_upgrade_set_next_pg_enum_oid('%u'::pg_catalog.oid);\n",
   10720                 :                               enum_oid);
   10721 GIC          47 :             appendPQExpBuffer(q, "ALTER TYPE %s ADD VALUE ", qualtypname);
   10722 CBC          47 :             appendStringLiteralAH(q, label, fout);
   10723              47 :             appendPQExpBufferStr(q, ";\n\n");
   10724                 :         }
   10725                 :     }
   10726 ECB             : 
   10727 CBC          53 :     if (dopt->binary_upgrade)
   10728               4 :         binary_upgrade_extension_member(q, &tyinfo->dobj,
   10729                 :                                         "TYPE", qtypname,
   10730 GIC           4 :                                         tyinfo->dobj.namespace->dobj.name);
   10731                 : 
   10732              53 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   10733              53 :         ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
   10734              53 :                      ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
   10735                 :                                   .namespace = tyinfo->dobj.namespace->dobj.name,
   10736 ECB             :                                   .owner = tyinfo->rolname,
   10737                 :                                   .description = "TYPE",
   10738                 :                                   .section = SECTION_PRE_DATA,
   10739                 :                                   .createStmt = q->data,
   10740                 :                                   .dropStmt = delq->data));
   10741                 : 
   10742                 :     /* Dump Type Comments and Security Labels */
   10743 CBC          53 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   10744              36 :         dumpComment(fout, "TYPE", qtypname,
   10745 GIC          36 :                     tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
   10746              36 :                     tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
   10747                 : 
   10748 CBC          53 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
   10749 UBC           0 :         dumpSecLabel(fout, "TYPE", qtypname,
   10750               0 :                      tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
   10751               0 :                      tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
   10752                 : 
   10753 CBC          53 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
   10754              36 :         dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
   10755                 :                 qtypname, NULL,
   10756              36 :                 tyinfo->dobj.namespace->dobj.name,
   10757 GIC          36 :                 tyinfo->rolname, &tyinfo->dacl);
   10758 ECB             : 
   10759 GIC          53 :     PQclear(res);
   10760 CBC          53 :     destroyPQExpBuffer(q);
   10761              53 :     destroyPQExpBuffer(delq);
   10762 GIC          53 :     destroyPQExpBuffer(query);
   10763              53 :     free(qtypname);
   10764              53 :     free(qualtypname);
   10765              53 : }
   10766                 : 
   10767                 : /*
   10768                 :  * dumpRangeType
   10769 ECB             :  *    writes out to fout the queries to recreate a user-defined range type
   10770                 :  */
   10771                 : static void
   10772 GIC          92 : dumpRangeType(Archive *fout, const TypeInfo *tyinfo)
   10773                 : {
   10774              92 :     DumpOptions *dopt = fout->dopt;
   10775              92 :     PQExpBuffer q = createPQExpBuffer();
   10776              92 :     PQExpBuffer delq = createPQExpBuffer();
   10777 CBC          92 :     PQExpBuffer query = createPQExpBuffer();
   10778 ECB             :     PGresult   *res;
   10779                 :     Oid         collationOid;
   10780                 :     char       *qtypname;
   10781                 :     char       *qualtypname;
   10782                 :     char       *procname;
   10783                 : 
   10784 GIC          92 :     if (!fout->is_prepared[PREPQUERY_DUMPRANGETYPE])
   10785 ECB             :     {
   10786                 :         /* Set up query for range-specific details */
   10787 CBC          41 :         appendPQExpBufferStr(query,
   10788                 :                              "PREPARE dumpRangeType(pg_catalog.oid) AS\n");
   10789                 : 
   10790 GIC          41 :         appendPQExpBufferStr(query,
   10791                 :                              "SELECT ");
   10792                 : 
   10793              41 :         if (fout->remoteVersion >= 140000)
   10794              41 :             appendPQExpBufferStr(query,
   10795                 :                                  "pg_catalog.format_type(rngmultitypid, NULL) AS rngmultitype, ");
   10796                 :         else
   10797 UIC           0 :             appendPQExpBufferStr(query,
   10798                 :                                  "NULL AS rngmultitype, ");
   10799 ECB             : 
   10800 CBC          41 :         appendPQExpBufferStr(query,
   10801                 :                              "pg_catalog.format_type(rngsubtype, NULL) AS rngsubtype, "
   10802                 :                              "opc.opcname AS opcname, "
   10803                 :                              "(SELECT nspname FROM pg_catalog.pg_namespace nsp "
   10804                 :                              "  WHERE nsp.oid = opc.opcnamespace) AS opcnsp, "
   10805                 :                              "opc.opcdefault, "
   10806                 :                              "CASE WHEN rngcollation = st.typcollation THEN 0 "
   10807                 :                              "     ELSE rngcollation END AS collation, "
   10808                 :                              "rngcanonical, rngsubdiff "
   10809                 :                              "FROM pg_catalog.pg_range r, pg_catalog.pg_type st, "
   10810                 :                              "     pg_catalog.pg_opclass opc "
   10811                 :                              "WHERE st.oid = rngsubtype AND opc.oid = rngsubopc AND "
   10812                 :                              "rngtypid = $1");
   10813                 : 
   10814 GIC          41 :         ExecuteSqlStatement(fout, query->data);
   10815 ECB             : 
   10816 GIC          41 :         fout->is_prepared[PREPQUERY_DUMPRANGETYPE] = true;
   10817                 :     }
   10818                 : 
   10819              92 :     printfPQExpBuffer(query,
   10820                 :                       "EXECUTE dumpRangeType('%u')",
   10821              92 :                       tyinfo->dobj.catId.oid);
   10822 ECB             : 
   10823 GIC          92 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   10824 ECB             : 
   10825 GIC          92 :     qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
   10826 CBC          92 :     qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
   10827 ECB             : 
   10828                 :     /*
   10829                 :      * CASCADE shouldn't be required here as for normal types since the I/O
   10830                 :      * functions are generic and do not get dropped.
   10831                 :      */
   10832 CBC          92 :     appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname);
   10833                 : 
   10834 GIC          92 :     if (dopt->binary_upgrade)
   10835               6 :         binary_upgrade_set_type_oids_by_type_oid(fout, q,
   10836               6 :                                                  tyinfo->dobj.catId.oid,
   10837                 :                                                  false, true);
   10838                 : 
   10839 CBC          92 :     appendPQExpBuffer(q, "CREATE TYPE %s AS RANGE (",
   10840 ECB             :                       qualtypname);
   10841                 : 
   10842 GBC          92 :     appendPQExpBuffer(q, "\n    subtype = %s",
   10843 ECB             :                       PQgetvalue(res, 0, PQfnumber(res, "rngsubtype")));
   10844                 : 
   10845 CBC          92 :     if (!PQgetisnull(res, 0, PQfnumber(res, "rngmultitype")))
   10846 GIC          92 :         appendPQExpBuffer(q, ",\n    multirange_type_name = %s",
   10847 EUB             :                           PQgetvalue(res, 0, PQfnumber(res, "rngmultitype")));
   10848 ECB             : 
   10849                 :     /* print subtype_opclass only if not default for subtype */
   10850 CBC          92 :     if (PQgetvalue(res, 0, PQfnumber(res, "opcdefault"))[0] != 't')
   10851 ECB             :     {
   10852 GIC          36 :         char       *opcname = PQgetvalue(res, 0, PQfnumber(res, "opcname"));
   10853              36 :         char       *nspname = PQgetvalue(res, 0, PQfnumber(res, "opcnsp"));
   10854                 : 
   10855 CBC          36 :         appendPQExpBuffer(q, ",\n    subtype_opclass = %s.",
   10856 ECB             :                           fmtId(nspname));
   10857 GIC          36 :         appendPQExpBufferStr(q, fmtId(opcname));
   10858 EUB             :     }
   10859                 : 
   10860 GBC          92 :     collationOid = atooid(PQgetvalue(res, 0, PQfnumber(res, "collation")));
   10861 GIC          92 :     if (OidIsValid(collationOid))
   10862                 :     {
   10863 CBC          41 :         CollInfo   *coll = findCollationByOid(collationOid);
   10864 ECB             : 
   10865 GIC          41 :         if (coll)
   10866              41 :             appendPQExpBuffer(q, ",\n    collation = %s",
   10867 CBC          41 :                               fmtQualifiedDumpable(coll));
   10868 ECB             :     }
   10869                 : 
   10870 GIC          92 :     procname = PQgetvalue(res, 0, PQfnumber(res, "rngcanonical"));
   10871              92 :     if (strcmp(procname, "-") != 0)
   10872 UIC           0 :         appendPQExpBuffer(q, ",\n    canonical = %s", procname);
   10873                 : 
   10874 GIC          92 :     procname = PQgetvalue(res, 0, PQfnumber(res, "rngsubdiff"));
   10875              92 :     if (strcmp(procname, "-") != 0)
   10876 CBC           5 :         appendPQExpBuffer(q, ",\n    subtype_diff = %s", procname);
   10877 ECB             : 
   10878 GIC          92 :     appendPQExpBufferStr(q, "\n);\n");
   10879 ECB             : 
   10880 GIC          92 :     if (dopt->binary_upgrade)
   10881 CBC           6 :         binary_upgrade_extension_member(q, &tyinfo->dobj,
   10882 EUB             :                                         "TYPE", qtypname,
   10883 GIC           6 :                                         tyinfo->dobj.namespace->dobj.name);
   10884 EUB             : 
   10885 GIC          92 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   10886 CBC          92 :         ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
   10887 GIC          92 :                      ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
   10888 ECB             :                                   .namespace = tyinfo->dobj.namespace->dobj.name,
   10889                 :                                   .owner = tyinfo->rolname,
   10890                 :                                   .description = "TYPE",
   10891                 :                                   .section = SECTION_PRE_DATA,
   10892                 :                                   .createStmt = q->data,
   10893                 :                                   .dropStmt = delq->data));
   10894                 : 
   10895                 :     /* Dump Type Comments and Security Labels */
   10896 GIC          92 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   10897 CBC          36 :         dumpComment(fout, "TYPE", qtypname,
   10898 GIC          36 :                     tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
   10899 CBC          36 :                     tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
   10900                 : 
   10901 GIC          92 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
   10902 LBC           0 :         dumpSecLabel(fout, "TYPE", qtypname,
   10903               0 :                      tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
   10904 UIC           0 :                      tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
   10905                 : 
   10906 CBC          92 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
   10907              36 :         dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
   10908 ECB             :                 qtypname, NULL,
   10909 CBC          36 :                 tyinfo->dobj.namespace->dobj.name,
   10910              36 :                 tyinfo->rolname, &tyinfo->dacl);
   10911 ECB             : 
   10912 CBC          92 :     PQclear(res);
   10913              92 :     destroyPQExpBuffer(q);
   10914              92 :     destroyPQExpBuffer(delq);
   10915              92 :     destroyPQExpBuffer(query);
   10916              92 :     free(qtypname);
   10917              92 :     free(qualtypname);
   10918 GIC          92 : }
   10919 EUB             : 
   10920                 : /*
   10921                 :  * dumpUndefinedType
   10922                 :  *    writes out to fout the queries to recreate a !typisdefined type
   10923                 :  *
   10924                 :  * This is a shell type, but we use different terminology to distinguish
   10925                 :  * this case from where we have to emit a shell type definition to break
   10926                 :  * circular dependencies.  An undefined type shouldn't ever have anything
   10927                 :  * depending on it.
   10928 ECB             :  */
   10929                 : static void
   10930 CBC          41 : dumpUndefinedType(Archive *fout, const TypeInfo *tyinfo)
   10931 ECB             : {
   10932 CBC          41 :     DumpOptions *dopt = fout->dopt;
   10933              41 :     PQExpBuffer q = createPQExpBuffer();
   10934 GIC          41 :     PQExpBuffer delq = createPQExpBuffer();
   10935                 :     char       *qtypname;
   10936                 :     char       *qualtypname;
   10937                 : 
   10938              41 :     qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
   10939              41 :     qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
   10940                 : 
   10941              41 :     appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname);
   10942                 : 
   10943              41 :     if (dopt->binary_upgrade)
   10944 CBC           2 :         binary_upgrade_set_type_oids_by_type_oid(fout, q,
   10945 GIC           2 :                                                  tyinfo->dobj.catId.oid,
   10946                 :                                                  false, false);
   10947 ECB             : 
   10948 GIC          41 :     appendPQExpBuffer(q, "CREATE TYPE %s;\n",
   10949                 :                       qualtypname);
   10950                 : 
   10951              41 :     if (dopt->binary_upgrade)
   10952               2 :         binary_upgrade_extension_member(q, &tyinfo->dobj,
   10953                 :                                         "TYPE", qtypname,
   10954 CBC           2 :                                         tyinfo->dobj.namespace->dobj.name);
   10955                 : 
   10956              41 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   10957 GIC          41 :         ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
   10958              41 :                      ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
   10959 ECB             :                                   .namespace = tyinfo->dobj.namespace->dobj.name,
   10960                 :                                   .owner = tyinfo->rolname,
   10961                 :                                   .description = "TYPE",
   10962                 :                                   .section = SECTION_PRE_DATA,
   10963                 :                                   .createStmt = q->data,
   10964                 :                                   .dropStmt = delq->data));
   10965                 : 
   10966                 :     /* Dump Type Comments and Security Labels */
   10967 CBC          41 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   10968              36 :         dumpComment(fout, "TYPE", qtypname,
   10969 GIC          36 :                     tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
   10970              36 :                     tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
   10971                 : 
   10972              41 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
   10973 UIC           0 :         dumpSecLabel(fout, "TYPE", qtypname,
   10974 LBC           0 :                      tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
   10975 UIC           0 :                      tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
   10976 ECB             : 
   10977 CBC          41 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
   10978 LBC           0 :         dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
   10979                 :                 qtypname, NULL,
   10980 UIC           0 :                 tyinfo->dobj.namespace->dobj.name,
   10981 LBC           0 :                 tyinfo->rolname, &tyinfo->dacl);
   10982                 : 
   10983 GIC          41 :     destroyPQExpBuffer(q);
   10984 CBC          41 :     destroyPQExpBuffer(delq);
   10985 GIC          41 :     free(qtypname);
   10986 CBC          41 :     free(qualtypname);
   10987 GIC          41 : }
   10988                 : 
   10989 ECB             : /*
   10990                 :  * dumpBaseType
   10991                 :  *    writes out to fout the queries to recreate a user-defined base type
   10992                 :  */
   10993                 : static void
   10994 CBC          71 : dumpBaseType(Archive *fout, const TypeInfo *tyinfo)
   10995 ECB             : {
   10996 GIC          71 :     DumpOptions *dopt = fout->dopt;
   10997              71 :     PQExpBuffer q = createPQExpBuffer();
   10998              71 :     PQExpBuffer delq = createPQExpBuffer();
   10999 CBC          71 :     PQExpBuffer query = createPQExpBuffer();
   11000                 :     PGresult   *res;
   11001 ECB             :     char       *qtypname;
   11002                 :     char       *qualtypname;
   11003                 :     char       *typlen;
   11004                 :     char       *typinput;
   11005                 :     char       *typoutput;
   11006                 :     char       *typreceive;
   11007                 :     char       *typsend;
   11008                 :     char       *typmodin;
   11009                 :     char       *typmodout;
   11010                 :     char       *typanalyze;
   11011                 :     char       *typsubscript;
   11012                 :     Oid         typreceiveoid;
   11013                 :     Oid         typsendoid;
   11014                 :     Oid         typmodinoid;
   11015                 :     Oid         typmodoutoid;
   11016                 :     Oid         typanalyzeoid;
   11017                 :     Oid         typsubscriptoid;
   11018                 :     char       *typcategory;
   11019                 :     char       *typispreferred;
   11020                 :     char       *typdelim;
   11021                 :     char       *typbyval;
   11022                 :     char       *typalign;
   11023                 :     char       *typstorage;
   11024                 :     char       *typcollatable;
   11025                 :     char       *typdefault;
   11026 CBC          71 :     bool        typdefault_is_literal = false;
   11027                 : 
   11028              71 :     if (!fout->is_prepared[PREPQUERY_DUMPBASETYPE])
   11029 ECB             :     {
   11030                 :         /* Set up query for type-specific details */
   11031 GIC          41 :         appendPQExpBufferStr(query,
   11032                 :                              "PREPARE dumpBaseType(pg_catalog.oid) AS\n"
   11033                 :                              "SELECT typlen, "
   11034                 :                              "typinput, typoutput, typreceive, typsend, "
   11035                 :                              "typreceive::pg_catalog.oid AS typreceiveoid, "
   11036                 :                              "typsend::pg_catalog.oid AS typsendoid, "
   11037                 :                              "typanalyze, "
   11038                 :                              "typanalyze::pg_catalog.oid AS typanalyzeoid, "
   11039 ECB             :                              "typdelim, typbyval, typalign, typstorage, "
   11040                 :                              "typmodin, typmodout, "
   11041                 :                              "typmodin::pg_catalog.oid AS typmodinoid, "
   11042                 :                              "typmodout::pg_catalog.oid AS typmodoutoid, "
   11043                 :                              "typcategory, typispreferred, "
   11044                 :                              "(typcollation <> 0) AS typcollatable, "
   11045 EUB             :                              "pg_catalog.pg_get_expr(typdefaultbin, 0) AS typdefaultbin, typdefault, ");
   11046                 : 
   11047 GBC          41 :         if (fout->remoteVersion >= 140000)
   11048 GIC          41 :             appendPQExpBufferStr(query,
   11049 ECB             :                                  "typsubscript, "
   11050                 :                                  "typsubscript::pg_catalog.oid AS typsubscriptoid ");
   11051                 :         else
   11052 LBC           0 :             appendPQExpBufferStr(query,
   11053 ECB             :                                  "'-' AS typsubscript, 0 AS typsubscriptoid ");
   11054                 : 
   11055 CBC          41 :         appendPQExpBufferStr(query, "FROM pg_catalog.pg_type "
   11056 ECB             :                              "WHERE oid = $1");
   11057                 : 
   11058 CBC          41 :         ExecuteSqlStatement(fout, query->data);
   11059 ECB             : 
   11060 CBC          41 :         fout->is_prepared[PREPQUERY_DUMPBASETYPE] = true;
   11061 ECB             :     }
   11062                 : 
   11063 GIC          71 :     printfPQExpBuffer(query,
   11064                 :                       "EXECUTE dumpBaseType('%u')",
   11065              71 :                       tyinfo->dobj.catId.oid);
   11066                 : 
   11067              71 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   11068 ECB             : 
   11069 GIC          71 :     typlen = PQgetvalue(res, 0, PQfnumber(res, "typlen"));
   11070 CBC          71 :     typinput = PQgetvalue(res, 0, PQfnumber(res, "typinput"));
   11071              71 :     typoutput = PQgetvalue(res, 0, PQfnumber(res, "typoutput"));
   11072              71 :     typreceive = PQgetvalue(res, 0, PQfnumber(res, "typreceive"));
   11073              71 :     typsend = PQgetvalue(res, 0, PQfnumber(res, "typsend"));
   11074 GIC          71 :     typmodin = PQgetvalue(res, 0, PQfnumber(res, "typmodin"));
   11075              71 :     typmodout = PQgetvalue(res, 0, PQfnumber(res, "typmodout"));
   11076              71 :     typanalyze = PQgetvalue(res, 0, PQfnumber(res, "typanalyze"));
   11077              71 :     typsubscript = PQgetvalue(res, 0, PQfnumber(res, "typsubscript"));
   11078              71 :     typreceiveoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typreceiveoid")));
   11079              71 :     typsendoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typsendoid")));
   11080 CBC          71 :     typmodinoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typmodinoid")));
   11081 GIC          71 :     typmodoutoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typmodoutoid")));
   11082              71 :     typanalyzeoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typanalyzeoid")));
   11083 CBC          71 :     typsubscriptoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typsubscriptoid")));
   11084 GIC          71 :     typcategory = PQgetvalue(res, 0, PQfnumber(res, "typcategory"));
   11085              71 :     typispreferred = PQgetvalue(res, 0, PQfnumber(res, "typispreferred"));
   11086 CBC          71 :     typdelim = PQgetvalue(res, 0, PQfnumber(res, "typdelim"));
   11087 GIC          71 :     typbyval = PQgetvalue(res, 0, PQfnumber(res, "typbyval"));
   11088              71 :     typalign = PQgetvalue(res, 0, PQfnumber(res, "typalign"));
   11089 CBC          71 :     typstorage = PQgetvalue(res, 0, PQfnumber(res, "typstorage"));
   11090              71 :     typcollatable = PQgetvalue(res, 0, PQfnumber(res, "typcollatable"));
   11091 GIC          71 :     if (!PQgetisnull(res, 0, PQfnumber(res, "typdefaultbin")))
   11092 UIC           0 :         typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefaultbin"));
   11093 GBC          71 :     else if (!PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
   11094                 :     {
   11095 GIC          46 :         typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault"));
   11096 CBC          46 :         typdefault_is_literal = true;   /* it needs quotes */
   11097                 :     }
   11098                 :     else
   11099 GIC          25 :         typdefault = NULL;
   11100                 : 
   11101              71 :     qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
   11102              71 :     qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
   11103                 : 
   11104                 :     /*
   11105                 :      * The reason we include CASCADE is that the circular dependency between
   11106                 :      * the type and its I/O functions makes it impossible to drop the type any
   11107                 :      * other way.
   11108                 :      */
   11109              71 :     appendPQExpBuffer(delq, "DROP TYPE %s CASCADE;\n", qualtypname);
   11110 ECB             : 
   11111                 :     /*
   11112                 :      * We might already have a shell type, but setting pg_type_oid is
   11113                 :      * harmless, and in any case we'd better set the array type OID.
   11114                 :      */
   11115 CBC          71 :     if (dopt->binary_upgrade)
   11116 GIC           8 :         binary_upgrade_set_type_oids_by_type_oid(fout, q,
   11117 CBC           8 :                                                  tyinfo->dobj.catId.oid,
   11118                 :                                                  false, false);
   11119 ECB             : 
   11120 GIC          71 :     appendPQExpBuffer(q,
   11121 ECB             :                       "CREATE TYPE %s (\n"
   11122                 :                       "    INTERNALLENGTH = %s",
   11123                 :                       qualtypname,
   11124 GIC          71 :                       (strcmp(typlen, "-1") == 0) ? "variable" : typlen);
   11125                 : 
   11126                 :     /* regproc result is sufficiently quoted already */
   11127              71 :     appendPQExpBuffer(q, ",\n    INPUT = %s", typinput);
   11128 CBC          71 :     appendPQExpBuffer(q, ",\n    OUTPUT = %s", typoutput);
   11129 GIC          71 :     if (OidIsValid(typreceiveoid))
   11130 LBC           0 :         appendPQExpBuffer(q, ",\n    RECEIVE = %s", typreceive);
   11131 CBC          71 :     if (OidIsValid(typsendoid))
   11132 LBC           0 :         appendPQExpBuffer(q, ",\n    SEND = %s", typsend);
   11133 GIC          71 :     if (OidIsValid(typmodinoid))
   11134               5 :         appendPQExpBuffer(q, ",\n    TYPMOD_IN = %s", typmodin);
   11135 CBC          71 :     if (OidIsValid(typmodoutoid))
   11136 GIC           5 :         appendPQExpBuffer(q, ",\n    TYPMOD_OUT = %s", typmodout);
   11137              71 :     if (OidIsValid(typanalyzeoid))
   11138 LBC           0 :         appendPQExpBuffer(q, ",\n    ANALYZE = %s", typanalyze);
   11139                 : 
   11140 GIC          71 :     if (strcmp(typcollatable, "t") == 0)
   11141 LBC           0 :         appendPQExpBufferStr(q, ",\n    COLLATABLE = true");
   11142 ECB             : 
   11143 GIC          71 :     if (typdefault != NULL)
   11144                 :     {
   11145              46 :         appendPQExpBufferStr(q, ",\n    DEFAULT = ");
   11146 CBC          46 :         if (typdefault_is_literal)
   11147 GIC          46 :             appendStringLiteralAH(q, typdefault, fout);
   11148 ECB             :         else
   11149 LBC           0 :             appendPQExpBufferStr(q, typdefault);
   11150                 :     }
   11151 ECB             : 
   11152 GIC          71 :     if (OidIsValid(typsubscriptoid))
   11153 CBC           5 :         appendPQExpBuffer(q, ",\n    SUBSCRIPT = %s", typsubscript);
   11154                 : 
   11155 GIC          71 :     if (OidIsValid(tyinfo->typelem))
   11156 CBC           5 :         appendPQExpBuffer(q, ",\n    ELEMENT = %s",
   11157               5 :                           getFormattedTypeName(fout, tyinfo->typelem,
   11158                 :                                                zeroIsError));
   11159 ECB             : 
   11160 GIC          71 :     if (strcmp(typcategory, "U") != 0)
   11161 ECB             :     {
   11162 CBC           5 :         appendPQExpBufferStr(q, ",\n    CATEGORY = ");
   11163               5 :         appendStringLiteralAH(q, typcategory, fout);
   11164                 :     }
   11165                 : 
   11166              71 :     if (strcmp(typispreferred, "t") == 0)
   11167               5 :         appendPQExpBufferStr(q, ",\n    PREFERRED = true");
   11168 EUB             : 
   11169 GIC          71 :     if (typdelim && strcmp(typdelim, ",") != 0)
   11170 ECB             :     {
   11171 LBC           0 :         appendPQExpBufferStr(q, ",\n    DELIMITER = ");
   11172               0 :         appendStringLiteralAH(q, typdelim, fout);
   11173                 :     }
   11174 ECB             : 
   11175 GIC          71 :     if (*typalign == TYPALIGN_CHAR)
   11176 LBC           0 :         appendPQExpBufferStr(q, ",\n    ALIGNMENT = char");
   11177 CBC          71 :     else if (*typalign == TYPALIGN_SHORT)
   11178 UIC           0 :         appendPQExpBufferStr(q, ",\n    ALIGNMENT = int2");
   11179 CBC          71 :     else if (*typalign == TYPALIGN_INT)
   11180 GIC          56 :         appendPQExpBufferStr(q, ",\n    ALIGNMENT = int4");
   11181 CBC          15 :     else if (*typalign == TYPALIGN_DOUBLE)
   11182              15 :         appendPQExpBufferStr(q, ",\n    ALIGNMENT = double");
   11183 ECB             : 
   11184 GIC          71 :     if (*typstorage == TYPSTORAGE_PLAIN)
   11185              71 :         appendPQExpBufferStr(q, ",\n    STORAGE = plain");
   11186 UIC           0 :     else if (*typstorage == TYPSTORAGE_EXTERNAL)
   11187               0 :         appendPQExpBufferStr(q, ",\n    STORAGE = external");
   11188               0 :     else if (*typstorage == TYPSTORAGE_EXTENDED)
   11189               0 :         appendPQExpBufferStr(q, ",\n    STORAGE = extended");
   11190               0 :     else if (*typstorage == TYPSTORAGE_MAIN)
   11191               0 :         appendPQExpBufferStr(q, ",\n    STORAGE = main");
   11192 ECB             : 
   11193 CBC          71 :     if (strcmp(typbyval, "t") == 0)
   11194              51 :         appendPQExpBufferStr(q, ",\n    PASSEDBYVALUE");
   11195 ECB             : 
   11196 GIC          71 :     appendPQExpBufferStr(q, "\n);\n");
   11197 ECB             : 
   11198 GBC          71 :     if (dopt->binary_upgrade)
   11199               8 :         binary_upgrade_extension_member(q, &tyinfo->dobj,
   11200 EUB             :                                         "TYPE", qtypname,
   11201 GIC           8 :                                         tyinfo->dobj.namespace->dobj.name);
   11202 ECB             : 
   11203 CBC          71 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   11204 GIC          71 :         ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
   11205 CBC          71 :                      ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
   11206 ECB             :                                   .namespace = tyinfo->dobj.namespace->dobj.name,
   11207                 :                                   .owner = tyinfo->rolname,
   11208                 :                                   .description = "TYPE",
   11209                 :                                   .section = SECTION_PRE_DATA,
   11210                 :                                   .createStmt = q->data,
   11211                 :                                   .dropStmt = delq->data));
   11212                 : 
   11213                 :     /* Dump Type Comments and Security Labels */
   11214 CBC          71 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   11215 GIC          36 :         dumpComment(fout, "TYPE", qtypname,
   11216              36 :                     tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
   11217              36 :                     tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
   11218                 : 
   11219              71 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
   11220 UIC           0 :         dumpSecLabel(fout, "TYPE", qtypname,
   11221               0 :                      tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
   11222               0 :                      tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
   11223                 : 
   11224 GIC          71 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
   11225              36 :         dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
   11226 ECB             :                 qtypname, NULL,
   11227 GIC          36 :                 tyinfo->dobj.namespace->dobj.name,
   11228 CBC          36 :                 tyinfo->rolname, &tyinfo->dacl);
   11229 ECB             : 
   11230 CBC          71 :     PQclear(res);
   11231 GIC          71 :     destroyPQExpBuffer(q);
   11232              71 :     destroyPQExpBuffer(delq);
   11233              71 :     destroyPQExpBuffer(query);
   11234 CBC          71 :     free(qtypname);
   11235              71 :     free(qualtypname);
   11236 GIC          71 : }
   11237 ECB             : 
   11238                 : /*
   11239                 :  * dumpDomain
   11240                 :  *    writes out to fout the queries to recreate a user-defined domain
   11241                 :  */
   11242                 : static void
   11243 GIC         121 : dumpDomain(Archive *fout, const TypeInfo *tyinfo)
   11244 ECB             : {
   11245 GIC         121 :     DumpOptions *dopt = fout->dopt;
   11246             121 :     PQExpBuffer q = createPQExpBuffer();
   11247 CBC         121 :     PQExpBuffer delq = createPQExpBuffer();
   11248             121 :     PQExpBuffer query = createPQExpBuffer();
   11249                 :     PGresult   *res;
   11250 ECB             :     int         i;
   11251                 :     char       *qtypname;
   11252                 :     char       *qualtypname;
   11253                 :     char       *typnotnull;
   11254                 :     char       *typdefn;
   11255                 :     char       *typdefault;
   11256                 :     Oid         typcollation;
   11257 GIC         121 :     bool        typdefault_is_literal = false;
   11258                 : 
   11259             121 :     if (!fout->is_prepared[PREPQUERY_DUMPDOMAIN])
   11260                 :     {
   11261                 :         /* Set up query for domain-specific details */
   11262              41 :         appendPQExpBufferStr(query,
   11263 ECB             :                              "PREPARE dumpDomain(pg_catalog.oid) AS\n");
   11264                 : 
   11265 CBC          41 :         appendPQExpBufferStr(query, "SELECT t.typnotnull, "
   11266 ECB             :                              "pg_catalog.format_type(t.typbasetype, t.typtypmod) AS typdefn, "
   11267                 :                              "pg_catalog.pg_get_expr(t.typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) AS typdefaultbin, "
   11268                 :                              "t.typdefault, "
   11269 EUB             :                              "CASE WHEN t.typcollation <> u.typcollation "
   11270                 :                              "THEN t.typcollation ELSE 0 END AS typcollation "
   11271                 :                              "FROM pg_catalog.pg_type t "
   11272                 :                              "LEFT JOIN pg_catalog.pg_type u ON (t.typbasetype = u.oid) "
   11273 ECB             :                              "WHERE t.oid = $1");
   11274 EUB             : 
   11275 GIC          41 :         ExecuteSqlStatement(fout, query->data);
   11276 EUB             : 
   11277 GBC          41 :         fout->is_prepared[PREPQUERY_DUMPDOMAIN] = true;
   11278                 :     }
   11279 ECB             : 
   11280 CBC         121 :     printfPQExpBuffer(query,
   11281 ECB             :                       "EXECUTE dumpDomain('%u')",
   11282 CBC         121 :                       tyinfo->dobj.catId.oid);
   11283 ECB             : 
   11284 GIC         121 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   11285                 : 
   11286             121 :     typnotnull = PQgetvalue(res, 0, PQfnumber(res, "typnotnull"));
   11287             121 :     typdefn = PQgetvalue(res, 0, PQfnumber(res, "typdefn"));
   11288             121 :     if (!PQgetisnull(res, 0, PQfnumber(res, "typdefaultbin")))
   11289              41 :         typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefaultbin"));
   11290 CBC          80 :     else if (!PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
   11291                 :     {
   11292 LBC           0 :         typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault"));
   11293               0 :         typdefault_is_literal = true;   /* it needs quotes */
   11294 ECB             :     }
   11295                 :     else
   11296 GIC          80 :         typdefault = NULL;
   11297             121 :     typcollation = atooid(PQgetvalue(res, 0, PQfnumber(res, "typcollation")));
   11298                 : 
   11299             121 :     if (dopt->binary_upgrade)
   11300              18 :         binary_upgrade_set_type_oids_by_type_oid(fout, q,
   11301              18 :                                                  tyinfo->dobj.catId.oid,
   11302                 :                                                  true,  /* force array type */
   11303                 :                                                  false);    /* force multirange type */
   11304                 : 
   11305             121 :     qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
   11306             121 :     qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
   11307                 : 
   11308             121 :     appendPQExpBuffer(q,
   11309                 :                       "CREATE DOMAIN %s AS %s",
   11310                 :                       qualtypname,
   11311                 :                       typdefn);
   11312                 : 
   11313                 :     /* Print collation only if different from base type's collation */
   11314             121 :     if (OidIsValid(typcollation))
   11315                 :     {
   11316                 :         CollInfo   *coll;
   11317                 : 
   11318              36 :         coll = findCollationByOid(typcollation);
   11319              36 :         if (coll)
   11320              36 :             appendPQExpBuffer(q, " COLLATE %s", fmtQualifiedDumpable(coll));
   11321                 :     }
   11322 ECB             : 
   11323 GIC         121 :     if (typnotnull[0] == 't')
   11324 CBC          10 :         appendPQExpBufferStr(q, " NOT NULL");
   11325                 : 
   11326 GIC         121 :     if (typdefault != NULL)
   11327 ECB             :     {
   11328 GIC          41 :         appendPQExpBufferStr(q, " DEFAULT ");
   11329              41 :         if (typdefault_is_literal)
   11330 UIC           0 :             appendStringLiteralAH(q, typdefault, fout);
   11331                 :         else
   11332 GIC          41 :             appendPQExpBufferStr(q, typdefault);
   11333                 :     }
   11334                 : 
   11335             121 :     PQclear(res);
   11336                 : 
   11337                 :     /*
   11338                 :      * Add any CHECK constraints for the domain
   11339                 :      */
   11340             202 :     for (i = 0; i < tyinfo->nDomChecks; i++)
   11341                 :     {
   11342              81 :         ConstraintInfo *domcheck = &(tyinfo->domChecks[i]);
   11343 ECB             : 
   11344 CBC          81 :         if (!domcheck->separate)
   11345 GIC          81 :             appendPQExpBuffer(q, "\n\tCONSTRAINT %s %s",
   11346              81 :                               fmtId(domcheck->dobj.name), domcheck->condef);
   11347                 :     }
   11348 EUB             : 
   11349 GIC         121 :     appendPQExpBufferStr(q, ";\n");
   11350                 : 
   11351 CBC         121 :     appendPQExpBuffer(delq, "DROP DOMAIN %s;\n", qualtypname);
   11352                 : 
   11353 GIC         121 :     if (dopt->binary_upgrade)
   11354 CBC          18 :         binary_upgrade_extension_member(q, &tyinfo->dobj,
   11355                 :                                         "DOMAIN", qtypname,
   11356              18 :                                         tyinfo->dobj.namespace->dobj.name);
   11357                 : 
   11358 GIC         121 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   11359 CBC         121 :         ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
   11360 GIC         121 :                      ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
   11361 ECB             :                                   .namespace = tyinfo->dobj.namespace->dobj.name,
   11362                 :                                   .owner = tyinfo->rolname,
   11363                 :                                   .description = "DOMAIN",
   11364                 :                                   .section = SECTION_PRE_DATA,
   11365                 :                                   .createStmt = q->data,
   11366                 :                                   .dropStmt = delq->data));
   11367                 : 
   11368                 :     /* Dump Domain Comments and Security Labels */
   11369 CBC         121 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   11370 LBC           0 :         dumpComment(fout, "DOMAIN", qtypname,
   11371               0 :                     tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
   11372               0 :                     tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
   11373 ECB             : 
   11374 CBC         121 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
   11375 LBC           0 :         dumpSecLabel(fout, "DOMAIN", qtypname,
   11376               0 :                      tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
   11377               0 :                      tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
   11378 ECB             : 
   11379 CBC         121 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
   11380              36 :         dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
   11381 ECB             :                 qtypname, NULL,
   11382 CBC          36 :                 tyinfo->dobj.namespace->dobj.name,
   11383              36 :                 tyinfo->rolname, &tyinfo->dacl);
   11384 ECB             : 
   11385                 :     /* Dump any per-constraint comments */
   11386 CBC         202 :     for (i = 0; i < tyinfo->nDomChecks; i++)
   11387 ECB             :     {
   11388 GBC          81 :         ConstraintInfo *domcheck = &(tyinfo->domChecks[i]);
   11389 CBC          81 :         PQExpBuffer conprefix = createPQExpBuffer();
   11390                 : 
   11391              81 :         appendPQExpBuffer(conprefix, "CONSTRAINT %s ON DOMAIN",
   11392              81 :                           fmtId(domcheck->dobj.name));
   11393                 : 
   11394 GIC          81 :         if (domcheck->dobj.dump & DUMP_COMPONENT_COMMENT)
   11395 CBC          36 :             dumpComment(fout, conprefix->data, qtypname,
   11396 GIC          36 :                         tyinfo->dobj.namespace->dobj.name,
   11397 CBC          36 :                         tyinfo->rolname,
   11398              36 :                         domcheck->dobj.catId, 0, tyinfo->dobj.dumpId);
   11399                 : 
   11400 GIC          81 :         destroyPQExpBuffer(conprefix);
   11401                 :     }
   11402                 : 
   11403             121 :     destroyPQExpBuffer(q);
   11404             121 :     destroyPQExpBuffer(delq);
   11405 CBC         121 :     destroyPQExpBuffer(query);
   11406 GIC         121 :     free(qtypname);
   11407             121 :     free(qualtypname);
   11408             121 : }
   11409                 : 
   11410                 : /*
   11411 ECB             :  * dumpCompositeType
   11412                 :  *    writes out to fout the queries to recreate a user-defined stand-alone
   11413                 :  *    composite type
   11414                 :  */
   11415                 : static void
   11416 CBC         123 : dumpCompositeType(Archive *fout, const TypeInfo *tyinfo)
   11417                 : {
   11418 GIC         123 :     DumpOptions *dopt = fout->dopt;
   11419             123 :     PQExpBuffer q = createPQExpBuffer();
   11420 CBC         123 :     PQExpBuffer dropped = createPQExpBuffer();
   11421 GIC         123 :     PQExpBuffer delq = createPQExpBuffer();
   11422             123 :     PQExpBuffer query = createPQExpBuffer();
   11423 ECB             :     PGresult   *res;
   11424                 :     char       *qtypname;
   11425                 :     char       *qualtypname;
   11426 EUB             :     int         ntups;
   11427 ECB             :     int         i_attname;
   11428 EUB             :     int         i_atttypdefn;
   11429 ECB             :     int         i_attlen;
   11430                 :     int         i_attalign;
   11431                 :     int         i_attisdropped;
   11432                 :     int         i_attcollation;
   11433                 :     int         i;
   11434 EUB             :     int         actual_atts;
   11435                 : 
   11436 CBC         123 :     if (!fout->is_prepared[PREPQUERY_DUMPCOMPOSITETYPE])
   11437 EUB             :     {
   11438                 :         /*
   11439 ECB             :          * Set up query for type-specific details.
   11440                 :          *
   11441                 :          * Since we only want to dump COLLATE clauses for attributes whose
   11442                 :          * collation is different from their type's default, we use a CASE
   11443                 :          * here to suppress uninteresting attcollations cheaply.  atttypid
   11444                 :          * will be 0 for dropped columns; collation does not matter for those.
   11445 EUB             :          */
   11446 GIC          58 :         appendPQExpBufferStr(query,
   11447                 :                              "PREPARE dumpCompositeType(pg_catalog.oid) AS\n"
   11448 ECB             :                              "SELECT a.attname, a.attnum, "
   11449                 :                              "pg_catalog.format_type(a.atttypid, a.atttypmod) AS atttypdefn, "
   11450                 :                              "a.attlen, a.attalign, a.attisdropped, "
   11451                 :                              "CASE WHEN a.attcollation <> at.typcollation "
   11452                 :                              "THEN a.attcollation ELSE 0 END AS attcollation "
   11453                 :                              "FROM pg_catalog.pg_type ct "
   11454                 :                              "JOIN pg_catalog.pg_attribute a ON a.attrelid = ct.typrelid "
   11455                 :                              "LEFT JOIN pg_catalog.pg_type at ON at.oid = a.atttypid "
   11456                 :                              "WHERE ct.oid = $1 "
   11457                 :                              "ORDER BY a.attnum");
   11458                 : 
   11459 CBC          58 :         ExecuteSqlStatement(fout, query->data);
   11460                 : 
   11461 GIC          58 :         fout->is_prepared[PREPQUERY_DUMPCOMPOSITETYPE] = true;
   11462 ECB             :     }
   11463                 : 
   11464 GIC         123 :     printfPQExpBuffer(query,
   11465 ECB             :                       "EXECUTE dumpCompositeType('%u')",
   11466 GIC         123 :                       tyinfo->dobj.catId.oid);
   11467 EUB             : 
   11468 GBC         123 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   11469                 : 
   11470 GIC         123 :     ntups = PQntuples(res);
   11471 ECB             : 
   11472 GBC         123 :     i_attname = PQfnumber(res, "attname");
   11473 CBC         123 :     i_atttypdefn = PQfnumber(res, "atttypdefn");
   11474 GBC         123 :     i_attlen = PQfnumber(res, "attlen");
   11475 CBC         123 :     i_attalign = PQfnumber(res, "attalign");
   11476             123 :     i_attisdropped = PQfnumber(res, "attisdropped");
   11477             123 :     i_attcollation = PQfnumber(res, "attcollation");
   11478 ECB             : 
   11479 GIC         123 :     if (dopt->binary_upgrade)
   11480 ECB             :     {
   11481 CBC          16 :         binary_upgrade_set_type_oids_by_type_oid(fout, q,
   11482 GBC          16 :                                                  tyinfo->dobj.catId.oid,
   11483 EUB             :                                                  false, false);
   11484 GBC          16 :         binary_upgrade_set_pg_class_oids(fout, q, tyinfo->typrelid, false);
   11485 EUB             :     }
   11486                 : 
   11487 GBC         123 :     qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
   11488 GIC         123 :     qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
   11489 ECB             : 
   11490 CBC         123 :     appendPQExpBuffer(q, "CREATE TYPE %s AS (",
   11491                 :                       qualtypname);
   11492 ECB             : 
   11493 GIC         123 :     actual_atts = 0;
   11494 CBC         382 :     for (i = 0; i < ntups; i++)
   11495 ECB             :     {
   11496                 :         char       *attname;
   11497                 :         char       *atttypdefn;
   11498                 :         char       *attlen;
   11499                 :         char       *attalign;
   11500                 :         bool        attisdropped;
   11501                 :         Oid         attcollation;
   11502                 : 
   11503 GIC         259 :         attname = PQgetvalue(res, i, i_attname);
   11504             259 :         atttypdefn = PQgetvalue(res, i, i_atttypdefn);
   11505             259 :         attlen = PQgetvalue(res, i, i_attlen);
   11506             259 :         attalign = PQgetvalue(res, i, i_attalign);
   11507             259 :         attisdropped = (PQgetvalue(res, i, i_attisdropped)[0] == 't');
   11508             259 :         attcollation = atooid(PQgetvalue(res, i, i_attcollation));
   11509                 : 
   11510 CBC         259 :         if (attisdropped && !dopt->binary_upgrade)
   11511               8 :             continue;
   11512 ECB             : 
   11513                 :         /* Format properly if not first attr */
   11514 GIC         251 :         if (actual_atts++ > 0)
   11515 CBC         128 :             appendPQExpBufferChar(q, ',');
   11516 GBC         251 :         appendPQExpBufferStr(q, "\n\t");
   11517 EUB             : 
   11518 GBC         251 :         if (!attisdropped)
   11519                 :         {
   11520 CBC         249 :             appendPQExpBuffer(q, "%s %s", fmtId(attname), atttypdefn);
   11521 ECB             : 
   11522                 :             /* Add collation if not default for the column type */
   11523 CBC         249 :             if (OidIsValid(attcollation))
   11524 ECB             :             {
   11525                 :                 CollInfo   *coll;
   11526                 : 
   11527 LBC           0 :                 coll = findCollationByOid(attcollation);
   11528               0 :                 if (coll)
   11529               0 :                     appendPQExpBuffer(q, " COLLATE %s",
   11530               0 :                                       fmtQualifiedDumpable(coll));
   11531 ECB             :             }
   11532                 :         }
   11533                 :         else
   11534                 :         {
   11535                 :             /*
   11536                 :              * This is a dropped attribute and we're in binary_upgrade mode.
   11537                 :              * Insert a placeholder for it in the CREATE TYPE command, and set
   11538                 :              * length and alignment with direct UPDATE to the catalogs
   11539                 :              * afterwards. See similar code in dumpTableSchema().
   11540                 :              */
   11541 CBC           2 :             appendPQExpBuffer(q, "%s INTEGER /* dummy */", fmtId(attname));
   11542 ECB             : 
   11543                 :             /* stash separately for insertion after the CREATE TYPE */
   11544 CBC           2 :             appendPQExpBufferStr(dropped,
   11545                 :                                  "\n-- For binary upgrade, recreate dropped column.\n");
   11546 GIC           2 :             appendPQExpBuffer(dropped, "UPDATE pg_catalog.pg_attribute\n"
   11547                 :                               "SET attlen = %s, "
   11548                 :                               "attalign = '%s', attbyval = false\n"
   11549                 :                               "WHERE attname = ", attlen, attalign);
   11550               2 :             appendStringLiteralAH(dropped, attname, fout);
   11551               2 :             appendPQExpBufferStr(dropped, "\n  AND attrelid = ");
   11552               2 :             appendStringLiteralAH(dropped, qualtypname, fout);
   11553 CBC           2 :             appendPQExpBufferStr(dropped, "::pg_catalog.regclass;\n");
   11554                 : 
   11555               2 :             appendPQExpBuffer(dropped, "ALTER TYPE %s ",
   11556                 :                               qualtypname);
   11557 GIC           2 :             appendPQExpBuffer(dropped, "DROP ATTRIBUTE %s;\n",
   11558 ECB             :                               fmtId(attname));
   11559                 :         }
   11560                 :     }
   11561 CBC         123 :     appendPQExpBufferStr(q, "\n);\n");
   11562 GIC         123 :     appendPQExpBufferStr(q, dropped->data);
   11563                 : 
   11564             123 :     appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname);
   11565                 : 
   11566             123 :     if (dopt->binary_upgrade)
   11567              16 :         binary_upgrade_extension_member(q, &tyinfo->dobj,
   11568                 :                                         "TYPE", qtypname,
   11569              16 :                                         tyinfo->dobj.namespace->dobj.name);
   11570                 : 
   11571 CBC         123 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   11572 GIC         107 :         ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
   11573 CBC         107 :                      ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
   11574                 :                                   .namespace = tyinfo->dobj.namespace->dobj.name,
   11575                 :                                   .owner = tyinfo->rolname,
   11576 ECB             :                                   .description = "TYPE",
   11577                 :                                   .section = SECTION_PRE_DATA,
   11578                 :                                   .createStmt = q->data,
   11579                 :                                   .dropStmt = delq->data));
   11580                 : 
   11581                 : 
   11582                 :     /* Dump Type Comments and Security Labels */
   11583 CBC         123 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   11584              36 :         dumpComment(fout, "TYPE", qtypname,
   11585              36 :                     tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
   11586              36 :                     tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
   11587                 : 
   11588 GBC         123 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
   11589 UBC           0 :         dumpSecLabel(fout, "TYPE", qtypname,
   11590 UIC           0 :                      tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
   11591               0 :                      tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
   11592 ECB             : 
   11593 CBC         123 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
   11594 GIC          17 :         dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
   11595 ECB             :                 qtypname, NULL,
   11596 CBC          17 :                 tyinfo->dobj.namespace->dobj.name,
   11597              17 :                 tyinfo->rolname, &tyinfo->dacl);
   11598                 : 
   11599                 :     /* Dump any per-column comments */
   11600 GIC         123 :     if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   11601 CBC          36 :         dumpCompositeTypeColComments(fout, tyinfo, res);
   11602 ECB             : 
   11603 GIC         123 :     PQclear(res);
   11604 CBC         123 :     destroyPQExpBuffer(q);
   11605 GIC         123 :     destroyPQExpBuffer(dropped);
   11606             123 :     destroyPQExpBuffer(delq);
   11607             123 :     destroyPQExpBuffer(query);
   11608             123 :     free(qtypname);
   11609             123 :     free(qualtypname);
   11610 CBC         123 : }
   11611                 : 
   11612                 : /*
   11613                 :  * dumpCompositeTypeColComments
   11614 ECB             :  *    writes out to fout the queries to recreate comments on the columns of
   11615                 :  *    a user-defined stand-alone composite type.
   11616                 :  *
   11617                 :  * The caller has already made a query to collect the names and attnums
   11618                 :  * of the type's columns, so we just pass that result into here rather
   11619                 :  * than reading them again.
   11620                 :  */
   11621                 : static void
   11622 CBC          36 : dumpCompositeTypeColComments(Archive *fout, const TypeInfo *tyinfo,
   11623                 :                              PGresult *res)
   11624 ECB             : {
   11625                 :     CommentItem *comments;
   11626 EUB             :     int         ncomments;
   11627                 :     PQExpBuffer query;
   11628 ECB             :     PQExpBuffer target;
   11629                 :     int         i;
   11630                 :     int         ntups;
   11631                 :     int         i_attname;
   11632                 :     int         i_attnum;
   11633                 :     int         i_attisdropped;
   11634                 : 
   11635                 :     /* do nothing, if --no-comments is supplied */
   11636 CBC          36 :     if (fout->dopt->no_comments)
   11637 UIC           0 :         return;
   11638 ECB             : 
   11639                 :     /* Search for comments associated with type's pg_class OID */
   11640 CBC          36 :     ncomments = findComments(RelationRelationId, tyinfo->typrelid,
   11641 ECB             :                              &comments);
   11642                 : 
   11643                 :     /* If no comments exist, we're done */
   11644 GIC          36 :     if (ncomments <= 0)
   11645 LBC           0 :         return;
   11646                 : 
   11647 ECB             :     /* Build COMMENT ON statements */
   11648 GIC          36 :     query = createPQExpBuffer();
   11649 CBC          36 :     target = createPQExpBuffer();
   11650 ECB             : 
   11651 GIC          36 :     ntups = PQntuples(res);
   11652 CBC          36 :     i_attnum = PQfnumber(res, "attnum");
   11653 GIC          36 :     i_attname = PQfnumber(res, "attname");
   11654 CBC          36 :     i_attisdropped = PQfnumber(res, "attisdropped");
   11655              72 :     while (ncomments > 0)
   11656 ECB             :     {
   11657                 :         const char *attname;
   11658                 : 
   11659 GIC          36 :         attname = NULL;
   11660              36 :         for (i = 0; i < ntups; i++)
   11661                 :         {
   11662              36 :             if (atoi(PQgetvalue(res, i, i_attnum)) == comments->objsubid &&
   11663              36 :                 PQgetvalue(res, i, i_attisdropped)[0] != 't')
   11664                 :             {
   11665 CBC          36 :                 attname = PQgetvalue(res, i, i_attname);
   11666 GBC          36 :                 break;
   11667 EUB             :             }
   11668                 :         }
   11669 GIC          36 :         if (attname)            /* just in case we don't find it */
   11670 ECB             :         {
   11671 GBC          36 :             const char *descr = comments->descr;
   11672 EUB             : 
   11673 GBC          36 :             resetPQExpBuffer(target);
   11674 GIC          36 :             appendPQExpBuffer(target, "COLUMN %s.",
   11675 CBC          36 :                               fmtId(tyinfo->dobj.name));
   11676              36 :             appendPQExpBufferStr(target, fmtId(attname));
   11677                 : 
   11678              36 :             resetPQExpBuffer(query);
   11679              36 :             appendPQExpBuffer(query, "COMMENT ON COLUMN %s.",
   11680 GIC          36 :                               fmtQualifiedDumpable(tyinfo));
   11681              36 :             appendPQExpBuffer(query, "%s IS ", fmtId(attname));
   11682 CBC          36 :             appendStringLiteralAH(query, descr, fout);
   11683 GIC          36 :             appendPQExpBufferStr(query, ";\n");
   11684 ECB             : 
   11685 CBC          36 :             ArchiveEntry(fout, nilCatalogId, createDumpId(),
   11686 GIC          36 :                          ARCHIVE_OPTS(.tag = target->data,
   11687 ECB             :                                       .namespace = tyinfo->dobj.namespace->dobj.name,
   11688                 :                                       .owner = tyinfo->rolname,
   11689                 :                                       .description = "COMMENT",
   11690                 :                                       .section = SECTION_NONE,
   11691                 :                                       .createStmt = query->data,
   11692                 :                                       .deps = &(tyinfo->dobj.dumpId),
   11693                 :                                       .nDeps = 1));
   11694                 :         }
   11695                 : 
   11696 CBC          36 :         comments++;
   11697 GIC          36 :         ncomments--;
   11698                 :     }
   11699 ECB             : 
   11700 CBC          36 :     destroyPQExpBuffer(query);
   11701              36 :     destroyPQExpBuffer(target);
   11702 ECB             : }
   11703                 : 
   11704                 : /*
   11705                 :  * dumpShellType
   11706                 :  *    writes out to fout the queries to create a shell type
   11707                 :  *
   11708                 :  * We dump a shell definition in advance of the I/O functions for the type.
   11709                 :  */
   11710                 : static void
   11711 GIC          74 : dumpShellType(Archive *fout, const ShellTypeInfo *stinfo)
   11712 ECB             : {
   11713 GIC          74 :     DumpOptions *dopt = fout->dopt;
   11714 ECB             :     PQExpBuffer q;
   11715                 : 
   11716                 :     /* Do nothing in data-only dump */
   11717 CBC          74 :     if (dopt->dataOnly)
   11718               3 :         return;
   11719                 : 
   11720 GIC          71 :     q = createPQExpBuffer();
   11721                 : 
   11722                 :     /*
   11723                 :      * Note the lack of a DROP command for the shell type; any required DROP
   11724                 :      * is driven off the base type entry, instead.  This interacts with
   11725                 :      * _printTocEntry()'s use of the presence of a DROP command to decide
   11726                 :      * whether an entry needs an ALTER OWNER command.  We don't want to alter
   11727                 :      * the shell type's owner immediately on creation; that should happen only
   11728                 :      * after it's filled in, otherwise the backend complains.
   11729                 :      */
   11730                 : 
   11731              71 :     if (dopt->binary_upgrade)
   11732 CBC           8 :         binary_upgrade_set_type_oids_by_type_oid(fout, q,
   11733 GIC           8 :                                                  stinfo->baseType->dobj.catId.oid,
   11734                 :                                                  false, false);
   11735                 : 
   11736              71 :     appendPQExpBuffer(q, "CREATE TYPE %s;\n",
   11737              71 :                       fmtQualifiedDumpable(stinfo));
   11738                 : 
   11739              71 :     if (stinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   11740              71 :         ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId,
   11741              71 :                      ARCHIVE_OPTS(.tag = stinfo->dobj.name,
   11742 ECB             :                                   .namespace = stinfo->dobj.namespace->dobj.name,
   11743                 :                                   .owner = stinfo->baseType->rolname,
   11744                 :                                   .description = "SHELL TYPE",
   11745                 :                                   .section = SECTION_PRE_DATA,
   11746                 :                                   .createStmt = q->data));
   11747                 : 
   11748 GIC          71 :     destroyPQExpBuffer(q);
   11749                 : }
   11750                 : 
   11751                 : /*
   11752                 :  * dumpProcLang
   11753                 :  *        writes out to fout the queries to recreate a user-defined
   11754                 :  *        procedural language
   11755 ECB             :  */
   11756                 : static void
   11757 CBC          83 : dumpProcLang(Archive *fout, const ProcLangInfo *plang)
   11758                 : {
   11759 GIC          83 :     DumpOptions *dopt = fout->dopt;
   11760 ECB             :     PQExpBuffer defqry;
   11761                 :     PQExpBuffer delqry;
   11762                 :     bool        useParams;
   11763                 :     char       *qlanname;
   11764                 :     FuncInfo   *funcInfo;
   11765 GIC          83 :     FuncInfo   *inlineInfo = NULL;
   11766 CBC          83 :     FuncInfo   *validatorInfo = NULL;
   11767                 : 
   11768 ECB             :     /* Do nothing in data-only dump */
   11769 CBC          83 :     if (dopt->dataOnly)
   11770               7 :         return;
   11771 ECB             : 
   11772                 :     /*
   11773                 :      * Try to find the support function(s).  It is not an error if we don't
   11774                 :      * find them --- if the functions are in the pg_catalog schema, as is
   11775                 :      * standard in 8.1 and up, then we won't have loaded them. (In this case
   11776                 :      * we will emit a parameterless CREATE LANGUAGE command, which will
   11777                 :      * require PL template knowledge in the backend to reload.)
   11778                 :      */
   11779                 : 
   11780 CBC          76 :     funcInfo = findFuncByOid(plang->lanplcallfoid);
   11781 GIC          76 :     if (funcInfo != NULL && !funcInfo->dobj.dump)
   11782               2 :         funcInfo = NULL;        /* treat not-dumped same as not-found */
   11783 ECB             : 
   11784 CBC          76 :     if (OidIsValid(plang->laninline))
   11785                 :     {
   11786              41 :         inlineInfo = findFuncByOid(plang->laninline);
   11787 GIC          41 :         if (inlineInfo != NULL && !inlineInfo->dobj.dump)
   11788               1 :             inlineInfo = NULL;
   11789 ECB             :     }
   11790                 : 
   11791 GIC          76 :     if (OidIsValid(plang->lanvalidator))
   11792                 :     {
   11793              41 :         validatorInfo = findFuncByOid(plang->lanvalidator);
   11794              41 :         if (validatorInfo != NULL && !validatorInfo->dobj.dump)
   11795               1 :             validatorInfo = NULL;
   11796                 :     }
   11797                 : 
   11798                 :     /*
   11799 ECB             :      * If the functions are dumpable then emit a complete CREATE LANGUAGE with
   11800                 :      * parameters.  Otherwise, we'll write a parameterless command, which will
   11801                 :      * be interpreted as CREATE EXTENSION.
   11802                 :      */
   11803 CBC          34 :     useParams = (funcInfo != NULL &&
   11804             144 :                  (inlineInfo != NULL || !OidIsValid(plang->laninline)) &&
   11805 GIC          34 :                  (validatorInfo != NULL || !OidIsValid(plang->lanvalidator)));
   11806 ECB             : 
   11807 CBC          76 :     defqry = createPQExpBuffer();
   11808 GIC          76 :     delqry = createPQExpBuffer();
   11809                 : 
   11810 CBC          76 :     qlanname = pg_strdup(fmtId(plang->dobj.name));
   11811 ECB             : 
   11812 CBC          76 :     appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n",
   11813                 :                       qlanname);
   11814 ECB             : 
   11815 GIC          76 :     if (useParams)
   11816 ECB             :     {
   11817 GIC          34 :         appendPQExpBuffer(defqry, "CREATE %sPROCEDURAL LANGUAGE %s",
   11818              34 :                           plang->lanpltrusted ? "TRUSTED " : "",
   11819 ECB             :                           qlanname);
   11820 GIC          34 :         appendPQExpBuffer(defqry, " HANDLER %s",
   11821              34 :                           fmtQualifiedDumpable(funcInfo));
   11822              34 :         if (OidIsValid(plang->laninline))
   11823 UBC           0 :             appendPQExpBuffer(defqry, " INLINE %s",
   11824               0 :                               fmtQualifiedDumpable(inlineInfo));
   11825 GBC          34 :         if (OidIsValid(plang->lanvalidator))
   11826 UBC           0 :             appendPQExpBuffer(defqry, " VALIDATOR %s",
   11827 UIC           0 :                               fmtQualifiedDumpable(validatorInfo));
   11828                 :     }
   11829                 :     else
   11830                 :     {
   11831                 :         /*
   11832                 :          * If not dumping parameters, then use CREATE OR REPLACE so that the
   11833                 :          * command will not fail if the language is preinstalled in the target
   11834                 :          * database.
   11835                 :          *
   11836                 :          * Modern servers will interpret this as CREATE EXTENSION IF NOT
   11837 ECB             :          * EXISTS; perhaps we should emit that instead?  But it might just add
   11838                 :          * confusion.
   11839                 :          */
   11840 CBC          42 :         appendPQExpBuffer(defqry, "CREATE OR REPLACE PROCEDURAL LANGUAGE %s",
   11841                 :                           qlanname);
   11842 ECB             :     }
   11843 GIC          76 :     appendPQExpBufferStr(defqry, ";\n");
   11844                 : 
   11845              76 :     if (dopt->binary_upgrade)
   11846 CBC           2 :         binary_upgrade_extension_member(defqry, &plang->dobj,
   11847 ECB             :                                         "LANGUAGE", qlanname, NULL);
   11848                 : 
   11849 CBC          76 :     if (plang->dobj.dump & DUMP_COMPONENT_DEFINITION)
   11850 GIC          35 :         ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
   11851 CBC          35 :                      ARCHIVE_OPTS(.tag = plang->dobj.name,
   11852                 :                                   .owner = plang->lanowner,
   11853 ECB             :                                   .description = "PROCEDURAL LANGUAGE",
   11854                 :                                   .section = SECTION_PRE_DATA,
   11855                 :                                   .createStmt = defqry->data,
   11856                 :                                   .dropStmt = delqry->data,
   11857                 :                                   ));
   11858                 : 
   11859                 :     /* Dump Proc Lang Comments and Security Labels */
   11860 CBC          76 :     if (plang->dobj.dump & DUMP_COMPONENT_COMMENT)
   11861 UIC           0 :         dumpComment(fout, "LANGUAGE", qlanname,
   11862 LBC           0 :                     NULL, plang->lanowner,
   11863               0 :                     plang->dobj.catId, 0, plang->dobj.dumpId);
   11864                 : 
   11865 CBC          76 :     if (plang->dobj.dump & DUMP_COMPONENT_SECLABEL)
   11866 UIC           0 :         dumpSecLabel(fout, "LANGUAGE", qlanname,
   11867 LBC           0 :                      NULL, plang->lanowner,
   11868               0 :                      plang->dobj.catId, 0, plang->dobj.dumpId);
   11869 ECB             : 
   11870 GIC          76 :     if (plang->lanpltrusted && plang->dobj.dump & DUMP_COMPONENT_ACL)
   11871              41 :         dumpACL(fout, plang->dobj.dumpId, InvalidDumpId, "LANGUAGE",
   11872                 :                 qlanname, NULL, NULL,
   11873              41 :                 plang->lanowner, &plang->dacl);
   11874                 : 
   11875              76 :     free(qlanname);
   11876                 : 
   11877              76 :     destroyPQExpBuffer(defqry);
   11878              76 :     destroyPQExpBuffer(delqry);
   11879 ECB             : }
   11880                 : 
   11881                 : /*
   11882                 :  * format_function_arguments: generate function name and argument list
   11883                 :  *
   11884                 :  * This is used when we can rely on pg_get_function_arguments to format
   11885 EUB             :  * the argument list.  Note, however, that pg_get_function_arguments
   11886                 :  * does not special-case zero-argument aggregates.
   11887                 :  */
   11888                 : static char *
   11889 CBC        3948 : format_function_arguments(const FuncInfo *finfo, const char *funcargs, bool is_agg)
   11890 ECB             : {
   11891                 :     PQExpBufferData fn;
   11892                 : 
   11893 CBC        3948 :     initPQExpBuffer(&fn);
   11894 GIC        3948 :     appendPQExpBufferStr(&fn, fmtId(finfo->dobj.name));
   11895            3948 :     if (is_agg && finfo->nargs == 0)
   11896 CBC          80 :         appendPQExpBufferStr(&fn, "(*)");
   11897 ECB             :     else
   11898 GIC        3868 :         appendPQExpBuffer(&fn, "(%s)", funcargs);
   11899 CBC        3948 :     return fn.data;
   11900 ECB             : }
   11901                 : 
   11902                 : /*
   11903                 :  * format_function_signature: generate function name and argument list
   11904                 :  *
   11905                 :  * Only a minimal list of input argument types is generated; this is
   11906                 :  * sufficient to reference the function, but not to define it.
   11907                 :  *
   11908                 :  * If honor_quotes is false then the function name is never quoted.
   11909                 :  * This is appropriate for use in TOC tags, but not in SQL commands.
   11910                 :  */
   11911                 : static char *
   11912 GIC        2094 : format_function_signature(Archive *fout, const FuncInfo *finfo, bool honor_quotes)
   11913                 : {
   11914                 :     PQExpBufferData fn;
   11915                 :     int         j;
   11916                 : 
   11917            2094 :     initPQExpBuffer(&fn);
   11918 CBC        2094 :     if (honor_quotes)
   11919 GIC         408 :         appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name));
   11920                 :     else
   11921            1686 :         appendPQExpBuffer(&fn, "%s(", finfo->dobj.name);
   11922            3890 :     for (j = 0; j < finfo->nargs; j++)
   11923                 :     {
   11924            1796 :         if (j > 0)
   11925             415 :             appendPQExpBufferStr(&fn, ", ");
   11926                 : 
   11927            1796 :         appendPQExpBufferStr(&fn,
   11928            1796 :                              getFormattedTypeName(fout, finfo->argtypes[j],
   11929                 :                                                   zeroIsError));
   11930                 :     }
   11931            2094 :     appendPQExpBufferChar(&fn, ')');
   11932 CBC        2094 :     return fn.data;
   11933 EUB             : }
   11934                 : 
   11935                 : 
   11936 ECB             : /*
   11937                 :  * dumpFunc:
   11938                 :  *    dump out one function
   11939                 :  */
   11940                 : static void
   11941 GBC        1715 : dumpFunc(Archive *fout, const FuncInfo *finfo)
   11942                 : {
   11943 GIC        1715 :     DumpOptions *dopt = fout->dopt;
   11944 ECB             :     PQExpBuffer query;
   11945                 :     PQExpBuffer q;
   11946                 :     PQExpBuffer delqry;
   11947                 :     PQExpBuffer asPart;
   11948                 :     PGresult   *res;
   11949                 :     char       *funcsig;        /* identity signature */
   11950 CBC        1715 :     char       *funcfullsig = NULL; /* full signature */
   11951 ECB             :     char       *funcsig_tag;
   11952                 :     char       *qual_funcsig;
   11953                 :     char       *proretset;
   11954                 :     char       *prosrc;
   11955                 :     char       *probin;
   11956                 :     char       *prosqlbody;
   11957                 :     char       *funcargs;
   11958                 :     char       *funciargs;
   11959                 :     char       *funcresult;
   11960                 :     char       *protrftypes;
   11961                 :     char       *prokind;
   11962                 :     char       *provolatile;
   11963                 :     char       *proisstrict;
   11964                 :     char       *prosecdef;
   11965                 :     char       *proleakproof;
   11966                 :     char       *proconfig;
   11967                 :     char       *procost;
   11968                 :     char       *prorows;
   11969                 :     char       *prosupport;
   11970                 :     char       *proparallel;
   11971                 :     char       *lanname;
   11972 CBC        1715 :     char      **configitems = NULL;
   11973 GIC        1715 :     int         nconfigitems = 0;
   11974 ECB             :     const char *keyword;
   11975                 : 
   11976                 :     /* Do nothing in data-only dump */
   11977 CBC        1715 :     if (dopt->dataOnly)
   11978              29 :         return;
   11979                 : 
   11980            1686 :     query = createPQExpBuffer();
   11981            1686 :     q = createPQExpBuffer();
   11982 GIC        1686 :     delqry = createPQExpBuffer();
   11983            1686 :     asPart = createPQExpBuffer();
   11984                 : 
   11985            1686 :     if (!fout->is_prepared[PREPQUERY_DUMPFUNC])
   11986                 :     {
   11987                 :         /* Set up query for function-specific details */
   11988              59 :         appendPQExpBufferStr(query,
   11989                 :                              "PREPARE dumpFunc(pg_catalog.oid) AS\n");
   11990                 : 
   11991 CBC          59 :         appendPQExpBufferStr(query,
   11992 ECB             :                              "SELECT\n"
   11993                 :                              "proretset,\n"
   11994                 :                              "prosrc,\n"
   11995                 :                              "probin,\n"
   11996                 :                              "provolatile,\n"
   11997                 :                              "proisstrict,\n"
   11998                 :                              "prosecdef,\n"
   11999                 :                              "lanname,\n"
   12000                 :                              "proconfig,\n"
   12001                 :                              "procost,\n"
   12002                 :                              "prorows,\n"
   12003                 :                              "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs,\n"
   12004                 :                              "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs,\n"
   12005                 :                              "pg_catalog.pg_get_function_result(p.oid) AS funcresult,\n"
   12006                 :                              "proleakproof,\n");
   12007                 : 
   12008 CBC          59 :         if (fout->remoteVersion >= 90500)
   12009 GIC          59 :             appendPQExpBufferStr(query,
   12010                 :                                  "array_to_string(protrftypes, ' ') AS protrftypes,\n");
   12011                 :         else
   12012 LBC           0 :             appendPQExpBufferStr(query,
   12013 ECB             :                                  "NULL AS protrftypes,\n");
   12014                 : 
   12015 CBC          59 :         if (fout->remoteVersion >= 90600)
   12016 GIC          59 :             appendPQExpBufferStr(query,
   12017                 :                                  "proparallel,\n");
   12018                 :         else
   12019 UIC           0 :             appendPQExpBufferStr(query,
   12020                 :                                  "'u' AS proparallel,\n");
   12021                 : 
   12022 GIC          59 :         if (fout->remoteVersion >= 110000)
   12023              59 :             appendPQExpBufferStr(query,
   12024                 :                                  "prokind,\n");
   12025                 :         else
   12026 LBC           0 :             appendPQExpBufferStr(query,
   12027 ECB             :                                  "CASE WHEN proiswindow THEN 'w' ELSE 'f' END AS prokind,\n");
   12028                 : 
   12029 GIC          59 :         if (fout->remoteVersion >= 120000)
   12030              59 :             appendPQExpBufferStr(query,
   12031 ECB             :                                  "prosupport,\n");
   12032                 :         else
   12033 UIC           0 :             appendPQExpBufferStr(query,
   12034 ECB             :                                  "'-' AS prosupport,\n");
   12035                 : 
   12036 CBC          59 :         if (fout->remoteVersion >= 140000)
   12037 GIC          59 :             appendPQExpBufferStr(query,
   12038                 :                                  "pg_get_function_sqlbody(p.oid) AS prosqlbody\n");
   12039                 :         else
   12040 UIC           0 :             appendPQExpBufferStr(query,
   12041                 :                                  "NULL AS prosqlbody\n");
   12042                 : 
   12043 CBC          59 :         appendPQExpBufferStr(query,
   12044                 :                              "FROM pg_catalog.pg_proc p, pg_catalog.pg_language l\n"
   12045                 :                              "WHERE p.oid = $1 "
   12046                 :                              "AND l.oid = p.prolang");
   12047                 : 
   12048 GIC          59 :         ExecuteSqlStatement(fout, query->data);
   12049                 : 
   12050              59 :         fout->is_prepared[PREPQUERY_DUMPFUNC] = true;
   12051                 :     }
   12052 ECB             : 
   12053 GIC        1686 :     printfPQExpBuffer(query,
   12054 ECB             :                       "EXECUTE dumpFunc('%u')",
   12055 GIC        1686 :                       finfo->dobj.catId.oid);
   12056                 : 
   12057            1686 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   12058                 : 
   12059            1686 :     proretset = PQgetvalue(res, 0, PQfnumber(res, "proretset"));
   12060 CBC        1686 :     if (PQgetisnull(res, 0, PQfnumber(res, "prosqlbody")))
   12061 ECB             :     {
   12062 GIC        1671 :         prosrc = PQgetvalue(res, 0, PQfnumber(res, "prosrc"));
   12063            1671 :         probin = PQgetvalue(res, 0, PQfnumber(res, "probin"));
   12064 CBC        1671 :         prosqlbody = NULL;
   12065 ECB             :     }
   12066                 :     else
   12067                 :     {
   12068 GIC          15 :         prosrc = NULL;
   12069              15 :         probin = NULL;
   12070              15 :         prosqlbody = PQgetvalue(res, 0, PQfnumber(res, "prosqlbody"));
   12071                 :     }
   12072            1686 :     funcargs = PQgetvalue(res, 0, PQfnumber(res, "funcargs"));
   12073            1686 :     funciargs = PQgetvalue(res, 0, PQfnumber(res, "funciargs"));
   12074            1686 :     funcresult = PQgetvalue(res, 0, PQfnumber(res, "funcresult"));
   12075 CBC        1686 :     protrftypes = PQgetvalue(res, 0, PQfnumber(res, "protrftypes"));
   12076            1686 :     prokind = PQgetvalue(res, 0, PQfnumber(res, "prokind"));
   12077            1686 :     provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
   12078 GIC        1686 :     proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
   12079 CBC        1686 :     prosecdef = PQgetvalue(res, 0, PQfnumber(res, "prosecdef"));
   12080 GIC        1686 :     proleakproof = PQgetvalue(res, 0, PQfnumber(res, "proleakproof"));
   12081 CBC        1686 :     proconfig = PQgetvalue(res, 0, PQfnumber(res, "proconfig"));
   12082            1686 :     procost = PQgetvalue(res, 0, PQfnumber(res, "procost"));
   12083            1686 :     prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows"));
   12084 GIC        1686 :     prosupport = PQgetvalue(res, 0, PQfnumber(res, "prosupport"));
   12085            1686 :     proparallel = PQgetvalue(res, 0, PQfnumber(res, "proparallel"));
   12086 CBC        1686 :     lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname"));
   12087                 : 
   12088 ECB             :     /*
   12089                 :      * See backend/commands/functioncmds.c for details of how the 'AS' clause
   12090                 :      * is used.
   12091                 :      */
   12092 GIC        1686 :     if (prosqlbody)
   12093                 :     {
   12094              15 :         appendPQExpBufferStr(asPart, prosqlbody);
   12095                 :     }
   12096            1671 :     else if (probin[0] != '\0')
   12097                 :     {
   12098 CBC         151 :         appendPQExpBufferStr(asPart, "AS ");
   12099             151 :         appendStringLiteralAH(asPart, probin, fout);
   12100             151 :         if (prosrc[0] != '\0')
   12101                 :         {
   12102             151 :             appendPQExpBufferStr(asPart, ", ");
   12103 ECB             : 
   12104                 :             /*
   12105                 :              * where we have bin, use dollar quoting if allowed and src
   12106                 :              * contains quote or backslash; else use regular quoting.
   12107                 :              */
   12108 GIC         151 :             if (dopt->disable_dollar_quoting ||
   12109             151 :                 (strchr(prosrc, '\'') == NULL && strchr(prosrc, '\\') == NULL))
   12110 CBC         151 :                 appendStringLiteralAH(asPart, prosrc, fout);
   12111                 :             else
   12112 LBC           0 :                 appendStringLiteralDQ(asPart, prosrc, NULL);
   12113 ECB             :         }
   12114                 :     }
   12115                 :     else
   12116                 :     {
   12117 CBC        1520 :         appendPQExpBufferStr(asPart, "AS ");
   12118 EUB             :         /* with no bin, dollar quote src unconditionally if allowed */
   12119 GBC        1520 :         if (dopt->disable_dollar_quoting)
   12120 LBC           0 :             appendStringLiteralAH(asPart, prosrc, fout);
   12121 EUB             :         else
   12122 GBC        1520 :             appendStringLiteralDQ(asPart, prosrc, NULL);
   12123                 :     }
   12124                 : 
   12125 GIC        1686 :     if (*proconfig)
   12126                 :     {
   12127              15 :         if (!parsePGArray(proconfig, &configitems, &nconfigitems))
   12128 UIC           0 :             pg_fatal("could not parse %s array", "proconfig");
   12129                 :     }
   12130                 :     else
   12131                 :     {
   12132 GIC        1671 :         configitems = NULL;
   12133            1671 :         nconfigitems = 0;
   12134                 :     }
   12135 ECB             : 
   12136 GIC        1686 :     funcfullsig = format_function_arguments(finfo, funcargs, false);
   12137            1686 :     funcsig = format_function_arguments(finfo, funciargs, false);
   12138 ECB             : 
   12139 GIC        1686 :     funcsig_tag = format_function_signature(fout, finfo, false);
   12140 ECB             : 
   12141 CBC        1686 :     qual_funcsig = psprintf("%s.%s",
   12142 GIC        1686 :                             fmtId(finfo->dobj.namespace->dobj.name),
   12143                 :                             funcsig);
   12144 ECB             : 
   12145 CBC        1686 :     if (prokind[0] == PROKIND_PROCEDURE)
   12146              81 :         keyword = "PROCEDURE";
   12147                 :     else
   12148 GIC        1605 :         keyword = "FUNCTION"; /* works for window functions too */
   12149                 : 
   12150            1686 :     appendPQExpBuffer(delqry, "DROP %s %s;\n",
   12151                 :                       keyword, qual_funcsig);
   12152                 : 
   12153            3372 :     appendPQExpBuffer(q, "CREATE %s %s.%s",
   12154                 :                       keyword,
   12155 CBC        1686 :                       fmtId(finfo->dobj.namespace->dobj.name),
   12156 EUB             :                       funcfullsig ? funcfullsig :
   12157                 :                       funcsig);
   12158                 : 
   12159 GIC        1686 :     if (prokind[0] == PROKIND_PROCEDURE)
   12160 ECB             :          /* no result type to output */ ;
   12161 GBC        1605 :     else if (funcresult)
   12162            1605 :         appendPQExpBuffer(q, " RETURNS %s", funcresult);
   12163 EUB             :     else
   12164 UIC           0 :         appendPQExpBuffer(q, " RETURNS %s%s",
   12165 LBC           0 :                           (proretset[0] == 't') ? "SETOF " : "",
   12166               0 :                           getFormattedTypeName(fout, finfo->prorettype,
   12167                 :                                                zeroIsError));
   12168 ECB             : 
   12169 GIC        1686 :     appendPQExpBuffer(q, "\n    LANGUAGE %s", fmtId(lanname));
   12170 ECB             : 
   12171 GIC        1686 :     if (*protrftypes)
   12172 ECB             :     {
   12173 LBC           0 :         Oid        *typeids = palloc(FUNC_MAX_ARGS * sizeof(Oid));
   12174                 :         int         i;
   12175                 : 
   12176 UIC           0 :         appendPQExpBufferStr(q, " TRANSFORM ");
   12177               0 :         parseOidArray(protrftypes, typeids, FUNC_MAX_ARGS);
   12178               0 :         for (i = 0; typeids[i]; i++)
   12179                 :         {
   12180               0 :             if (i != 0)
   12181               0 :                 appendPQExpBufferStr(q, ", ");
   12182               0 :             appendPQExpBuffer(q, "FOR TYPE %s",
   12183               0 :                               getFormattedTypeName(fout, typeids[i], zeroAsNone));
   12184 ECB             :         }
   12185                 :     }
   12186                 : 
   12187 GIC        1686 :     if (prokind[0] == PROKIND_WINDOW)
   12188 CBC           5 :         appendPQExpBufferStr(q, " WINDOW");
   12189 ECB             : 
   12190 CBC        1686 :     if (provolatile[0] != PROVOLATILE_VOLATILE)
   12191 ECB             :     {
   12192 GIC         352 :         if (provolatile[0] == PROVOLATILE_IMMUTABLE)
   12193 CBC         332 :             appendPQExpBufferStr(q, " IMMUTABLE");
   12194              20 :         else if (provolatile[0] == PROVOLATILE_STABLE)
   12195 GIC          20 :             appendPQExpBufferStr(q, " STABLE");
   12196 UIC           0 :         else if (provolatile[0] != PROVOLATILE_VOLATILE)
   12197               0 :             pg_fatal("unrecognized provolatile value for function \"%s\"",
   12198                 :                      finfo->dobj.name);
   12199                 :     }
   12200                 : 
   12201 GIC        1686 :     if (proisstrict[0] == 't')
   12202             357 :         appendPQExpBufferStr(q, " STRICT");
   12203                 : 
   12204            1686 :     if (prosecdef[0] == 't')
   12205 UIC           0 :         appendPQExpBufferStr(q, " SECURITY DEFINER");
   12206                 : 
   12207 CBC        1686 :     if (proleakproof[0] == 't')
   12208 GIC          10 :         appendPQExpBufferStr(q, " LEAKPROOF");
   12209                 : 
   12210                 :     /*
   12211                 :      * COST and ROWS are emitted only if present and not default, so as not to
   12212 ECB             :      * break backwards-compatibility of the dump without need.  Keep this code
   12213                 :      * in sync with the defaults in functioncmds.c.
   12214                 :      */
   12215 GIC        1686 :     if (strcmp(procost, "0") != 0)
   12216 ECB             :     {
   12217 CBC        1686 :         if (strcmp(lanname, "internal") == 0 || strcmp(lanname, "c") == 0)
   12218                 :         {
   12219 ECB             :             /* default cost is 1 */
   12220 CBC         388 :             if (strcmp(procost, "1") != 0)
   12221 UIC           0 :                 appendPQExpBuffer(q, " COST %s", procost);
   12222 ECB             :         }
   12223                 :         else
   12224                 :         {
   12225                 :             /* default cost is 100 */
   12226 CBC        1298 :             if (strcmp(procost, "100") != 0)
   12227               5 :                 appendPQExpBuffer(q, " COST %s", procost);
   12228                 :         }
   12229                 :     }
   12230 GIC        1686 :     if (proretset[0] == 't' &&
   12231             155 :         strcmp(prorows, "0") != 0 && strcmp(prorows, "1000") != 0)
   12232 UIC           0 :         appendPQExpBuffer(q, " ROWS %s", prorows);
   12233                 : 
   12234 GIC        1686 :     if (strcmp(prosupport, "-") != 0)
   12235                 :     {
   12236 ECB             :         /* We rely on regprocout to provide quoting and qualification */
   12237 GIC          46 :         appendPQExpBuffer(q, " SUPPORT %s", prosupport);
   12238 ECB             :     }
   12239                 : 
   12240 GIC        1686 :     if (proparallel[0] != PROPARALLEL_UNSAFE)
   12241                 :     {
   12242             120 :         if (proparallel[0] == PROPARALLEL_SAFE)
   12243             115 :             appendPQExpBufferStr(q, " PARALLEL SAFE");
   12244               5 :         else if (proparallel[0] == PROPARALLEL_RESTRICTED)
   12245 CBC           5 :             appendPQExpBufferStr(q, " PARALLEL RESTRICTED");
   12246 UIC           0 :         else if (proparallel[0] != PROPARALLEL_UNSAFE)
   12247               0 :             pg_fatal("unrecognized proparallel value for function \"%s\"",
   12248                 :                      finfo->dobj.name);
   12249                 :     }
   12250                 : 
   12251 GNC        1721 :     for (int i = 0; i < nconfigitems; i++)
   12252                 :     {
   12253                 :         /* we feel free to scribble on configitems[] here */
   12254 GIC          35 :         char       *configitem = configitems[i];
   12255                 :         char       *pos;
   12256                 : 
   12257              35 :         pos = strchr(configitem, '=');
   12258              35 :         if (pos == NULL)
   12259 UIC           0 :             continue;
   12260 GIC          35 :         *pos++ = '\0';
   12261              35 :         appendPQExpBuffer(q, "\n    SET %s TO ", fmtId(configitem));
   12262                 : 
   12263                 :         /*
   12264                 :          * Variables that are marked GUC_LIST_QUOTE were already fully quoted
   12265                 :          * by flatten_set_variable_args() before they were put into the
   12266                 :          * proconfig array.  However, because the quoting rules used there
   12267 ECB             :          * aren't exactly like SQL's, we have to break the list value apart
   12268                 :          * and then quote the elements as string literals.  (The elements may
   12269                 :          * be double-quoted as-is, but we can't just feed them to the SQL
   12270                 :          * parser; it would do the wrong thing with elements that are
   12271                 :          * zero-length or longer than NAMEDATALEN.)
   12272                 :          *
   12273                 :          * Variables that are not so marked should just be emitted as simple
   12274                 :          * string literals.  If the variable is not known to
   12275                 :          * variable_is_guc_list_quote(), we'll do that; this makes it unsafe
   12276                 :          * to use GUC_LIST_QUOTE for extension variables.
   12277                 :          */
   12278 CBC          35 :         if (variable_is_guc_list_quote(configitem))
   12279                 :         {
   12280 ECB             :             char      **namelist;
   12281                 :             char      **nameptr;
   12282                 : 
   12283                 :             /* Parse string into list of identifiers */
   12284                 :             /* this shouldn't fail really */
   12285 GIC          10 :             if (SplitGUCList(pos, ',', &namelist))
   12286 ECB             :             {
   12287 GIC          35 :                 for (nameptr = namelist; *nameptr; nameptr++)
   12288                 :                 {
   12289              25 :                     if (nameptr != namelist)
   12290              15 :                         appendPQExpBufferStr(q, ", ");
   12291              25 :                     appendStringLiteralAH(q, *nameptr, fout);
   12292                 :                 }
   12293                 :             }
   12294              10 :             pg_free(namelist);
   12295                 :         }
   12296                 :         else
   12297              25 :             appendStringLiteralAH(q, pos, fout);
   12298                 :     }
   12299                 : 
   12300            1686 :     appendPQExpBuffer(q, "\n    %s;\n", asPart->data);
   12301                 : 
   12302            1686 :     append_depends_on_extension(fout, q, &finfo->dobj,
   12303 ECB             :                                 "pg_catalog.pg_proc", keyword,
   12304                 :                                 qual_funcsig);
   12305                 : 
   12306 GIC        1686 :     if (dopt->binary_upgrade)
   12307 GBC         277 :         binary_upgrade_extension_member(q, &finfo->dobj,
   12308                 :                                         keyword, funcsig,
   12309 GIC         277 :                                         finfo->dobj.namespace->dobj.name);
   12310 ECB             : 
   12311 CBC        1686 :     if (finfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   12312 GIC        1584 :         ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
   12313            1584 :                      ARCHIVE_OPTS(.tag = funcsig_tag,
   12314 EUB             :                                   .namespace = finfo->dobj.namespace->dobj.name,
   12315                 :                                   .owner = finfo->rolname,
   12316                 :                                   .description = keyword,
   12317 ECB             :                                   .section = SECTION_PRE_DATA,
   12318                 :                                   .createStmt = q->data,
   12319                 :                                   .dropStmt = delqry->data));
   12320                 : 
   12321 EUB             :     /* Dump Function Comments and Security Labels */
   12322 GIC        1686 :     if (finfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   12323 UIC           0 :         dumpComment(fout, keyword, funcsig,
   12324 LBC           0 :                     finfo->dobj.namespace->dobj.name, finfo->rolname,
   12325               0 :                     finfo->dobj.catId, 0, finfo->dobj.dumpId);
   12326                 : 
   12327 GIC        1686 :     if (finfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
   12328 UBC           0 :         dumpSecLabel(fout, keyword, funcsig,
   12329 UIC           0 :                      finfo->dobj.namespace->dobj.name, finfo->rolname,
   12330               0 :                      finfo->dobj.catId, 0, finfo->dobj.dumpId);
   12331 ECB             : 
   12332 CBC        1686 :     if (finfo->dobj.dump & DUMP_COMPONENT_ACL)
   12333 GIC         104 :         dumpACL(fout, finfo->dobj.dumpId, InvalidDumpId, keyword,
   12334                 :                 funcsig, NULL,
   12335 GBC         104 :                 finfo->dobj.namespace->dobj.name,
   12336 GIC         104 :                 finfo->rolname, &finfo->dacl);
   12337                 : 
   12338 CBC        1686 :     PQclear(res);
   12339                 : 
   12340 GIC        1686 :     destroyPQExpBuffer(query);
   12341            1686 :     destroyPQExpBuffer(q);
   12342            1686 :     destroyPQExpBuffer(delqry);
   12343 CBC        1686 :     destroyPQExpBuffer(asPart);
   12344 GIC        1686 :     free(funcsig);
   12345 GNC        1686 :     free(funcfullsig);
   12346 GIC        1686 :     free(funcsig_tag);
   12347 CBC        1686 :     free(qual_funcsig);
   12348 GNC        1686 :     free(configitems);
   12349                 : }
   12350 ECB             : 
   12351                 : 
   12352                 : /*
   12353                 :  * Dump a user-defined cast
   12354                 :  */
   12355                 : static void
   12356 CBC          68 : dumpCast(Archive *fout, const CastInfo *cast)
   12357 ECB             : {
   12358 GIC          68 :     DumpOptions *dopt = fout->dopt;
   12359                 :     PQExpBuffer defqry;
   12360                 :     PQExpBuffer delqry;
   12361 ECB             :     PQExpBuffer labelq;
   12362                 :     PQExpBuffer castargs;
   12363 CBC          68 :     FuncInfo   *funcInfo = NULL;
   12364                 :     const char *sourceType;
   12365 ECB             :     const char *targetType;
   12366                 : 
   12367                 :     /* Do nothing in data-only dump */
   12368 CBC          68 :     if (dopt->dataOnly)
   12369               3 :         return;
   12370 ECB             : 
   12371                 :     /* Cannot dump if we don't have the cast function's info */
   12372 CBC          65 :     if (OidIsValid(cast->castfunc))
   12373 ECB             :     {
   12374 CBC          40 :         funcInfo = findFuncByOid(cast->castfunc);
   12375              40 :         if (funcInfo == NULL)
   12376 LBC           0 :             pg_fatal("could not find function definition for function with OID %u",
   12377 ECB             :                      cast->castfunc);
   12378                 :     }
   12379                 : 
   12380 GIC          65 :     defqry = createPQExpBuffer();
   12381              65 :     delqry = createPQExpBuffer();
   12382              65 :     labelq = createPQExpBuffer();
   12383              65 :     castargs = createPQExpBuffer();
   12384                 : 
   12385 CBC          65 :     sourceType = getFormattedTypeName(fout, cast->castsource, zeroAsNone);
   12386 GIC          65 :     targetType = getFormattedTypeName(fout, cast->casttarget, zeroAsNone);
   12387 CBC          65 :     appendPQExpBuffer(delqry, "DROP CAST (%s AS %s);\n",
   12388                 :                       sourceType, targetType);
   12389 ECB             : 
   12390 GIC          65 :     appendPQExpBuffer(defqry, "CREATE CAST (%s AS %s) ",
   12391 ECB             :                       sourceType, targetType);
   12392                 : 
   12393 CBC          65 :     switch (cast->castmethod)
   12394                 :     {
   12395              25 :         case COERCION_METHOD_BINARY:
   12396 GIC          25 :             appendPQExpBufferStr(defqry, "WITHOUT FUNCTION");
   12397              25 :             break;
   12398 UIC           0 :         case COERCION_METHOD_INOUT:
   12399               0 :             appendPQExpBufferStr(defqry, "WITH INOUT");
   12400               0 :             break;
   12401 CBC          40 :         case COERCION_METHOD_FUNCTION:
   12402              40 :             if (funcInfo)
   12403 ECB             :             {
   12404 GIC          40 :                 char       *fsig = format_function_signature(fout, funcInfo, true);
   12405 EUB             : 
   12406                 :                 /*
   12407                 :                  * Always qualify the function name (format_function_signature
   12408                 :                  * won't qualify it).
   12409                 :                  */
   12410 CBC          40 :                 appendPQExpBuffer(defqry, "WITH FUNCTION %s.%s",
   12411 GIC          40 :                                   fmtId(funcInfo->dobj.namespace->dobj.name), fsig);
   12412 CBC          40 :                 free(fsig);
   12413 EUB             :             }
   12414                 :             else
   12415 LBC           0 :                 pg_log_warning("bogus value in pg_cast.castfunc or pg_cast.castmethod field");
   12416 GIC          40 :             break;
   12417 UIC           0 :         default:
   12418 LBC           0 :             pg_log_warning("bogus value in pg_cast.castmethod field");
   12419                 :     }
   12420 ECB             : 
   12421 GBC          65 :     if (cast->castcontext == 'a')
   12422 GIC          35 :         appendPQExpBufferStr(defqry, " AS ASSIGNMENT");
   12423              30 :     else if (cast->castcontext == 'i')
   12424              10 :         appendPQExpBufferStr(defqry, " AS IMPLICIT");
   12425 CBC          65 :     appendPQExpBufferStr(defqry, ";\n");
   12426 ECB             : 
   12427 GIC          65 :     appendPQExpBuffer(labelq, "CAST (%s AS %s)",
   12428                 :                       sourceType, targetType);
   12429 ECB             : 
   12430 CBC          65 :     appendPQExpBuffer(castargs, "(%s AS %s)",
   12431                 :                       sourceType, targetType);
   12432 ECB             : 
   12433 GIC          65 :     if (dopt->binary_upgrade)
   12434 CBC           7 :         binary_upgrade_extension_member(defqry, &cast->dobj,
   12435               7 :                                         "CAST", castargs->data, NULL);
   12436                 : 
   12437 GIC          65 :     if (cast->dobj.dump & DUMP_COMPONENT_DEFINITION)
   12438 CBC          65 :         ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId,
   12439              65 :                      ARCHIVE_OPTS(.tag = labelq->data,
   12440                 :                                   .description = "CAST",
   12441 ECB             :                                   .section = SECTION_PRE_DATA,
   12442                 :                                   .createStmt = defqry->data,
   12443                 :                                   .dropStmt = delqry->data));
   12444                 : 
   12445                 :     /* Dump Cast Comments */
   12446 CBC          65 :     if (cast->dobj.dump & DUMP_COMPONENT_COMMENT)
   12447 UIC           0 :         dumpComment(fout, "CAST", castargs->data,
   12448 ECB             :                     NULL, "",
   12449 UIC           0 :                     cast->dobj.catId, 0, cast->dobj.dumpId);
   12450                 : 
   12451 GIC          65 :     destroyPQExpBuffer(defqry);
   12452 CBC          65 :     destroyPQExpBuffer(delqry);
   12453 GIC          65 :     destroyPQExpBuffer(labelq);
   12454 CBC          65 :     destroyPQExpBuffer(castargs);
   12455 ECB             : }
   12456                 : 
   12457 EUB             : /*
   12458                 :  * Dump a transform
   12459                 :  */
   12460                 : static void
   12461 GIC          43 : dumpTransform(Archive *fout, const TransformInfo *transform)
   12462 ECB             : {
   12463 GIC          43 :     DumpOptions *dopt = fout->dopt;
   12464 ECB             :     PQExpBuffer defqry;
   12465                 :     PQExpBuffer delqry;
   12466 EUB             :     PQExpBuffer labelq;
   12467                 :     PQExpBuffer transformargs;
   12468 GIC          43 :     FuncInfo   *fromsqlFuncInfo = NULL;
   12469 GBC          43 :     FuncInfo   *tosqlFuncInfo = NULL;
   12470 EUB             :     char       *lanname;
   12471                 :     const char *transformType;
   12472                 : 
   12473                 :     /* Do nothing in data-only dump */
   12474 GBC          43 :     if (dopt->dataOnly)
   12475               3 :         return;
   12476 EUB             : 
   12477                 :     /* Cannot dump if we don't have the transform functions' info */
   12478 GIC          40 :     if (OidIsValid(transform->trffromsql))
   12479                 :     {
   12480 CBC          40 :         fromsqlFuncInfo = findFuncByOid(transform->trffromsql);
   12481              40 :         if (fromsqlFuncInfo == NULL)
   12482 UIC           0 :             pg_fatal("could not find function definition for function with OID %u",
   12483 ECB             :                      transform->trffromsql);
   12484                 :     }
   12485 CBC          40 :     if (OidIsValid(transform->trftosql))
   12486 ECB             :     {
   12487 CBC          40 :         tosqlFuncInfo = findFuncByOid(transform->trftosql);
   12488              40 :         if (tosqlFuncInfo == NULL)
   12489 UBC           0 :             pg_fatal("could not find function definition for function with OID %u",
   12490 EUB             :                      transform->trftosql);
   12491                 :     }
   12492                 : 
   12493 GIC          40 :     defqry = createPQExpBuffer();
   12494 CBC          40 :     delqry = createPQExpBuffer();
   12495              40 :     labelq = createPQExpBuffer();
   12496 GIC          40 :     transformargs = createPQExpBuffer();
   12497 ECB             : 
   12498 GBC          40 :     lanname = get_language_name(fout, transform->trflang);
   12499 GIC          40 :     transformType = getFormattedTypeName(fout, transform->trftype, zeroAsNone);
   12500 ECB             : 
   12501 CBC          40 :     appendPQExpBuffer(delqry, "DROP TRANSFORM FOR %s LANGUAGE %s;\n",
   12502                 :                       transformType, lanname);
   12503                 : 
   12504 GIC          40 :     appendPQExpBuffer(defqry, "CREATE TRANSFORM FOR %s LANGUAGE %s (",
   12505                 :                       transformType, lanname);
   12506                 : 
   12507              40 :     if (!transform->trffromsql && !transform->trftosql)
   12508 LBC           0 :         pg_log_warning("bogus transform definition, at least one of trffromsql and trftosql should be nonzero");
   12509                 : 
   12510 CBC          40 :     if (transform->trffromsql)
   12511                 :     {
   12512 GIC          40 :         if (fromsqlFuncInfo)
   12513 ECB             :         {
   12514 GBC          40 :             char       *fsig = format_function_signature(fout, fromsqlFuncInfo, true);
   12515                 : 
   12516                 :             /*
   12517                 :              * Always qualify the function name (format_function_signature
   12518                 :              * won't qualify it).
   12519 ECB             :              */
   12520 CBC          40 :             appendPQExpBuffer(defqry, "FROM SQL WITH FUNCTION %s.%s",
   12521 GIC          40 :                               fmtId(fromsqlFuncInfo->dobj.namespace->dobj.name), fsig);
   12522              40 :             free(fsig);
   12523 ECB             :         }
   12524                 :         else
   12525 UBC           0 :             pg_log_warning("bogus value in pg_transform.trffromsql field");
   12526                 :     }
   12527 ECB             : 
   12528 GIC          40 :     if (transform->trftosql)
   12529                 :     {
   12530 CBC          40 :         if (transform->trffromsql)
   12531 GIC          40 :             appendPQExpBufferStr(defqry, ", ");
   12532                 : 
   12533 CBC          40 :         if (tosqlFuncInfo)
   12534                 :         {
   12535              40 :             char       *fsig = format_function_signature(fout, tosqlFuncInfo, true);
   12536 ECB             : 
   12537                 :             /*
   12538                 :              * Always qualify the function name (format_function_signature
   12539 EUB             :              * won't qualify it).
   12540                 :              */
   12541 GIC          40 :             appendPQExpBuffer(defqry, "TO SQL WITH FUNCTION %s.%s",
   12542              40 :                               fmtId(tosqlFuncInfo->dobj.namespace->dobj.name), fsig);
   12543              40 :             free(fsig);
   12544 ECB             :         }
   12545                 :         else
   12546 UIC           0 :             pg_log_warning("bogus value in pg_transform.trftosql field");
   12547 ECB             :     }
   12548                 : 
   12549 GIC          40 :     appendPQExpBufferStr(defqry, ");\n");
   12550 ECB             : 
   12551 CBC          40 :     appendPQExpBuffer(labelq, "TRANSFORM FOR %s LANGUAGE %s",
   12552 EUB             :                       transformType, lanname);
   12553 ECB             : 
   12554 CBC          40 :     appendPQExpBuffer(transformargs, "FOR %s LANGUAGE %s",
   12555                 :                       transformType, lanname);
   12556                 : 
   12557 GIC          40 :     if (dopt->binary_upgrade)
   12558               2 :         binary_upgrade_extension_member(defqry, &transform->dobj,
   12559               2 :                                         "TRANSFORM", transformargs->data, NULL);
   12560                 : 
   12561              40 :     if (transform->dobj.dump & DUMP_COMPONENT_DEFINITION)
   12562              40 :         ArchiveEntry(fout, transform->dobj.catId, transform->dobj.dumpId,
   12563              40 :                      ARCHIVE_OPTS(.tag = labelq->data,
   12564                 :                                   .description = "TRANSFORM",
   12565                 :                                   .section = SECTION_PRE_DATA,
   12566                 :                                   .createStmt = defqry->data,
   12567                 :                                   .dropStmt = delqry->data,
   12568                 :                                   .deps = transform->dobj.dependencies,
   12569                 :                                   .nDeps = transform->dobj.nDeps));
   12570                 : 
   12571 ECB             :     /* Dump Transform Comments */
   12572 GIC          40 :     if (transform->dobj.dump & DUMP_COMPONENT_COMMENT)
   12573 UIC           0 :         dumpComment(fout, "TRANSFORM", transformargs->data,
   12574                 :                     NULL, "",
   12575               0 :                     transform->dobj.catId, 0, transform->dobj.dumpId);
   12576                 : 
   12577 GIC          40 :     free(lanname);
   12578 CBC          40 :     destroyPQExpBuffer(defqry);
   12579 GIC          40 :     destroyPQExpBuffer(delqry);
   12580 CBC          40 :     destroyPQExpBuffer(labelq);
   12581 GIC          40 :     destroyPQExpBuffer(transformargs);
   12582 ECB             : }
   12583                 : 
   12584                 : 
   12585                 : /*
   12586                 :  * dumpOpr
   12587                 :  *    write out a single operator definition
   12588                 :  */
   12589                 : static void
   12590 CBC         108 : dumpOpr(Archive *fout, const OprInfo *oprinfo)
   12591                 : {
   12592 GIC         108 :     DumpOptions *dopt = fout->dopt;
   12593 ECB             :     PQExpBuffer query;
   12594                 :     PQExpBuffer q;
   12595                 :     PQExpBuffer delq;
   12596                 :     PQExpBuffer oprid;
   12597                 :     PQExpBuffer details;
   12598                 :     PGresult   *res;
   12599                 :     int         i_oprkind;
   12600                 :     int         i_oprcode;
   12601                 :     int         i_oprleft;
   12602                 :     int         i_oprright;
   12603                 :     int         i_oprcom;
   12604                 :     int         i_oprnegate;
   12605                 :     int         i_oprrest;
   12606                 :     int         i_oprjoin;
   12607                 :     int         i_oprcanmerge;
   12608                 :     int         i_oprcanhash;
   12609                 :     char       *oprkind;
   12610                 :     char       *oprcode;
   12611                 :     char       *oprleft;
   12612                 :     char       *oprright;
   12613                 :     char       *oprcom;
   12614                 :     char       *oprnegate;
   12615                 :     char       *oprrest;
   12616 EUB             :     char       *oprjoin;
   12617                 :     char       *oprcanmerge;
   12618                 :     char       *oprcanhash;
   12619                 :     char       *oprregproc;
   12620 ECB             :     char       *oprref;
   12621 EUB             : 
   12622                 :     /* Do nothing in data-only dump */
   12623 GBC         108 :     if (dopt->dataOnly)
   12624 GIC           3 :         return;
   12625 ECB             : 
   12626                 :     /*
   12627                 :      * some operators are invalid because they were the result of user
   12628                 :      * defining operators before commutators exist
   12629                 :      */
   12630 GIC         105 :     if (!OidIsValid(oprinfo->oprcode))
   12631 CBC          14 :         return;
   12632                 : 
   12633              91 :     query = createPQExpBuffer();
   12634              91 :     q = createPQExpBuffer();
   12635              91 :     delq = createPQExpBuffer();
   12636              91 :     oprid = createPQExpBuffer();
   12637              91 :     details = createPQExpBuffer();
   12638 ECB             : 
   12639 CBC          91 :     if (!fout->is_prepared[PREPQUERY_DUMPOPR])
   12640 ECB             :     {
   12641                 :         /* Set up query for operator-specific details */
   12642 GIC          41 :         appendPQExpBufferStr(query,
   12643                 :                              "PREPARE dumpOpr(pg_catalog.oid) AS\n"
   12644                 :                              "SELECT oprkind, "
   12645                 :                              "oprcode::pg_catalog.regprocedure, "
   12646                 :                              "oprleft::pg_catalog.regtype, "
   12647                 :                              "oprright::pg_catalog.regtype, "
   12648                 :                              "oprcom, "
   12649 ECB             :                              "oprnegate, "
   12650                 :                              "oprrest::pg_catalog.regprocedure, "
   12651                 :                              "oprjoin::pg_catalog.regprocedure, "
   12652                 :                              "oprcanmerge, oprcanhash "
   12653                 :                              "FROM pg_catalog.pg_operator "
   12654                 :                              "WHERE oid = $1");
   12655                 : 
   12656 CBC          41 :         ExecuteSqlStatement(fout, query->data);
   12657                 : 
   12658 GIC          41 :         fout->is_prepared[PREPQUERY_DUMPOPR] = true;
   12659                 :     }
   12660                 : 
   12661 CBC          91 :     printfPQExpBuffer(query,
   12662 ECB             :                       "EXECUTE dumpOpr('%u')",
   12663 GIC          91 :                       oprinfo->dobj.catId.oid);
   12664                 : 
   12665 CBC          91 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   12666                 : 
   12667              91 :     i_oprkind = PQfnumber(res, "oprkind");
   12668              91 :     i_oprcode = PQfnumber(res, "oprcode");
   12669 GBC          91 :     i_oprleft = PQfnumber(res, "oprleft");
   12670 GIC          91 :     i_oprright = PQfnumber(res, "oprright");
   12671              91 :     i_oprcom = PQfnumber(res, "oprcom");
   12672              91 :     i_oprnegate = PQfnumber(res, "oprnegate");
   12673 CBC          91 :     i_oprrest = PQfnumber(res, "oprrest");
   12674              91 :     i_oprjoin = PQfnumber(res, "oprjoin");
   12675              91 :     i_oprcanmerge = PQfnumber(res, "oprcanmerge");
   12676              91 :     i_oprcanhash = PQfnumber(res, "oprcanhash");
   12677                 : 
   12678              91 :     oprkind = PQgetvalue(res, 0, i_oprkind);
   12679              91 :     oprcode = PQgetvalue(res, 0, i_oprcode);
   12680              91 :     oprleft = PQgetvalue(res, 0, i_oprleft);
   12681 GIC          91 :     oprright = PQgetvalue(res, 0, i_oprright);
   12682              91 :     oprcom = PQgetvalue(res, 0, i_oprcom);
   12683 CBC          91 :     oprnegate = PQgetvalue(res, 0, i_oprnegate);
   12684 GIC          91 :     oprrest = PQgetvalue(res, 0, i_oprrest);
   12685              91 :     oprjoin = PQgetvalue(res, 0, i_oprjoin);
   12686 CBC          91 :     oprcanmerge = PQgetvalue(res, 0, i_oprcanmerge);
   12687 GIC          91 :     oprcanhash = PQgetvalue(res, 0, i_oprcanhash);
   12688 ECB             : 
   12689                 :     /* In PG14 upwards postfix operator support does not exist anymore. */
   12690 CBC          91 :     if (strcmp(oprkind, "r") == 0)
   12691 UBC           0 :         pg_log_warning("postfix operators are not supported anymore (operator \"%s\")",
   12692 EUB             :                        oprcode);
   12693                 : 
   12694 CBC          91 :     oprregproc = convertRegProcReference(oprcode);
   12695              91 :     if (oprregproc)
   12696                 :     {
   12697              91 :         appendPQExpBuffer(details, "    FUNCTION = %s", oprregproc);
   12698 GIC          91 :         free(oprregproc);
   12699                 :     }
   12700                 : 
   12701              91 :     appendPQExpBuffer(oprid, "%s (",
   12702              91 :                       oprinfo->dobj.name);
   12703 ECB             : 
   12704                 :     /*
   12705                 :      * right unary means there's a left arg and left unary means there's a
   12706                 :      * right arg.  (Although the "r" case is dead code for PG14 and later,
   12707                 :      * continue to support it in case we're dumping from an old server.)
   12708 EUB             :      */
   12709 CBC          91 :     if (strcmp(oprkind, "r") == 0 ||
   12710 GBC          91 :         strcmp(oprkind, "b") == 0)
   12711 EUB             :     {
   12712 GIC          71 :         appendPQExpBuffer(details, ",\n    LEFTARG = %s", oprleft);
   12713              71 :         appendPQExpBufferStr(oprid, oprleft);
   12714 ECB             :     }
   12715                 :     else
   12716 CBC          20 :         appendPQExpBufferStr(oprid, "NONE");
   12717 ECB             : 
   12718 CBC          91 :     if (strcmp(oprkind, "l") == 0 ||
   12719 GIC          71 :         strcmp(oprkind, "b") == 0)
   12720 ECB             :     {
   12721 GIC          91 :         appendPQExpBuffer(details, ",\n    RIGHTARG = %s", oprright);
   12722              91 :         appendPQExpBuffer(oprid, ", %s)", oprright);
   12723 ECB             :     }
   12724                 :     else
   12725 UIC           0 :         appendPQExpBufferStr(oprid, ", NONE)");
   12726 ECB             : 
   12727 CBC          91 :     oprref = getFormattedOperatorName(oprcom);
   12728              91 :     if (oprref)
   12729                 :     {
   12730              20 :         appendPQExpBuffer(details, ",\n    COMMUTATOR = %s", oprref);
   12731              20 :         free(oprref);
   12732 ECB             :     }
   12733                 : 
   12734 GIC          91 :     oprref = getFormattedOperatorName(oprnegate);
   12735              91 :     if (oprref)
   12736                 :     {
   12737               5 :         appendPQExpBuffer(details, ",\n    NEGATOR = %s", oprref);
   12738               5 :         free(oprref);
   12739 ECB             :     }
   12740 EUB             : 
   12741 GIC          91 :     if (strcmp(oprcanmerge, "t") == 0)
   12742 GBC          20 :         appendPQExpBufferStr(details, ",\n    MERGES");
   12743                 : 
   12744 CBC          91 :     if (strcmp(oprcanhash, "t") == 0)
   12745 LBC           0 :         appendPQExpBufferStr(details, ",\n    HASHES");
   12746 ECB             : 
   12747 CBC          91 :     oprregproc = convertRegProcReference(oprrest);
   12748 GIC          91 :     if (oprregproc)
   12749                 :     {
   12750              20 :         appendPQExpBuffer(details, ",\n    RESTRICT = %s", oprregproc);
   12751              20 :         free(oprregproc);
   12752                 :     }
   12753                 : 
   12754 CBC          91 :     oprregproc = convertRegProcReference(oprjoin);
   12755 GIC          91 :     if (oprregproc)
   12756 ECB             :     {
   12757 GIC          20 :         appendPQExpBuffer(details, ",\n    JOIN = %s", oprregproc);
   12758              20 :         free(oprregproc);
   12759                 :     }
   12760                 : 
   12761 CBC          91 :     appendPQExpBuffer(delq, "DROP OPERATOR %s.%s;\n",
   12762              91 :                       fmtId(oprinfo->dobj.namespace->dobj.name),
   12763                 :                       oprid->data);
   12764                 : 
   12765 GIC          91 :     appendPQExpBuffer(q, "CREATE OPERATOR %s.%s (\n%s\n);\n",
   12766              91 :                       fmtId(oprinfo->dobj.namespace->dobj.name),
   12767 CBC          91 :                       oprinfo->dobj.name, details->data);
   12768 ECB             : 
   12769 GIC          91 :     if (dopt->binary_upgrade)
   12770              12 :         binary_upgrade_extension_member(q, &oprinfo->dobj,
   12771 CBC          12 :                                         "OPERATOR", oprid->data,
   12772 GIC          12 :                                         oprinfo->dobj.namespace->dobj.name);
   12773 ECB             : 
   12774 CBC          91 :     if (oprinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   12775 GBC          91 :         ArchiveEntry(fout, oprinfo->dobj.catId, oprinfo->dobj.dumpId,
   12776 GIC          91 :                      ARCHIVE_OPTS(.tag = oprinfo->dobj.name,
   12777                 :                                   .namespace = oprinfo->dobj.namespace->dobj.name,
   12778 ECB             :                                   .owner = oprinfo->rolname,
   12779                 :                                   .description = "OPERATOR",
   12780                 :                                   .section = SECTION_PRE_DATA,
   12781                 :                                   .createStmt = q->data,
   12782 EUB             :                                   .dropStmt = delq->data));
   12783                 : 
   12784                 :     /* Dump Operator Comments */
   12785 GIC          91 :     if (oprinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   12786 LBC           0 :         dumpComment(fout, "OPERATOR", oprid->data,
   12787               0 :                     oprinfo->dobj.namespace->dobj.name, oprinfo->rolname,
   12788               0 :                     oprinfo->dobj.catId, 0, oprinfo->dobj.dumpId);
   12789 ECB             : 
   12790 GIC          91 :     PQclear(res);
   12791 ECB             : 
   12792 CBC          91 :     destroyPQExpBuffer(query);
   12793 GIC          91 :     destroyPQExpBuffer(q);
   12794 CBC          91 :     destroyPQExpBuffer(delq);
   12795 GIC          91 :     destroyPQExpBuffer(oprid);
   12796              91 :     destroyPQExpBuffer(details);
   12797 ECB             : }
   12798                 : 
   12799                 : /*
   12800                 :  * Convert a function reference obtained from pg_operator
   12801 EUB             :  *
   12802                 :  * Returns allocated string of what to print, or NULL if function references
   12803 ECB             :  * is InvalidOid. Returned string is expected to be free'd by the caller.
   12804                 :  *
   12805                 :  * The input is a REGPROCEDURE display; we have to strip the argument-types
   12806                 :  * part.
   12807                 :  */
   12808                 : static char *
   12809 GIC         273 : convertRegProcReference(const char *proc)
   12810                 : {
   12811                 :     char       *name;
   12812                 :     char       *paren;
   12813 ECB             :     bool        inquote;
   12814                 : 
   12815                 :     /* In all cases "-" means a null reference */
   12816 GIC         273 :     if (strcmp(proc, "-") == 0)
   12817             142 :         return NULL;
   12818 EUB             : 
   12819 GIC         131 :     name = pg_strdup(proc);
   12820                 :     /* find non-double-quoted left paren */
   12821 CBC         131 :     inquote = false;
   12822 GIC        1462 :     for (paren = name; *paren; paren++)
   12823 ECB             :     {
   12824 CBC        1462 :         if (*paren == '(' && !inquote)
   12825                 :         {
   12826             131 :             *paren = '\0';
   12827 GIC         131 :             break;
   12828 ECB             :         }
   12829 GIC        1331 :         if (*paren == '"')
   12830              50 :             inquote = !inquote;
   12831                 :     }
   12832             131 :     return name;
   12833                 : }
   12834 ECB             : 
   12835                 : /*
   12836                 :  * getFormattedOperatorName - retrieve the operator name for the
   12837                 :  * given operator OID (presented in string form).
   12838                 :  *
   12839 EUB             :  * Returns an allocated string, or NULL if the given OID is invalid.
   12840                 :  * Caller is responsible for free'ing result string.
   12841                 :  *
   12842 ECB             :  * What we produce has the format "OPERATOR(schema.oprname)".  This is only
   12843                 :  * useful in commands where the operator's argument types can be inferred from
   12844                 :  * context.  We always schema-qualify the name, though.  The predecessor to
   12845                 :  * this code tried to skip the schema qualification if possible, but that led
   12846                 :  * to wrong results in corner cases, such as if an operator and its negator
   12847                 :  * are in different schemas.
   12848                 :  */
   12849                 : static char *
   12850 CBC         470 : getFormattedOperatorName(const char *oproid)
   12851 ECB             : {
   12852                 :     OprInfo    *oprInfo;
   12853                 : 
   12854                 :     /* In all cases "0" means a null reference */
   12855 CBC         470 :     if (strcmp(oproid, "0") == 0)
   12856             445 :         return NULL;
   12857                 : 
   12858 GIC          25 :     oprInfo = findOprByOid(atooid(oproid));
   12859              25 :     if (oprInfo == NULL)
   12860                 :     {
   12861 UIC           0 :         pg_log_warning("could not find operator with OID %s",
   12862                 :                        oproid);
   12863               0 :         return NULL;
   12864                 :     }
   12865 ECB             : 
   12866 GBC          25 :     return psprintf("OPERATOR(%s.%s)",
   12867 GIC          25 :                     fmtId(oprInfo->dobj.namespace->dobj.name),
   12868 EUB             :                     oprInfo->dobj.name);
   12869                 : }
   12870 ECB             : 
   12871                 : /*
   12872                 :  * Convert a function OID obtained from pg_ts_parser or pg_ts_template
   12873                 :  *
   12874                 :  * It is sufficient to use REGPROC rather than REGPROCEDURE, since the
   12875                 :  * argument lists of these functions are predetermined.  Note that the
   12876                 :  * caller should ensure we are in the proper schema, because the results
   12877                 :  * are search path dependent!
   12878                 :  */
   12879                 : static char *
   12880 GIC         180 : convertTSFunction(Archive *fout, Oid funcOid)
   12881                 : {
   12882                 :     char       *result;
   12883 ECB             :     char        query[128];
   12884                 :     PGresult   *res;
   12885                 : 
   12886 GIC         180 :     snprintf(query, sizeof(query),
   12887                 :              "SELECT '%u'::pg_catalog.regproc", funcOid);
   12888             180 :     res = ExecuteSqlQueryForSingleRow(fout, query);
   12889                 : 
   12890             180 :     result = pg_strdup(PQgetvalue(res, 0, 0));
   12891                 : 
   12892             180 :     PQclear(res);
   12893                 : 
   12894             180 :     return result;
   12895                 : }
   12896                 : 
   12897                 : /*
   12898                 :  * dumpAccessMethod
   12899                 :  *    write out a single access method definition
   12900                 :  */
   12901                 : static void
   12902              82 : dumpAccessMethod(Archive *fout, const AccessMethodInfo *aminfo)
   12903                 : {
   12904              82 :     DumpOptions *dopt = fout->dopt;
   12905                 :     PQExpBuffer q;
   12906                 :     PQExpBuffer delq;
   12907                 :     char       *qamname;
   12908                 : 
   12909                 :     /* Do nothing in data-only dump */
   12910              82 :     if (dopt->dataOnly)
   12911               6 :         return;
   12912                 : 
   12913              76 :     q = createPQExpBuffer();
   12914              76 :     delq = createPQExpBuffer();
   12915                 : 
   12916 CBC          76 :     qamname = pg_strdup(fmtId(aminfo->dobj.name));
   12917 ECB             : 
   12918 GIC          76 :     appendPQExpBuffer(q, "CREATE ACCESS METHOD %s ", qamname);
   12919                 : 
   12920              76 :     switch (aminfo->amtype)
   12921                 :     {
   12922              36 :         case AMTYPE_INDEX:
   12923 CBC          36 :             appendPQExpBufferStr(q, "TYPE INDEX ");
   12924              36 :             break;
   12925 GIC          40 :         case AMTYPE_TABLE:
   12926 CBC          40 :             appendPQExpBufferStr(q, "TYPE TABLE ");
   12927              40 :             break;
   12928 LBC           0 :         default:
   12929               0 :             pg_log_warning("invalid type \"%c\" of access method \"%s\"",
   12930 ECB             :                            aminfo->amtype, qamname);
   12931 UIC           0 :             destroyPQExpBuffer(q);
   12932 LBC           0 :             destroyPQExpBuffer(delq);
   12933 UIC           0 :             free(qamname);
   12934               0 :             return;
   12935 ECB             :     }
   12936                 : 
   12937 GIC          76 :     appendPQExpBuffer(q, "HANDLER %s;\n", aminfo->amhandler);
   12938                 : 
   12939              76 :     appendPQExpBuffer(delq, "DROP ACCESS METHOD %s;\n",
   12940                 :                       qamname);
   12941                 : 
   12942              76 :     if (dopt->binary_upgrade)
   12943               4 :         binary_upgrade_extension_member(q, &aminfo->dobj,
   12944                 :                                         "ACCESS METHOD", qamname, NULL);
   12945                 : 
   12946              76 :     if (aminfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   12947              76 :         ArchiveEntry(fout, aminfo->dobj.catId, aminfo->dobj.dumpId,
   12948              76 :                      ARCHIVE_OPTS(.tag = aminfo->dobj.name,
   12949 ECB             :                                   .description = "ACCESS METHOD",
   12950                 :                                   .section = SECTION_PRE_DATA,
   12951                 :                                   .createStmt = q->data,
   12952                 :                                   .dropStmt = delq->data));
   12953                 : 
   12954                 :     /* Dump Access Method Comments */
   12955 GIC          76 :     if (aminfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   12956 LBC           0 :         dumpComment(fout, "ACCESS METHOD", qamname,
   12957                 :                     NULL, "",
   12958               0 :                     aminfo->dobj.catId, 0, aminfo->dobj.dumpId);
   12959                 : 
   12960 CBC          76 :     destroyPQExpBuffer(q);
   12961              76 :     destroyPQExpBuffer(delq);
   12962              76 :     free(qamname);
   12963 ECB             : }
   12964                 : 
   12965                 : /*
   12966                 :  * dumpOpclass
   12967                 :  *    write out a single operator class definition
   12968                 :  */
   12969                 : static void
   12970 GIC         132 : dumpOpclass(Archive *fout, const OpclassInfo *opcinfo)
   12971 ECB             : {
   12972 CBC         132 :     DumpOptions *dopt = fout->dopt;
   12973 ECB             :     PQExpBuffer query;
   12974                 :     PQExpBuffer q;
   12975                 :     PQExpBuffer delq;
   12976                 :     PQExpBuffer nameusing;
   12977                 :     PGresult   *res;
   12978                 :     int         ntups;
   12979                 :     int         i_opcintype;
   12980                 :     int         i_opckeytype;
   12981                 :     int         i_opcdefault;
   12982                 :     int         i_opcfamily;
   12983                 :     int         i_opcfamilyname;
   12984 EUB             :     int         i_opcfamilynsp;
   12985                 :     int         i_amname;
   12986                 :     int         i_amopstrategy;
   12987 ECB             :     int         i_amopopr;
   12988                 :     int         i_sortfamily;
   12989                 :     int         i_sortfamilynsp;
   12990                 :     int         i_amprocnum;
   12991                 :     int         i_amproc;
   12992                 :     int         i_amproclefttype;
   12993                 :     int         i_amprocrighttype;
   12994                 :     char       *opcintype;
   12995                 :     char       *opckeytype;
   12996                 :     char       *opcdefault;
   12997                 :     char       *opcfamily;
   12998                 :     char       *opcfamilyname;
   12999                 :     char       *opcfamilynsp;
   13000                 :     char       *amname;
   13001                 :     char       *amopstrategy;
   13002                 :     char       *amopopr;
   13003                 :     char       *sortfamily;
   13004                 :     char       *sortfamilynsp;
   13005                 :     char       *amprocnum;
   13006                 :     char       *amproc;
   13007                 :     char       *amproclefttype;
   13008                 :     char       *amprocrighttype;
   13009                 :     bool        needComma;
   13010                 :     int         i;
   13011                 : 
   13012                 :     /* Do nothing in data-only dump */
   13013 GIC         132 :     if (dopt->dataOnly)
   13014 CBC           9 :         return;
   13015 ECB             : 
   13016 GIC         123 :     query = createPQExpBuffer();
   13017             123 :     q = createPQExpBuffer();
   13018 GBC         123 :     delq = createPQExpBuffer();
   13019 GIC         123 :     nameusing = createPQExpBuffer();
   13020 ECB             : 
   13021                 :     /* Get additional fields from the pg_opclass row */
   13022 GIC         123 :     appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
   13023 ECB             :                       "opckeytype::pg_catalog.regtype, "
   13024                 :                       "opcdefault, opcfamily, "
   13025                 :                       "opfname AS opcfamilyname, "
   13026                 :                       "nspname AS opcfamilynsp, "
   13027                 :                       "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
   13028                 :                       "FROM pg_catalog.pg_opclass c "
   13029                 :                       "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = opcfamily "
   13030                 :                       "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
   13031                 :                       "WHERE c.oid = '%u'::pg_catalog.oid",
   13032 GIC         123 :                       opcinfo->dobj.catId.oid);
   13033                 : 
   13034 CBC         123 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   13035 ECB             : 
   13036 GIC         123 :     i_opcintype = PQfnumber(res, "opcintype");
   13037 CBC         123 :     i_opckeytype = PQfnumber(res, "opckeytype");
   13038 GBC         123 :     i_opcdefault = PQfnumber(res, "opcdefault");
   13039 GIC         123 :     i_opcfamily = PQfnumber(res, "opcfamily");
   13040 CBC         123 :     i_opcfamilyname = PQfnumber(res, "opcfamilyname");
   13041             123 :     i_opcfamilynsp = PQfnumber(res, "opcfamilynsp");
   13042 GIC         123 :     i_amname = PQfnumber(res, "amname");
   13043 ECB             : 
   13044                 :     /* opcintype may still be needed after we PQclear res */
   13045 GIC         123 :     opcintype = pg_strdup(PQgetvalue(res, 0, i_opcintype));
   13046             123 :     opckeytype = PQgetvalue(res, 0, i_opckeytype);
   13047 CBC         123 :     opcdefault = PQgetvalue(res, 0, i_opcdefault);
   13048 ECB             :     /* opcfamily will still be needed after we PQclear res */
   13049 GIC         123 :     opcfamily = pg_strdup(PQgetvalue(res, 0, i_opcfamily));
   13050 CBC         123 :     opcfamilyname = PQgetvalue(res, 0, i_opcfamilyname);
   13051             123 :     opcfamilynsp = PQgetvalue(res, 0, i_opcfamilynsp);
   13052                 :     /* amname will still be needed after we PQclear res */
   13053 GIC         123 :     amname = pg_strdup(PQgetvalue(res, 0, i_amname));
   13054 ECB             : 
   13055 CBC         123 :     appendPQExpBuffer(delq, "DROP OPERATOR CLASS %s",
   13056 GIC         123 :                       fmtQualifiedDumpable(opcinfo));
   13057             123 :     appendPQExpBuffer(delq, " USING %s;\n",
   13058 ECB             :                       fmtId(amname));
   13059                 : 
   13060                 :     /* Build the fixed portion of the CREATE command */
   13061 GIC         123 :     appendPQExpBuffer(q, "CREATE OPERATOR CLASS %s\n    ",
   13062 CBC         123 :                       fmtQualifiedDumpable(opcinfo));
   13063             123 :     if (strcmp(opcdefault, "t") == 0)
   13064 LBC           0 :         appendPQExpBufferStr(q, "DEFAULT ");
   13065 CBC         123 :     appendPQExpBuffer(q, "FOR TYPE %s USING %s",
   13066                 :                       opcintype,
   13067 ECB             :                       fmtId(amname));
   13068 CBC         123 :     if (strlen(opcfamilyname) > 0)
   13069 ECB             :     {
   13070 GIC         123 :         appendPQExpBufferStr(q, " FAMILY ");
   13071             123 :         appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp));
   13072             123 :         appendPQExpBufferStr(q, fmtId(opcfamilyname));
   13073                 :     }
   13074             123 :     appendPQExpBufferStr(q, " AS\n    ");
   13075                 : 
   13076             123 :     needComma = false;
   13077                 : 
   13078 CBC         123 :     if (strcmp(opckeytype, "-") != 0)
   13079 EUB             :     {
   13080 UBC           0 :         appendPQExpBuffer(q, "STORAGE %s",
   13081 EUB             :                           opckeytype);
   13082 UIC           0 :         needComma = true;
   13083 ECB             :     }
   13084                 : 
   13085 CBC         123 :     PQclear(res);
   13086 ECB             : 
   13087                 :     /*
   13088                 :      * Now fetch and print the OPERATOR entries (pg_amop rows).
   13089                 :      *
   13090                 :      * Print only those opfamily members that are tied to the opclass by
   13091                 :      * pg_depend entries.
   13092                 :      */
   13093 GIC         123 :     resetPQExpBuffer(query);
   13094             123 :     appendPQExpBuffer(query, "SELECT amopstrategy, "
   13095                 :                       "amopopr::pg_catalog.regoperator, "
   13096                 :                       "opfname AS sortfamily, "
   13097                 :                       "nspname AS sortfamilynsp "
   13098                 :                       "FROM pg_catalog.pg_amop ao JOIN pg_catalog.pg_depend ON "
   13099                 :                       "(classid = 'pg_catalog.pg_amop'::pg_catalog.regclass AND objid = ao.oid) "
   13100                 :                       "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = amopsortfamily "
   13101                 :                       "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
   13102 ECB             :                       "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
   13103                 :                       "AND refobjid = '%u'::pg_catalog.oid "
   13104                 :                       "AND amopfamily = '%s'::pg_catalog.oid "
   13105                 :                       "ORDER BY amopstrategy",
   13106 GIC         123 :                       opcinfo->dobj.catId.oid,
   13107                 :                       opcfamily);
   13108                 : 
   13109 CBC         123 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   13110 ECB             : 
   13111 GIC         123 :     ntups = PQntuples(res);
   13112 ECB             : 
   13113 GIC         123 :     i_amopstrategy = PQfnumber(res, "amopstrategy");
   13114 CBC         123 :     i_amopopr = PQfnumber(res, "amopopr");
   13115             123 :     i_sortfamily = PQfnumber(res, "sortfamily");
   13116 GIC         123 :     i_sortfamilynsp = PQfnumber(res, "sortfamilynsp");
   13117 ECB             : 
   13118 GIC         349 :     for (i = 0; i < ntups; i++)
   13119 ECB             :     {
   13120 CBC         226 :         amopstrategy = PQgetvalue(res, i, i_amopstrategy);
   13121 GIC         226 :         amopopr = PQgetvalue(res, i, i_amopopr);
   13122 CBC         226 :         sortfamily = PQgetvalue(res, i, i_sortfamily);
   13123             226 :         sortfamilynsp = PQgetvalue(res, i, i_sortfamilynsp);
   13124                 : 
   13125             226 :         if (needComma)
   13126 GIC         144 :             appendPQExpBufferStr(q, " ,\n    ");
   13127                 : 
   13128             226 :         appendPQExpBuffer(q, "OPERATOR %s %s",
   13129                 :                           amopstrategy, amopopr);
   13130                 : 
   13131             226 :         if (strlen(sortfamily) > 0)
   13132                 :         {
   13133 UIC           0 :             appendPQExpBufferStr(q, " FOR ORDER BY ");
   13134               0 :             appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
   13135               0 :             appendPQExpBufferStr(q, fmtId(sortfamily));
   13136                 :         }
   13137                 : 
   13138 GIC         226 :         needComma = true;
   13139                 :     }
   13140                 : 
   13141             123 :     PQclear(res);
   13142                 : 
   13143 ECB             :     /*
   13144                 :      * Now fetch and print the FUNCTION entries (pg_amproc rows).
   13145                 :      *
   13146                 :      * Print only those opfamily members that are tied to the opclass by
   13147                 :      * pg_depend entries.
   13148                 :      *
   13149                 :      * We print the amproclefttype/amprocrighttype even though in most cases
   13150                 :      * the backend could deduce the right values, because of the corner case
   13151                 :      * of a btree sort support function for a cross-type comparison.
   13152                 :      */
   13153 GIC         123 :     resetPQExpBuffer(query);
   13154 EUB             : 
   13155 GIC         123 :     appendPQExpBuffer(query, "SELECT amprocnum, "
   13156 EUB             :                       "amproc::pg_catalog.regprocedure, "
   13157                 :                       "amproclefttype::pg_catalog.regtype, "
   13158                 :                       "amprocrighttype::pg_catalog.regtype "
   13159 ECB             :                       "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
   13160                 :                       "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
   13161                 :                       "AND refobjid = '%u'::pg_catalog.oid "
   13162                 :                       "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
   13163                 :                       "AND objid = ap.oid "
   13164                 :                       "ORDER BY amprocnum",
   13165 GIC         123 :                       opcinfo->dobj.catId.oid);
   13166                 : 
   13167             123 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   13168                 : 
   13169             123 :     ntups = PQntuples(res);
   13170                 : 
   13171             123 :     i_amprocnum = PQfnumber(res, "amprocnum");
   13172             123 :     i_amproc = PQfnumber(res, "amproc");
   13173 CBC         123 :     i_amproclefttype = PQfnumber(res, "amproclefttype");
   13174 GIC         123 :     i_amprocrighttype = PQfnumber(res, "amprocrighttype");
   13175                 : 
   13176             159 :     for (i = 0; i < ntups; i++)
   13177                 :     {
   13178              36 :         amprocnum = PQgetvalue(res, i, i_amprocnum);
   13179 CBC          36 :         amproc = PQgetvalue(res, i, i_amproc);
   13180 GIC          36 :         amproclefttype = PQgetvalue(res, i, i_amproclefttype);
   13181 CBC          36 :         amprocrighttype = PQgetvalue(res, i, i_amprocrighttype);
   13182                 : 
   13183              36 :         if (needComma)
   13184 GIC          36 :             appendPQExpBufferStr(q, " ,\n    ");
   13185 ECB             : 
   13186 GIC          36 :         appendPQExpBuffer(q, "FUNCTION %s", amprocnum);
   13187 ECB             : 
   13188 GIC          36 :         if (*amproclefttype && *amprocrighttype)
   13189              36 :             appendPQExpBuffer(q, " (%s, %s)", amproclefttype, amprocrighttype);
   13190                 : 
   13191              36 :         appendPQExpBuffer(q, " %s", amproc);
   13192                 : 
   13193              36 :         needComma = true;
   13194                 :     }
   13195 ECB             : 
   13196 GIC         123 :     PQclear(res);
   13197 ECB             : 
   13198                 :     /*
   13199                 :      * If needComma is still false it means we haven't added anything after
   13200                 :      * the AS keyword.  To avoid printing broken SQL, append a dummy STORAGE
   13201                 :      * clause with the same datatype.  This isn't sanctioned by the
   13202                 :      * documentation, but actually DefineOpClass will treat it as a no-op.
   13203                 :      */
   13204 CBC         123 :     if (!needComma)
   13205 GIC          41 :         appendPQExpBuffer(q, "STORAGE %s", opcintype);
   13206 ECB             : 
   13207 CBC         123 :     appendPQExpBufferStr(q, ";\n");
   13208                 : 
   13209             123 :     appendPQExpBufferStr(nameusing, fmtId(opcinfo->dobj.name));
   13210 GIC         123 :     appendPQExpBuffer(nameusing, " USING %s",
   13211 ECB             :                       fmtId(amname));
   13212                 : 
   13213 CBC         123 :     if (dopt->binary_upgrade)
   13214 GIC           6 :         binary_upgrade_extension_member(q, &opcinfo->dobj,
   13215 CBC           6 :                                         "OPERATOR CLASS", nameusing->data,
   13216               6 :                                         opcinfo->dobj.namespace->dobj.name);
   13217 ECB             : 
   13218 CBC         123 :     if (opcinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   13219             123 :         ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId,
   13220             123 :                      ARCHIVE_OPTS(.tag = opcinfo->dobj.name,
   13221 EUB             :                                   .namespace = opcinfo->dobj.namespace->dobj.name,
   13222                 :                                   .owner = opcinfo->rolname,
   13223                 :                                   .description = "OPERATOR CLASS",
   13224                 :                                   .section = SECTION_PRE_DATA,
   13225                 :                                   .createStmt = q->data,
   13226                 :                                   .dropStmt = delq->data));
   13227                 : 
   13228                 :     /* Dump Operator Class Comments */
   13229 GIC         123 :     if (opcinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   13230 LBC           0 :         dumpComment(fout, "OPERATOR CLASS", nameusing->data,
   13231 UIC           0 :                     opcinfo->dobj.namespace->dobj.name, opcinfo->rolname,
   13232 LBC           0 :                     opcinfo->dobj.catId, 0, opcinfo->dobj.dumpId);
   13233                 : 
   13234 GIC         123 :     free(opcintype);
   13235 CBC         123 :     free(opcfamily);
   13236             123 :     free(amname);
   13237 GIC         123 :     destroyPQExpBuffer(query);
   13238             123 :     destroyPQExpBuffer(q);
   13239 CBC         123 :     destroyPQExpBuffer(delq);
   13240             123 :     destroyPQExpBuffer(nameusing);
   13241 ECB             : }
   13242                 : 
   13243                 : /*
   13244                 :  * dumpOpfamily
   13245                 :  *    write out a single operator family definition
   13246                 :  *
   13247                 :  * Note: this also dumps any "loose" operator members that aren't bound to a
   13248                 :  * specific opclass within the opfamily.
   13249 EUB             :  */
   13250                 : static void
   13251 GBC         113 : dumpOpfamily(Archive *fout, const OpfamilyInfo *opfinfo)
   13252                 : {
   13253 CBC         113 :     DumpOptions *dopt = fout->dopt;
   13254 ECB             :     PQExpBuffer query;
   13255                 :     PQExpBuffer q;
   13256                 :     PQExpBuffer delq;
   13257                 :     PQExpBuffer nameusing;
   13258                 :     PGresult   *res;
   13259                 :     PGresult   *res_ops;
   13260                 :     PGresult   *res_procs;
   13261                 :     int         ntups;
   13262                 :     int         i_amname;
   13263                 :     int         i_amopstrategy;
   13264                 :     int         i_amopopr;
   13265                 :     int         i_sortfamily;
   13266                 :     int         i_sortfamilynsp;
   13267                 :     int         i_amprocnum;
   13268                 :     int         i_amproc;
   13269                 :     int         i_amproclefttype;
   13270                 :     int         i_amprocrighttype;
   13271                 :     char       *amname;
   13272                 :     char       *amopstrategy;
   13273                 :     char       *amopopr;
   13274                 :     char       *sortfamily;
   13275                 :     char       *sortfamilynsp;
   13276                 :     char       *amprocnum;
   13277                 :     char       *amproc;
   13278                 :     char       *amproclefttype;
   13279                 :     char       *amprocrighttype;
   13280                 :     bool        needComma;
   13281                 :     int         i;
   13282                 : 
   13283                 :     /* Do nothing in data-only dump */
   13284 GIC         113 :     if (dopt->dataOnly)
   13285               6 :         return;
   13286                 : 
   13287             107 :     query = createPQExpBuffer();
   13288             107 :     q = createPQExpBuffer();
   13289             107 :     delq = createPQExpBuffer();
   13290             107 :     nameusing = createPQExpBuffer();
   13291                 : 
   13292                 :     /*
   13293                 :      * Fetch only those opfamily members that are tied directly to the
   13294                 :      * opfamily by pg_depend entries.
   13295                 :      */
   13296             107 :     appendPQExpBuffer(query, "SELECT amopstrategy, "
   13297                 :                       "amopopr::pg_catalog.regoperator, "
   13298                 :                       "opfname AS sortfamily, "
   13299                 :                       "nspname AS sortfamilynsp "
   13300                 :                       "FROM pg_catalog.pg_amop ao JOIN pg_catalog.pg_depend ON "
   13301                 :                       "(classid = 'pg_catalog.pg_amop'::pg_catalog.regclass AND objid = ao.oid) "
   13302                 :                       "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = amopsortfamily "
   13303                 :                       "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
   13304                 :                       "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
   13305                 :                       "AND refobjid = '%u'::pg_catalog.oid "
   13306 ECB             :                       "AND amopfamily = '%u'::pg_catalog.oid "
   13307                 :                       "ORDER BY amopstrategy",
   13308 GIC         107 :                       opfinfo->dobj.catId.oid,
   13309 CBC         107 :                       opfinfo->dobj.catId.oid);
   13310 ECB             : 
   13311 CBC         107 :     res_ops = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   13312 ECB             : 
   13313 GIC         107 :     resetPQExpBuffer(query);
   13314                 : 
   13315 CBC         107 :     appendPQExpBuffer(query, "SELECT amprocnum, "
   13316                 :                       "amproc::pg_catalog.regprocedure, "
   13317                 :                       "amproclefttype::pg_catalog.regtype, "
   13318                 :                       "amprocrighttype::pg_catalog.regtype "
   13319                 :                       "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
   13320                 :                       "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
   13321                 :                       "AND refobjid = '%u'::pg_catalog.oid "
   13322                 :                       "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
   13323                 :                       "AND objid = ap.oid "
   13324                 :                       "ORDER BY amprocnum",
   13325             107 :                       opfinfo->dobj.catId.oid);
   13326                 : 
   13327             107 :     res_procs = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   13328                 : 
   13329 ECB             :     /* Get additional fields from the pg_opfamily row */
   13330 CBC         107 :     resetPQExpBuffer(query);
   13331 ECB             : 
   13332 CBC         107 :     appendPQExpBuffer(query, "SELECT "
   13333 ECB             :                       "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opfmethod) AS amname "
   13334                 :                       "FROM pg_catalog.pg_opfamily "
   13335                 :                       "WHERE oid = '%u'::pg_catalog.oid",
   13336 GIC         107 :                       opfinfo->dobj.catId.oid);
   13337                 : 
   13338 CBC         107 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   13339 ECB             : 
   13340 CBC         107 :     i_amname = PQfnumber(res, "amname");
   13341                 : 
   13342 ECB             :     /* amname will still be needed after we PQclear res */
   13343 CBC         107 :     amname = pg_strdup(PQgetvalue(res, 0, i_amname));
   13344 ECB             : 
   13345 GIC         107 :     appendPQExpBuffer(delq, "DROP OPERATOR FAMILY %s",
   13346 CBC         107 :                       fmtQualifiedDumpable(opfinfo));
   13347 GIC         107 :     appendPQExpBuffer(delq, " USING %s;\n",
   13348 ECB             :                       fmtId(amname));
   13349                 : 
   13350                 :     /* Build the fixed portion of the CREATE command */
   13351 GIC         107 :     appendPQExpBuffer(q, "CREATE OPERATOR FAMILY %s",
   13352             107 :                       fmtQualifiedDumpable(opfinfo));
   13353             107 :     appendPQExpBuffer(q, " USING %s;\n",
   13354 ECB             :                       fmtId(amname));
   13355                 : 
   13356 CBC         107 :     PQclear(res);
   13357 EUB             : 
   13358 ECB             :     /* Do we need an ALTER to add loose members? */
   13359 GIC         107 :     if (PQntuples(res_ops) > 0 || PQntuples(res_procs) > 0)
   13360                 :     {
   13361 CBC          51 :         appendPQExpBuffer(q, "ALTER OPERATOR FAMILY %s",
   13362 GIC          51 :                           fmtQualifiedDumpable(opfinfo));
   13363 CBC          51 :         appendPQExpBuffer(q, " USING %s ADD\n    ",
   13364 ECB             :                           fmtId(amname));
   13365                 : 
   13366 GIC          51 :         needComma = false;
   13367 ECB             : 
   13368                 :         /*
   13369                 :          * Now fetch and print the OPERATOR entries (pg_amop rows).
   13370                 :          */
   13371 CBC          51 :         ntups = PQntuples(res_ops);
   13372                 : 
   13373 GBC          51 :         i_amopstrategy = PQfnumber(res_ops, "amopstrategy");
   13374 GIC          51 :         i_amopopr = PQfnumber(res_ops, "amopopr");
   13375 GBC          51 :         i_sortfamily = PQfnumber(res_ops, "sortfamily");
   13376 GIC          51 :         i_sortfamilynsp = PQfnumber(res_ops, "sortfamilynsp");
   13377                 : 
   13378 CBC         231 :         for (i = 0; i < ntups; i++)
   13379                 :         {
   13380 GIC         180 :             amopstrategy = PQgetvalue(res_ops, i, i_amopstrategy);
   13381             180 :             amopopr = PQgetvalue(res_ops, i, i_amopopr);
   13382             180 :             sortfamily = PQgetvalue(res_ops, i, i_sortfamily);
   13383             180 :             sortfamilynsp = PQgetvalue(res_ops, i, i_sortfamilynsp);
   13384                 : 
   13385             180 :             if (needComma)
   13386 CBC         144 :                 appendPQExpBufferStr(q, " ,\n    ");
   13387 ECB             : 
   13388 GIC         180 :             appendPQExpBuffer(q, "OPERATOR %s %s",
   13389                 :                               amopstrategy, amopopr);
   13390                 : 
   13391             180 :             if (strlen(sortfamily) > 0)
   13392                 :             {
   13393 UIC           0 :                 appendPQExpBufferStr(q, " FOR ORDER BY ");
   13394               0 :                 appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
   13395               0 :                 appendPQExpBufferStr(q, fmtId(sortfamily));
   13396                 :             }
   13397                 : 
   13398 GIC         180 :             needComma = true;
   13399 ECB             :         }
   13400                 : 
   13401                 :         /*
   13402                 :          * Now fetch and print the FUNCTION entries (pg_amproc rows).
   13403                 :          */
   13404 CBC          51 :         ntups = PQntuples(res_procs);
   13405                 : 
   13406              51 :         i_amprocnum = PQfnumber(res_procs, "amprocnum");
   13407              51 :         i_amproc = PQfnumber(res_procs, "amproc");
   13408              51 :         i_amproclefttype = PQfnumber(res_procs, "amproclefttype");
   13409              51 :         i_amprocrighttype = PQfnumber(res_procs, "amprocrighttype");
   13410                 : 
   13411             246 :         for (i = 0; i < ntups; i++)
   13412                 :         {
   13413             195 :             amprocnum = PQgetvalue(res_procs, i, i_amprocnum);
   13414             195 :             amproc = PQgetvalue(res_procs, i, i_amproc);
   13415             195 :             amproclefttype = PQgetvalue(res_procs, i, i_amproclefttype);
   13416             195 :             amprocrighttype = PQgetvalue(res_procs, i, i_amprocrighttype);
   13417                 : 
   13418             195 :             if (needComma)
   13419             180 :                 appendPQExpBufferStr(q, " ,\n    ");
   13420                 : 
   13421             195 :             appendPQExpBuffer(q, "FUNCTION %s (%s, %s) %s",
   13422                 :                               amprocnum, amproclefttype, amprocrighttype,
   13423                 :                               amproc);
   13424 ECB             : 
   13425 GIC         195 :             needComma = true;
   13426 EUB             :         }
   13427                 : 
   13428 GBC          51 :         appendPQExpBufferStr(q, ";\n");
   13429                 :     }
   13430                 : 
   13431 CBC         107 :     appendPQExpBufferStr(nameusing, fmtId(opfinfo->dobj.name));
   13432 GIC         107 :     appendPQExpBuffer(nameusing, " USING %s",
   13433                 :                       fmtId(amname));
   13434 ECB             : 
   13435 GIC         107 :     if (dopt->binary_upgrade)
   13436               9 :         binary_upgrade_extension_member(q, &opfinfo->dobj,
   13437               9 :                                         "OPERATOR FAMILY", nameusing->data,
   13438               9 :                                         opfinfo->dobj.namespace->dobj.name);
   13439                 : 
   13440             107 :     if (opfinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   13441             107 :         ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId,
   13442             107 :                      ARCHIVE_OPTS(.tag = opfinfo->dobj.name,
   13443                 :                                   .namespace = opfinfo->dobj.namespace->dobj.name,
   13444                 :                                   .owner = opfinfo->rolname,
   13445                 :                                   .description = "OPERATOR FAMILY",
   13446 ECB             :                                   .section = SECTION_PRE_DATA,
   13447                 :                                   .createStmt = q->data,
   13448                 :                                   .dropStmt = delq->data));
   13449                 : 
   13450                 :     /* Dump Operator Family Comments */
   13451 GIC         107 :     if (opfinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   13452 UIC           0 :         dumpComment(fout, "OPERATOR FAMILY", nameusing->data,
   13453               0 :                     opfinfo->dobj.namespace->dobj.name, opfinfo->rolname,
   13454               0 :                     opfinfo->dobj.catId, 0, opfinfo->dobj.dumpId);
   13455                 : 
   13456 GIC         107 :     free(amname);
   13457             107 :     PQclear(res_ops);
   13458 CBC         107 :     PQclear(res_procs);
   13459 GIC         107 :     destroyPQExpBuffer(query);
   13460 CBC         107 :     destroyPQExpBuffer(q);
   13461 GIC         107 :     destroyPQExpBuffer(delq);
   13462 CBC         107 :     destroyPQExpBuffer(nameusing);
   13463                 : }
   13464 ECB             : 
   13465                 : /*
   13466                 :  * dumpCollation
   13467                 :  *    write out a single collation definition
   13468                 :  */
   13469                 : static void
   13470 GIC          81 : dumpCollation(Archive *fout, const CollInfo *collinfo)
   13471 ECB             : {
   13472 CBC          81 :     DumpOptions *dopt = fout->dopt;
   13473 ECB             :     PQExpBuffer query;
   13474                 :     PQExpBuffer q;
   13475                 :     PQExpBuffer delq;
   13476                 :     char       *qcollname;
   13477                 :     PGresult   *res;
   13478                 :     int         i_collprovider;
   13479                 :     int         i_collisdeterministic;
   13480                 :     int         i_collcollate;
   13481                 :     int         i_collctype;
   13482                 :     int         i_colliculocale;
   13483                 :     int         i_collicurules;
   13484                 :     const char *collprovider;
   13485                 :     const char *collcollate;
   13486                 :     const char *collctype;
   13487                 :     const char *colliculocale;
   13488                 :     const char *collicurules;
   13489                 : 
   13490                 :     /* Do nothing in data-only dump */
   13491 CBC          81 :     if (dopt->dataOnly)
   13492 GIC           6 :         return;
   13493                 : 
   13494              75 :     query = createPQExpBuffer();
   13495              75 :     q = createPQExpBuffer();
   13496              75 :     delq = createPQExpBuffer();
   13497                 : 
   13498              75 :     qcollname = pg_strdup(fmtId(collinfo->dobj.name));
   13499 ECB             : 
   13500                 :     /* Get collation-specific details */
   13501 GIC          75 :     appendPQExpBufferStr(query, "SELECT ");
   13502 ECB             : 
   13503 GIC          75 :     if (fout->remoteVersion >= 100000)
   13504 CBC          75 :         appendPQExpBufferStr(query,
   13505 ECB             :                              "collprovider, "
   13506                 :                              "collversion, ");
   13507                 :     else
   13508 LBC           0 :         appendPQExpBufferStr(query,
   13509 ECB             :                              "'c' AS collprovider, "
   13510                 :                              "NULL AS collversion, ");
   13511                 : 
   13512 GIC          75 :     if (fout->remoteVersion >= 120000)
   13513 CBC          75 :         appendPQExpBufferStr(query,
   13514 ECB             :                              "collisdeterministic, ");
   13515                 :     else
   13516 UIC           0 :         appendPQExpBufferStr(query,
   13517                 :                              "true AS collisdeterministic, ");
   13518                 : 
   13519 GIC          75 :     if (fout->remoteVersion >= 150000)
   13520              75 :         appendPQExpBufferStr(query,
   13521                 :                              "colliculocale, ");
   13522                 :     else
   13523 UIC           0 :         appendPQExpBufferStr(query,
   13524 ECB             :                              "NULL AS colliculocale, ");
   13525 EUB             : 
   13526 GNC          75 :     if (fout->remoteVersion >= 160000)
   13527              75 :         appendPQExpBufferStr(query,
   13528                 :                              "collicurules, ");
   13529                 :     else
   13530 UNC           0 :         appendPQExpBufferStr(query,
   13531                 :                              "NULL AS collicurules, ");
   13532                 : 
   13533 GBC          75 :     appendPQExpBuffer(query,
   13534 EUB             :                       "collcollate, "
   13535                 :                       "collctype "
   13536 ECB             :                       "FROM pg_catalog.pg_collation c "
   13537                 :                       "WHERE c.oid = '%u'::pg_catalog.oid",
   13538 CBC          75 :                       collinfo->dobj.catId.oid);
   13539 ECB             : 
   13540 CBC          75 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   13541 ECB             : 
   13542 CBC          75 :     i_collprovider = PQfnumber(res, "collprovider");
   13543 GIC          75 :     i_collisdeterministic = PQfnumber(res, "collisdeterministic");
   13544              75 :     i_collcollate = PQfnumber(res, "collcollate");
   13545              75 :     i_collctype = PQfnumber(res, "collctype");
   13546              75 :     i_colliculocale = PQfnumber(res, "colliculocale");
   13547 GNC          75 :     i_collicurules = PQfnumber(res, "collicurules");
   13548                 : 
   13549 GIC          75 :     collprovider = PQgetvalue(res, 0, i_collprovider);
   13550                 : 
   13551              75 :     if (!PQgetisnull(res, 0, i_collcollate))
   13552              35 :         collcollate = PQgetvalue(res, 0, i_collcollate);
   13553                 :     else
   13554 CBC          40 :         collcollate = NULL;
   13555                 : 
   13556              75 :     if (!PQgetisnull(res, 0, i_collctype))
   13557 GIC          35 :         collctype = PQgetvalue(res, 0, i_collctype);
   13558                 :     else
   13559              40 :         collctype = NULL;
   13560                 : 
   13561              75 :     if (!PQgetisnull(res, 0, i_colliculocale))
   13562              40 :         colliculocale = PQgetvalue(res, 0, i_colliculocale);
   13563                 :     else
   13564              35 :         colliculocale = NULL;
   13565                 : 
   13566 GNC          75 :     if (!PQgetisnull(res, 0, i_collicurules))
   13567 UNC           0 :         collicurules = PQgetvalue(res, 0, i_collicurules);
   13568                 :     else
   13569 GNC          75 :         collicurules = NULL;
   13570                 : 
   13571 GIC          75 :     appendPQExpBuffer(delq, "DROP COLLATION %s;\n",
   13572              75 :                       fmtQualifiedDumpable(collinfo));
   13573                 : 
   13574              75 :     appendPQExpBuffer(q, "CREATE COLLATION %s (",
   13575              75 :                       fmtQualifiedDumpable(collinfo));
   13576                 : 
   13577              75 :     appendPQExpBufferStr(q, "provider = ");
   13578              75 :     if (collprovider[0] == 'c')
   13579              35 :         appendPQExpBufferStr(q, "libc");
   13580              40 :     else if (collprovider[0] == 'i')
   13581              40 :         appendPQExpBufferStr(q, "icu");
   13582 UIC           0 :     else if (collprovider[0] == 'd')
   13583                 :         /* to allow dumping pg_catalog; not accepted on input */
   13584               0 :         appendPQExpBufferStr(q, "default");
   13585                 :     else
   13586               0 :         pg_fatal("unrecognized collation provider: %s",
   13587                 :                  collprovider);
   13588                 : 
   13589 GIC          75 :     if (strcmp(PQgetvalue(res, 0, i_collisdeterministic), "f") == 0)
   13590 UIC           0 :         appendPQExpBufferStr(q, ", deterministic = false");
   13591                 : 
   13592 CBC          75 :     if (colliculocale != NULL)
   13593 ECB             :     {
   13594 GIC          40 :         appendPQExpBufferStr(q, ", locale = ");
   13595 CBC          40 :         appendStringLiteralAH(q, colliculocale, fout);
   13596 ECB             :     }
   13597                 :     else
   13598                 :     {
   13599 GIC          35 :         Assert(collcollate != NULL);
   13600              35 :         Assert(collctype != NULL);
   13601                 : 
   13602              35 :         if (strcmp(collcollate, collctype) == 0)
   13603                 :         {
   13604 CBC          35 :             appendPQExpBufferStr(q, ", locale = ");
   13605 GIC          35 :             appendStringLiteralAH(q, collcollate, fout);
   13606                 :         }
   13607                 :         else
   13608                 :         {
   13609 UIC           0 :             appendPQExpBufferStr(q, ", lc_collate = ");
   13610               0 :             appendStringLiteralAH(q, collcollate, fout);
   13611               0 :             appendPQExpBufferStr(q, ", lc_ctype = ");
   13612               0 :             appendStringLiteralAH(q, collctype, fout);
   13613                 :         }
   13614                 :     }
   13615                 : 
   13616 GNC          75 :     if (collicurules)
   13617                 :     {
   13618 UNC           0 :         appendPQExpBufferStr(q, ", rules = ");
   13619               0 :         appendStringLiteralAH(q, collicurules, fout);
   13620                 :     }
   13621                 : 
   13622 ECB             :     /*
   13623                 :      * For binary upgrade, carry over the collation version.  For normal
   13624                 :      * dump/restore, omit the version, so that it is computed upon restore.
   13625                 :      */
   13626 GIC          75 :     if (dopt->binary_upgrade)
   13627 ECB             :     {
   13628                 :         int         i_collversion;
   13629                 : 
   13630 GIC           3 :         i_collversion = PQfnumber(res, "collversion");
   13631               3 :         if (!PQgetisnull(res, 0, i_collversion))
   13632                 :         {
   13633               2 :             appendPQExpBufferStr(q, ", version = ");
   13634               2 :             appendStringLiteralAH(q,
   13635                 :                                   PQgetvalue(res, 0, i_collversion),
   13636                 :                                   fout);
   13637                 :         }
   13638                 :     }
   13639 ECB             : 
   13640 GIC          75 :     appendPQExpBufferStr(q, ");\n");
   13641 ECB             : 
   13642 GIC          75 :     if (dopt->binary_upgrade)
   13643               3 :         binary_upgrade_extension_member(q, &collinfo->dobj,
   13644 ECB             :                                         "COLLATION", qcollname,
   13645 GIC           3 :                                         collinfo->dobj.namespace->dobj.name);
   13646 ECB             : 
   13647 GIC          75 :     if (collinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   13648              75 :         ArchiveEntry(fout, collinfo->dobj.catId, collinfo->dobj.dumpId,
   13649              75 :                      ARCHIVE_OPTS(.tag = collinfo->dobj.name,
   13650 ECB             :                                   .namespace = collinfo->dobj.namespace->dobj.name,
   13651                 :                                   .owner = collinfo->rolname,
   13652                 :                                   .description = "COLLATION",
   13653                 :                                   .section = SECTION_PRE_DATA,
   13654                 :                                   .createStmt = q->data,
   13655                 :                                   .dropStmt = delq->data));
   13656                 : 
   13657                 :     /* Dump Collation Comments */
   13658 GIC          75 :     if (collinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   13659 CBC          35 :         dumpComment(fout, "COLLATION", qcollname,
   13660              35 :                     collinfo->dobj.namespace->dobj.name, collinfo->rolname,
   13661              35 :                     collinfo->dobj.catId, 0, collinfo->dobj.dumpId);
   13662                 : 
   13663 GIC          75 :     PQclear(res);
   13664                 : 
   13665 CBC          75 :     destroyPQExpBuffer(query);
   13666              75 :     destroyPQExpBuffer(q);
   13667              75 :     destroyPQExpBuffer(delq);
   13668 GIC          75 :     free(qcollname);
   13669                 : }
   13670 ECB             : 
   13671                 : /*
   13672                 :  * dumpConversion
   13673                 :  *    write out a single conversion definition
   13674                 :  */
   13675                 : static void
   13676 CBC          39 : dumpConversion(Archive *fout, const ConvInfo *convinfo)
   13677 ECB             : {
   13678 GIC          39 :     DumpOptions *dopt = fout->dopt;
   13679                 :     PQExpBuffer query;
   13680 ECB             :     PQExpBuffer q;
   13681                 :     PQExpBuffer delq;
   13682                 :     char       *qconvname;
   13683                 :     PGresult   *res;
   13684                 :     int         i_conforencoding;
   13685                 :     int         i_contoencoding;
   13686                 :     int         i_conproc;
   13687                 :     int         i_condefault;
   13688                 :     const char *conforencoding;
   13689                 :     const char *contoencoding;
   13690                 :     const char *conproc;
   13691                 :     bool        condefault;
   13692                 : 
   13693                 :     /* Do nothing in data-only dump */
   13694 CBC          39 :     if (dopt->dataOnly)
   13695               3 :         return;
   13696 ECB             : 
   13697 CBC          36 :     query = createPQExpBuffer();
   13698 GIC          36 :     q = createPQExpBuffer();
   13699 CBC          36 :     delq = createPQExpBuffer();
   13700 ECB             : 
   13701 GIC          36 :     qconvname = pg_strdup(fmtId(convinfo->dobj.name));
   13702 ECB             : 
   13703                 :     /* Get conversion-specific details */
   13704 GIC          36 :     appendPQExpBuffer(query, "SELECT "
   13705 ECB             :                       "pg_catalog.pg_encoding_to_char(conforencoding) AS conforencoding, "
   13706                 :                       "pg_catalog.pg_encoding_to_char(contoencoding) AS contoencoding, "
   13707 EUB             :                       "conproc, condefault "
   13708                 :                       "FROM pg_catalog.pg_conversion c "
   13709                 :                       "WHERE c.oid = '%u'::pg_catalog.oid",
   13710 GIC          36 :                       convinfo->dobj.catId.oid);
   13711                 : 
   13712 CBC          36 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   13713                 : 
   13714 GIC          36 :     i_conforencoding = PQfnumber(res, "conforencoding");
   13715              36 :     i_contoencoding = PQfnumber(res, "contoencoding");
   13716              36 :     i_conproc = PQfnumber(res, "conproc");
   13717              36 :     i_condefault = PQfnumber(res, "condefault");
   13718 ECB             : 
   13719 GIC          36 :     conforencoding = PQgetvalue(res, 0, i_conforencoding);
   13720 CBC          36 :     contoencoding = PQgetvalue(res, 0, i_contoencoding);
   13721              36 :     conproc = PQgetvalue(res, 0, i_conproc);
   13722              36 :     condefault = (PQgetvalue(res, 0, i_condefault)[0] == 't');
   13723 ECB             : 
   13724 GIC          36 :     appendPQExpBuffer(delq, "DROP CONVERSION %s;\n",
   13725 CBC          36 :                       fmtQualifiedDumpable(convinfo));
   13726                 : 
   13727              36 :     appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
   13728 ECB             :                       (condefault) ? "DEFAULT " : "",
   13729 CBC          36 :                       fmtQualifiedDumpable(convinfo));
   13730              36 :     appendStringLiteralAH(q, conforencoding, fout);
   13731 GIC          36 :     appendPQExpBufferStr(q, " TO ");
   13732 CBC          36 :     appendStringLiteralAH(q, contoencoding, fout);
   13733 ECB             :     /* regproc output is already sufficiently quoted */
   13734 GIC          36 :     appendPQExpBuffer(q, " FROM %s;\n", conproc);
   13735 ECB             : 
   13736 GIC          36 :     if (dopt->binary_upgrade)
   13737               1 :         binary_upgrade_extension_member(q, &convinfo->dobj,
   13738                 :                                         "CONVERSION", qconvname,
   13739 CBC           1 :                                         convinfo->dobj.namespace->dobj.name);
   13740                 : 
   13741 GIC          36 :     if (convinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   13742 CBC          36 :         ArchiveEntry(fout, convinfo->dobj.catId, convinfo->dobj.dumpId,
   13743 GIC          36 :                      ARCHIVE_OPTS(.tag = convinfo->dobj.name,
   13744                 :                                   .namespace = convinfo->dobj.namespace->dobj.name,
   13745 ECB             :                                   .owner = convinfo->rolname,
   13746                 :                                   .description = "CONVERSION",
   13747                 :                                   .section = SECTION_PRE_DATA,
   13748                 :                                   .createStmt = q->data,
   13749                 :                                   .dropStmt = delq->data));
   13750                 : 
   13751                 :     /* Dump Conversion Comments */
   13752 CBC          36 :     if (convinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   13753 GIC          36 :         dumpComment(fout, "CONVERSION", qconvname,
   13754 CBC          36 :                     convinfo->dobj.namespace->dobj.name, convinfo->rolname,
   13755              36 :                     convinfo->dobj.catId, 0, convinfo->dobj.dumpId);
   13756 ECB             : 
   13757 GIC          36 :     PQclear(res);
   13758                 : 
   13759              36 :     destroyPQExpBuffer(query);
   13760              36 :     destroyPQExpBuffer(q);
   13761              36 :     destroyPQExpBuffer(delq);
   13762              36 :     free(qconvname);
   13763                 : }
   13764                 : 
   13765 ECB             : /*
   13766 EUB             :  * format_aggregate_signature: generate aggregate name and argument list
   13767                 :  *
   13768                 :  * The argument type names are qualified if needed.  The aggregate name
   13769                 :  * is never qualified.
   13770 ECB             :  */
   13771                 : static char *
   13772 CBC         288 : format_aggregate_signature(const AggInfo *agginfo, Archive *fout, bool honor_quotes)
   13773 ECB             : {
   13774                 :     PQExpBufferData buf;
   13775                 :     int         j;
   13776                 : 
   13777 GIC         288 :     initPQExpBuffer(&buf);
   13778             288 :     if (honor_quotes)
   13779 UIC           0 :         appendPQExpBufferStr(&buf, fmtId(agginfo->aggfn.dobj.name));
   13780                 :     else
   13781 GIC         288 :         appendPQExpBufferStr(&buf, agginfo->aggfn.dobj.name);
   13782                 : 
   13783             288 :     if (agginfo->aggfn.nargs == 0)
   13784 CBC          40 :         appendPQExpBufferStr(&buf, "(*)");
   13785                 :     else
   13786 ECB             :     {
   13787 GIC         248 :         appendPQExpBufferChar(&buf, '(');
   13788             541 :         for (j = 0; j < agginfo->aggfn.nargs; j++)
   13789             293 :             appendPQExpBuffer(&buf, "%s%s",
   13790                 :                               (j > 0) ? ", " : "",
   13791                 :                               getFormattedTypeName(fout,
   13792             293 :                                                    agginfo->aggfn.argtypes[j],
   13793                 :                                                    zeroIsError));
   13794             248 :         appendPQExpBufferChar(&buf, ')');
   13795                 :     }
   13796             288 :     return buf.data;
   13797                 : }
   13798                 : 
   13799                 : /*
   13800                 :  * dumpAgg
   13801                 :  *    write out a single aggregate definition
   13802                 :  */
   13803                 : static void
   13804             292 : dumpAgg(Archive *fout, const AggInfo *agginfo)
   13805 ECB             : {
   13806 CBC         292 :     DumpOptions *dopt = fout->dopt;
   13807                 :     PQExpBuffer query;
   13808 ECB             :     PQExpBuffer q;
   13809                 :     PQExpBuffer delq;
   13810                 :     PQExpBuffer details;
   13811                 :     char       *aggsig;         /* identity signature */
   13812 CBC         292 :     char       *aggfullsig = NULL;  /* full signature */
   13813                 :     char       *aggsig_tag;
   13814                 :     PGresult   *res;
   13815 ECB             :     int         i_agginitval;
   13816                 :     int         i_aggminitval;
   13817                 :     const char *aggtransfn;
   13818                 :     const char *aggfinalfn;
   13819                 :     const char *aggcombinefn;
   13820                 :     const char *aggserialfn;
   13821                 :     const char *aggdeserialfn;
   13822 EUB             :     const char *aggmtransfn;
   13823                 :     const char *aggminvtransfn;
   13824                 :     const char *aggmfinalfn;
   13825                 :     bool        aggfinalextra;
   13826 ECB             :     bool        aggmfinalextra;
   13827                 :     char        aggfinalmodify;
   13828                 :     char        aggmfinalmodify;
   13829                 :     const char *aggsortop;
   13830 EUB             :     char       *aggsortconvop;
   13831                 :     char        aggkind;
   13832                 :     const char *aggtranstype;
   13833 ECB             :     const char *aggtransspace;
   13834                 :     const char *aggmtranstype;
   13835                 :     const char *aggmtransspace;
   13836                 :     const char *agginitval;
   13837 EUB             :     const char *aggminitval;
   13838                 :     const char *proparallel;
   13839                 :     char        defaultfinalmodify;
   13840 ECB             : 
   13841                 :     /* Do nothing in data-only dump */
   13842 GIC         292 :     if (dopt->dataOnly)
   13843               4 :         return;
   13844 EUB             : 
   13845 GIC         288 :     query = createPQExpBuffer();
   13846             288 :     q = createPQExpBuffer();
   13847 CBC         288 :     delq = createPQExpBuffer();
   13848 GIC         288 :     details = createPQExpBuffer();
   13849                 : 
   13850             288 :     if (!fout->is_prepared[PREPQUERY_DUMPAGG])
   13851                 :     {
   13852 ECB             :         /* Set up query for aggregate-specific details */
   13853 GIC          58 :         appendPQExpBufferStr(query,
   13854 ECB             :                              "PREPARE dumpAgg(pg_catalog.oid) AS\n");
   13855                 : 
   13856 CBC          58 :         appendPQExpBufferStr(query,
   13857 ECB             :                              "SELECT "
   13858                 :                              "aggtransfn,\n"
   13859                 :                              "aggfinalfn,\n"
   13860                 :                              "aggtranstype::pg_catalog.regtype,\n"
   13861                 :                              "agginitval,\n"
   13862                 :                              "aggsortop,\n"
   13863                 :                              "pg_catalog.pg_get_function_arguments(p.oid) AS funcargs,\n"
   13864                 :                              "pg_catalog.pg_get_function_identity_arguments(p.oid) AS funciargs,\n");
   13865                 : 
   13866 CBC          58 :         if (fout->remoteVersion >= 90400)
   13867 GIC          58 :             appendPQExpBufferStr(query,
   13868 ECB             :                                  "aggkind,\n"
   13869                 :                                  "aggmtransfn,\n"
   13870                 :                                  "aggminvtransfn,\n"
   13871                 :                                  "aggmfinalfn,\n"
   13872                 :                                  "aggmtranstype::pg_catalog.regtype,\n"
   13873                 :                                  "aggfinalextra,\n"
   13874                 :                                  "aggmfinalextra,\n"
   13875                 :                                  "aggtransspace,\n"
   13876                 :                                  "aggmtransspace,\n"
   13877                 :                                  "aggminitval,\n");
   13878                 :         else
   13879 UIC           0 :             appendPQExpBufferStr(query,
   13880 ECB             :                                  "'n' AS aggkind,\n"
   13881 EUB             :                                  "'-' AS aggmtransfn,\n"
   13882                 :                                  "'-' AS aggminvtransfn,\n"
   13883 ECB             :                                  "'-' AS aggmfinalfn,\n"
   13884                 :                                  "0 AS aggmtranstype,\n"
   13885                 :                                  "false AS aggfinalextra,\n"
   13886                 :                                  "false AS aggmfinalextra,\n"
   13887                 :                                  "0 AS aggtransspace,\n"
   13888                 :                                  "0 AS aggmtransspace,\n"
   13889                 :                                  "NULL AS aggminitval,\n");
   13890                 : 
   13891 CBC          58 :         if (fout->remoteVersion >= 90600)
   13892              58 :             appendPQExpBufferStr(query,
   13893 ECB             :                                  "aggcombinefn,\n"
   13894                 :                                  "aggserialfn,\n"
   13895                 :                                  "aggdeserialfn,\n"
   13896 EUB             :                                  "proparallel,\n");
   13897                 :         else
   13898 UBC           0 :             appendPQExpBufferStr(query,
   13899                 :                                  "'-' AS aggcombinefn,\n"
   13900 EUB             :                                  "'-' AS aggserialfn,\n"
   13901                 :                                  "'-' AS aggdeserialfn,\n"
   13902                 :                                  "'u' AS proparallel,\n");
   13903 ECB             : 
   13904 GBC          58 :         if (fout->remoteVersion >= 110000)
   13905 GIC          58 :             appendPQExpBufferStr(query,
   13906 ECB             :                                  "aggfinalmodify,\n"
   13907                 :                                  "aggmfinalmodify\n");
   13908                 :         else
   13909 LBC           0 :             appendPQExpBufferStr(query,
   13910                 :                                  "'0' AS aggfinalmodify,\n"
   13911                 :                                  "'0' AS aggmfinalmodify\n");
   13912                 : 
   13913 CBC          58 :         appendPQExpBufferStr(query,
   13914 ECB             :                              "FROM pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
   13915                 :                              "WHERE a.aggfnoid = p.oid "
   13916                 :                              "AND p.oid = $1");
   13917                 : 
   13918 CBC          58 :         ExecuteSqlStatement(fout, query->data);
   13919 ECB             : 
   13920 GIC          58 :         fout->is_prepared[PREPQUERY_DUMPAGG] = true;
   13921                 :     }
   13922                 : 
   13923 GBC         288 :     printfPQExpBuffer(query,
   13924 EUB             :                       "EXECUTE dumpAgg('%u')",
   13925 GBC         288 :                       agginfo->aggfn.dobj.catId.oid);
   13926 EUB             : 
   13927 GIC         288 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   13928                 : 
   13929             288 :     i_agginitval = PQfnumber(res, "agginitval");
   13930 CBC         288 :     i_aggminitval = PQfnumber(res, "aggminitval");
   13931                 : 
   13932 GBC         288 :     aggtransfn = PQgetvalue(res, 0, PQfnumber(res, "aggtransfn"));
   13933             288 :     aggfinalfn = PQgetvalue(res, 0, PQfnumber(res, "aggfinalfn"));
   13934 GIC         288 :     aggcombinefn = PQgetvalue(res, 0, PQfnumber(res, "aggcombinefn"));
   13935             288 :     aggserialfn = PQgetvalue(res, 0, PQfnumber(res, "aggserialfn"));
   13936             288 :     aggdeserialfn = PQgetvalue(res, 0, PQfnumber(res, "aggdeserialfn"));
   13937             288 :     aggmtransfn = PQgetvalue(res, 0, PQfnumber(res, "aggmtransfn"));
   13938             288 :     aggminvtransfn = PQgetvalue(res, 0, PQfnumber(res, "aggminvtransfn"));
   13939             288 :     aggmfinalfn = PQgetvalue(res, 0, PQfnumber(res, "aggmfinalfn"));
   13940 CBC         288 :     aggfinalextra = (PQgetvalue(res, 0, PQfnumber(res, "aggfinalextra"))[0] == 't');
   13941 GIC         288 :     aggmfinalextra = (PQgetvalue(res, 0, PQfnumber(res, "aggmfinalextra"))[0] == 't');
   13942             288 :     aggfinalmodify = PQgetvalue(res, 0, PQfnumber(res, "aggfinalmodify"))[0];
   13943             288 :     aggmfinalmodify = PQgetvalue(res, 0, PQfnumber(res, "aggmfinalmodify"))[0];
   13944 CBC         288 :     aggsortop = PQgetvalue(res, 0, PQfnumber(res, "aggsortop"));
   13945             288 :     aggkind = PQgetvalue(res, 0, PQfnumber(res, "aggkind"))[0];
   13946 GIC         288 :     aggtranstype = PQgetvalue(res, 0, PQfnumber(res, "aggtranstype"));
   13947 CBC         288 :     aggtransspace = PQgetvalue(res, 0, PQfnumber(res, "aggtransspace"));
   13948             288 :     aggmtranstype = PQgetvalue(res, 0, PQfnumber(res, "aggmtranstype"));
   13949 GIC         288 :     aggmtransspace = PQgetvalue(res, 0, PQfnumber(res, "aggmtransspace"));
   13950             288 :     agginitval = PQgetvalue(res, 0, i_agginitval);
   13951             288 :     aggminitval = PQgetvalue(res, 0, i_aggminitval);
   13952             288 :     proparallel = PQgetvalue(res, 0, PQfnumber(res, "proparallel"));
   13953                 : 
   13954 ECB             :     {
   13955                 :         char       *funcargs;
   13956                 :         char       *funciargs;
   13957                 : 
   13958 GIC         288 :         funcargs = PQgetvalue(res, 0, PQfnumber(res, "funcargs"));
   13959 CBC         288 :         funciargs = PQgetvalue(res, 0, PQfnumber(res, "funciargs"));
   13960 GIC         288 :         aggfullsig = format_function_arguments(&agginfo->aggfn, funcargs, true);
   13961 CBC         288 :         aggsig = format_function_arguments(&agginfo->aggfn, funciargs, true);
   13962 ECB             :     }
   13963                 : 
   13964 GIC         288 :     aggsig_tag = format_aggregate_signature(agginfo, fout, false);
   13965                 : 
   13966                 :     /* identify default modify flag for aggkind (must match DefineAggregate) */
   13967             288 :     defaultfinalmodify = (aggkind == AGGKIND_NORMAL) ? AGGMODIFY_READ_ONLY : AGGMODIFY_READ_WRITE;
   13968                 :     /* replace omitted flags for old versions */
   13969             288 :     if (aggfinalmodify == '0')
   13970 UIC           0 :         aggfinalmodify = defaultfinalmodify;
   13971 GIC         288 :     if (aggmfinalmodify == '0')
   13972 LBC           0 :         aggmfinalmodify = defaultfinalmodify;
   13973 ECB             : 
   13974                 :     /* regproc and regtype output is already sufficiently quoted */
   13975 CBC         288 :     appendPQExpBuffer(details, "    SFUNC = %s,\n    STYPE = %s",
   13976                 :                       aggtransfn, aggtranstype);
   13977 ECB             : 
   13978 GIC         288 :     if (strcmp(aggtransspace, "0") != 0)
   13979 ECB             :     {
   13980 CBC           5 :         appendPQExpBuffer(details, ",\n    SSPACE = %s",
   13981 ECB             :                           aggtransspace);
   13982                 :     }
   13983                 : 
   13984 GIC         288 :     if (!PQgetisnull(res, 0, i_agginitval))
   13985                 :     {
   13986             211 :         appendPQExpBufferStr(details, ",\n    INITCOND = ");
   13987             211 :         appendStringLiteralAH(details, agginitval, fout);
   13988                 :     }
   13989                 : 
   13990 CBC         288 :     if (strcmp(aggfinalfn, "-") != 0)
   13991                 :     {
   13992             136 :         appendPQExpBuffer(details, ",\n    FINALFUNC = %s",
   13993                 :                           aggfinalfn);
   13994 GIC         136 :         if (aggfinalextra)
   13995              10 :             appendPQExpBufferStr(details, ",\n    FINALFUNC_EXTRA");
   13996             136 :         if (aggfinalmodify != defaultfinalmodify)
   13997                 :         {
   13998              36 :             switch (aggfinalmodify)
   13999                 :             {
   14000 UIC           0 :                 case AGGMODIFY_READ_ONLY:
   14001               0 :                     appendPQExpBufferStr(details, ",\n    FINALFUNC_MODIFY = READ_ONLY");
   14002               0 :                     break;
   14003 GIC          36 :                 case AGGMODIFY_SHAREABLE:
   14004              36 :                     appendPQExpBufferStr(details, ",\n    FINALFUNC_MODIFY = SHAREABLE");
   14005              36 :                     break;
   14006 UIC           0 :                 case AGGMODIFY_READ_WRITE:
   14007               0 :                     appendPQExpBufferStr(details, ",\n    FINALFUNC_MODIFY = READ_WRITE");
   14008 LBC           0 :                     break;
   14009               0 :                 default:
   14010 UIC           0 :                     pg_fatal("unrecognized aggfinalmodify value for aggregate \"%s\"",
   14011 ECB             :                              agginfo->aggfn.dobj.name);
   14012                 :                     break;
   14013                 :             }
   14014                 :         }
   14015                 :     }
   14016                 : 
   14017 GIC         288 :     if (strcmp(aggcombinefn, "-") != 0)
   14018 LBC           0 :         appendPQExpBuffer(details, ",\n    COMBINEFUNC = %s", aggcombinefn);
   14019                 : 
   14020 GIC         288 :     if (strcmp(aggserialfn, "-") != 0)
   14021 UIC           0 :         appendPQExpBuffer(details, ",\n    SERIALFUNC = %s", aggserialfn);
   14022                 : 
   14023 GIC         288 :     if (strcmp(aggdeserialfn, "-") != 0)
   14024 LBC           0 :         appendPQExpBuffer(details, ",\n    DESERIALFUNC = %s", aggdeserialfn);
   14025                 : 
   14026 CBC         288 :     if (strcmp(aggmtransfn, "-") != 0)
   14027                 :     {
   14028              30 :         appendPQExpBuffer(details, ",\n    MSFUNC = %s,\n    MINVFUNC = %s,\n    MSTYPE = %s",
   14029 ECB             :                           aggmtransfn,
   14030                 :                           aggminvtransfn,
   14031                 :                           aggmtranstype);
   14032                 :     }
   14033                 : 
   14034 CBC         288 :     if (strcmp(aggmtransspace, "0") != 0)
   14035 ECB             :     {
   14036 LBC           0 :         appendPQExpBuffer(details, ",\n    MSSPACE = %s",
   14037                 :                           aggmtransspace);
   14038 ECB             :     }
   14039                 : 
   14040 GIC         288 :     if (!PQgetisnull(res, 0, i_aggminitval))
   14041 ECB             :     {
   14042 GIC          10 :         appendPQExpBufferStr(details, ",\n    MINITCOND = ");
   14043 CBC          10 :         appendStringLiteralAH(details, aggminitval, fout);
   14044 ECB             :     }
   14045                 : 
   14046 CBC         288 :     if (strcmp(aggmfinalfn, "-") != 0)
   14047                 :     {
   14048 LBC           0 :         appendPQExpBuffer(details, ",\n    MFINALFUNC = %s",
   14049                 :                           aggmfinalfn);
   14050               0 :         if (aggmfinalextra)
   14051               0 :             appendPQExpBufferStr(details, ",\n    MFINALFUNC_EXTRA");
   14052 UIC           0 :         if (aggmfinalmodify != defaultfinalmodify)
   14053 ECB             :         {
   14054 UIC           0 :             switch (aggmfinalmodify)
   14055 ECB             :             {
   14056 LBC           0 :                 case AGGMODIFY_READ_ONLY:
   14057               0 :                     appendPQExpBufferStr(details, ",\n    MFINALFUNC_MODIFY = READ_ONLY");
   14058 UIC           0 :                     break;
   14059               0 :                 case AGGMODIFY_SHAREABLE:
   14060               0 :                     appendPQExpBufferStr(details, ",\n    MFINALFUNC_MODIFY = SHAREABLE");
   14061               0 :                     break;
   14062               0 :                 case AGGMODIFY_READ_WRITE:
   14063               0 :                     appendPQExpBufferStr(details, ",\n    MFINALFUNC_MODIFY = READ_WRITE");
   14064               0 :                     break;
   14065               0 :                 default:
   14066 LBC           0 :                     pg_fatal("unrecognized aggmfinalmodify value for aggregate \"%s\"",
   14067 ECB             :                              agginfo->aggfn.dobj.name);
   14068                 :                     break;
   14069                 :             }
   14070                 :         }
   14071                 :     }
   14072                 : 
   14073 CBC         288 :     aggsortconvop = getFormattedOperatorName(aggsortop);
   14074             288 :     if (aggsortconvop)
   14075 ECB             :     {
   14076 LBC           0 :         appendPQExpBuffer(details, ",\n    SORTOP = %s",
   14077                 :                           aggsortconvop);
   14078 UIC           0 :         free(aggsortconvop);
   14079                 :     }
   14080                 : 
   14081 GIC         288 :     if (aggkind == AGGKIND_HYPOTHETICAL)
   14082               5 :         appendPQExpBufferStr(details, ",\n    HYPOTHETICAL");
   14083                 : 
   14084             288 :     if (proparallel[0] != PROPARALLEL_UNSAFE)
   14085                 :     {
   14086 CBC           5 :         if (proparallel[0] == PROPARALLEL_SAFE)
   14087 GIC           5 :             appendPQExpBufferStr(details, ",\n    PARALLEL = safe");
   14088 UIC           0 :         else if (proparallel[0] == PROPARALLEL_RESTRICTED)
   14089               0 :             appendPQExpBufferStr(details, ",\n    PARALLEL = restricted");
   14090               0 :         else if (proparallel[0] != PROPARALLEL_UNSAFE)
   14091 LBC           0 :             pg_fatal("unrecognized proparallel value for function \"%s\"",
   14092 ECB             :                      agginfo->aggfn.dobj.name);
   14093 EUB             :     }
   14094                 : 
   14095 CBC         288 :     appendPQExpBuffer(delq, "DROP AGGREGATE %s.%s;\n",
   14096 GIC         288 :                       fmtId(agginfo->aggfn.dobj.namespace->dobj.name),
   14097 ECB             :                       aggsig);
   14098                 : 
   14099 GIC         576 :     appendPQExpBuffer(q, "CREATE AGGREGATE %s.%s (\n%s\n);\n",
   14100             288 :                       fmtId(agginfo->aggfn.dobj.namespace->dobj.name),
   14101 ECB             :                       aggfullsig ? aggfullsig : aggsig, details->data);
   14102                 : 
   14103 CBC         288 :     if (dopt->binary_upgrade)
   14104 GIC          49 :         binary_upgrade_extension_member(q, &agginfo->aggfn.dobj,
   14105                 :                                         "AGGREGATE", aggsig,
   14106 CBC          49 :                                         agginfo->aggfn.dobj.namespace->dobj.name);
   14107                 : 
   14108             288 :     if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_DEFINITION)
   14109 GIC         272 :         ArchiveEntry(fout, agginfo->aggfn.dobj.catId,
   14110 CBC         272 :                      agginfo->aggfn.dobj.dumpId,
   14111 GIC         272 :                      ARCHIVE_OPTS(.tag = aggsig_tag,
   14112                 :                                   .namespace = agginfo->aggfn.dobj.namespace->dobj.name,
   14113                 :                                   .owner = agginfo->aggfn.rolname,
   14114                 :                                   .description = "AGGREGATE",
   14115                 :                                   .section = SECTION_PRE_DATA,
   14116                 :                                   .createStmt = q->data,
   14117                 :                                   .dropStmt = delq->data));
   14118 ECB             : 
   14119                 :     /* Dump Aggregate Comments */
   14120 CBC         288 :     if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_COMMENT)
   14121 GIC          10 :         dumpComment(fout, "AGGREGATE", aggsig,
   14122              10 :                     agginfo->aggfn.dobj.namespace->dobj.name,
   14123              10 :                     agginfo->aggfn.rolname,
   14124              10 :                     agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
   14125                 : 
   14126 CBC         288 :     if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_SECLABEL)
   14127 UIC           0 :         dumpSecLabel(fout, "AGGREGATE", aggsig,
   14128               0 :                      agginfo->aggfn.dobj.namespace->dobj.name,
   14129               0 :                      agginfo->aggfn.rolname,
   14130               0 :                      agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
   14131                 : 
   14132                 :     /*
   14133                 :      * Since there is no GRANT ON AGGREGATE syntax, we have to make the ACL
   14134                 :      * command look like a function's GRANT; in particular this affects the
   14135                 :      * syntax for zero-argument aggregates and ordered-set aggregates.
   14136                 :      */
   14137 GIC         288 :     free(aggsig);
   14138                 : 
   14139             288 :     aggsig = format_function_signature(fout, &agginfo->aggfn, true);
   14140                 : 
   14141             288 :     if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_ACL)
   14142              17 :         dumpACL(fout, agginfo->aggfn.dobj.dumpId, InvalidDumpId,
   14143                 :                 "FUNCTION", aggsig, NULL,
   14144              17 :                 agginfo->aggfn.dobj.namespace->dobj.name,
   14145              17 :                 agginfo->aggfn.rolname, &agginfo->aggfn.dacl);
   14146                 : 
   14147             288 :     free(aggsig);
   14148 GNC         288 :     free(aggfullsig);
   14149 GIC         288 :     free(aggsig_tag);
   14150                 : 
   14151             288 :     PQclear(res);
   14152                 : 
   14153             288 :     destroyPQExpBuffer(query);
   14154             288 :     destroyPQExpBuffer(q);
   14155 CBC         288 :     destroyPQExpBuffer(delq);
   14156             288 :     destroyPQExpBuffer(details);
   14157                 : }
   14158 ECB             : 
   14159                 : /*
   14160                 :  * dumpTSParser
   14161                 :  *    write out a single text search parser
   14162                 :  */
   14163                 : static void
   14164 GIC          39 : dumpTSParser(Archive *fout, const TSParserInfo *prsinfo)
   14165                 : {
   14166 CBC          39 :     DumpOptions *dopt = fout->dopt;
   14167                 :     PQExpBuffer q;
   14168                 :     PQExpBuffer delq;
   14169 ECB             :     char       *qprsname;
   14170                 : 
   14171                 :     /* Do nothing in data-only dump */
   14172 GIC          39 :     if (dopt->dataOnly)
   14173               3 :         return;
   14174                 : 
   14175              36 :     q = createPQExpBuffer();
   14176              36 :     delq = createPQExpBuffer();
   14177                 : 
   14178              36 :     qprsname = pg_strdup(fmtId(prsinfo->dobj.name));
   14179 ECB             : 
   14180 CBC          36 :     appendPQExpBuffer(q, "CREATE TEXT SEARCH PARSER %s (\n",
   14181 GIC          36 :                       fmtQualifiedDumpable(prsinfo));
   14182                 : 
   14183              36 :     appendPQExpBuffer(q, "    START = %s,\n",
   14184              36 :                       convertTSFunction(fout, prsinfo->prsstart));
   14185              36 :     appendPQExpBuffer(q, "    GETTOKEN = %s,\n",
   14186              36 :                       convertTSFunction(fout, prsinfo->prstoken));
   14187              36 :     appendPQExpBuffer(q, "    END = %s,\n",
   14188              36 :                       convertTSFunction(fout, prsinfo->prsend));
   14189              36 :     if (prsinfo->prsheadline != InvalidOid)
   14190 UIC           0 :         appendPQExpBuffer(q, "    HEADLINE = %s,\n",
   14191               0 :                           convertTSFunction(fout, prsinfo->prsheadline));
   14192 GBC          36 :     appendPQExpBuffer(q, "    LEXTYPES = %s );\n",
   14193 GIC          36 :                       convertTSFunction(fout, prsinfo->prslextype));
   14194                 : 
   14195              36 :     appendPQExpBuffer(delq, "DROP TEXT SEARCH PARSER %s;\n",
   14196              36 :                       fmtQualifiedDumpable(prsinfo));
   14197                 : 
   14198              36 :     if (dopt->binary_upgrade)
   14199               1 :         binary_upgrade_extension_member(q, &prsinfo->dobj,
   14200                 :                                         "TEXT SEARCH PARSER", qprsname,
   14201               1 :                                         prsinfo->dobj.namespace->dobj.name);
   14202                 : 
   14203              36 :     if (prsinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   14204 CBC          36 :         ArchiveEntry(fout, prsinfo->dobj.catId, prsinfo->dobj.dumpId,
   14205              36 :                      ARCHIVE_OPTS(.tag = prsinfo->dobj.name,
   14206                 :                                   .namespace = prsinfo->dobj.namespace->dobj.name,
   14207                 :                                   .description = "TEXT SEARCH PARSER",
   14208                 :                                   .section = SECTION_PRE_DATA,
   14209                 :                                   .createStmt = q->data,
   14210                 :                                   .dropStmt = delq->data));
   14211 EUB             : 
   14212                 :     /* Dump Parser Comments */
   14213 GIC          36 :     if (prsinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   14214              36 :         dumpComment(fout, "TEXT SEARCH PARSER", qprsname,
   14215              36 :                     prsinfo->dobj.namespace->dobj.name, "",
   14216              36 :                     prsinfo->dobj.catId, 0, prsinfo->dobj.dumpId);
   14217 ECB             : 
   14218 CBC          36 :     destroyPQExpBuffer(q);
   14219 GIC          36 :     destroyPQExpBuffer(delq);
   14220              36 :     free(qprsname);
   14221                 : }
   14222 EUB             : 
   14223                 : /*
   14224                 :  * dumpTSDictionary
   14225                 :  *    write out a single text search dictionary
   14226 ECB             :  */
   14227                 : static void
   14228 GIC          84 : dumpTSDictionary(Archive *fout, const TSDictInfo *dictinfo)
   14229                 : {
   14230              84 :     DumpOptions *dopt = fout->dopt;
   14231 ECB             :     PQExpBuffer q;
   14232                 :     PQExpBuffer delq;
   14233                 :     PQExpBuffer query;
   14234                 :     char       *qdictname;
   14235                 :     PGresult   *res;
   14236                 :     char       *nspname;
   14237                 :     char       *tmplname;
   14238                 : 
   14239                 :     /* Do nothing in data-only dump */
   14240 CBC          84 :     if (dopt->dataOnly)
   14241 GIC           3 :         return;
   14242 ECB             : 
   14243 CBC          81 :     q = createPQExpBuffer();
   14244 GIC          81 :     delq = createPQExpBuffer();
   14245 CBC          81 :     query = createPQExpBuffer();
   14246 ECB             : 
   14247 CBC          81 :     qdictname = pg_strdup(fmtId(dictinfo->dobj.name));
   14248 ECB             : 
   14249                 :     /* Fetch name and namespace of the dictionary's template */
   14250 CBC          81 :     appendPQExpBuffer(query, "SELECT nspname, tmplname "
   14251 ECB             :                       "FROM pg_ts_template p, pg_namespace n "
   14252                 :                       "WHERE p.oid = '%u' AND n.oid = tmplnamespace",
   14253 CBC          81 :                       dictinfo->dicttemplate);
   14254              81 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   14255              81 :     nspname = PQgetvalue(res, 0, 0);
   14256              81 :     tmplname = PQgetvalue(res, 0, 1);
   14257 ECB             : 
   14258 CBC          81 :     appendPQExpBuffer(q, "CREATE TEXT SEARCH DICTIONARY %s (\n",
   14259              81 :                       fmtQualifiedDumpable(dictinfo));
   14260 ECB             : 
   14261 CBC          81 :     appendPQExpBufferStr(q, "    TEMPLATE = ");
   14262              81 :     appendPQExpBuffer(q, "%s.", fmtId(nspname));
   14263              81 :     appendPQExpBufferStr(q, fmtId(tmplname));
   14264 ECB             : 
   14265 CBC          81 :     PQclear(res);
   14266                 : 
   14267                 :     /* the dictinitoption can be dumped straight into the command */
   14268 GIC          81 :     if (dictinfo->dictinitoption)
   14269              45 :         appendPQExpBuffer(q, ",\n    %s", dictinfo->dictinitoption);
   14270                 : 
   14271 CBC          81 :     appendPQExpBufferStr(q, " );\n");
   14272 ECB             : 
   14273 CBC          81 :     appendPQExpBuffer(delq, "DROP TEXT SEARCH DICTIONARY %s;\n",
   14274              81 :                       fmtQualifiedDumpable(dictinfo));
   14275                 : 
   14276 GIC          81 :     if (dopt->binary_upgrade)
   14277 CBC          10 :         binary_upgrade_extension_member(q, &dictinfo->dobj,
   14278                 :                                         "TEXT SEARCH DICTIONARY", qdictname,
   14279 GIC          10 :                                         dictinfo->dobj.namespace->dobj.name);
   14280 ECB             : 
   14281 GIC          81 :     if (dictinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   14282 CBC          81 :         ArchiveEntry(fout, dictinfo->dobj.catId, dictinfo->dobj.dumpId,
   14283 GBC          81 :                      ARCHIVE_OPTS(.tag = dictinfo->dobj.name,
   14284 ECB             :                                   .namespace = dictinfo->dobj.namespace->dobj.name,
   14285 EUB             :                                   .owner = dictinfo->rolname,
   14286                 :                                   .description = "TEXT SEARCH DICTIONARY",
   14287                 :                                   .section = SECTION_PRE_DATA,
   14288 ECB             :                                   .createStmt = q->data,
   14289                 :                                   .dropStmt = delq->data));
   14290                 : 
   14291                 :     /* Dump Dictionary Comments */
   14292 GIC          81 :     if (dictinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   14293 CBC          36 :         dumpComment(fout, "TEXT SEARCH DICTIONARY", qdictname,
   14294 GIC          36 :                     dictinfo->dobj.namespace->dobj.name, dictinfo->rolname,
   14295              36 :                     dictinfo->dobj.catId, 0, dictinfo->dobj.dumpId);
   14296                 : 
   14297 CBC          81 :     destroyPQExpBuffer(q);
   14298 GIC          81 :     destroyPQExpBuffer(delq);
   14299 CBC          81 :     destroyPQExpBuffer(query);
   14300              81 :     free(qdictname);
   14301                 : }
   14302                 : 
   14303 ECB             : /*
   14304                 :  * dumpTSTemplate
   14305                 :  *    write out a single text search template
   14306                 :  */
   14307                 : static void
   14308 CBC          39 : dumpTSTemplate(Archive *fout, const TSTemplateInfo *tmplinfo)
   14309 ECB             : {
   14310 GIC          39 :     DumpOptions *dopt = fout->dopt;
   14311 ECB             :     PQExpBuffer q;
   14312                 :     PQExpBuffer delq;
   14313 EUB             :     char       *qtmplname;
   14314                 : 
   14315                 :     /* Do nothing in data-only dump */
   14316 CBC          39 :     if (dopt->dataOnly)
   14317               3 :         return;
   14318 ECB             : 
   14319 GBC          36 :     q = createPQExpBuffer();
   14320              36 :     delq = createPQExpBuffer();
   14321 EUB             : 
   14322 GBC          36 :     qtmplname = pg_strdup(fmtId(tmplinfo->dobj.name));
   14323 EUB             : 
   14324 GIC          36 :     appendPQExpBuffer(q, "CREATE TEXT SEARCH TEMPLATE %s (\n",
   14325              36 :                       fmtQualifiedDumpable(tmplinfo));
   14326                 : 
   14327              36 :     if (tmplinfo->tmplinit != InvalidOid)
   14328 UIC           0 :         appendPQExpBuffer(q, "    INIT = %s,\n",
   14329               0 :                           convertTSFunction(fout, tmplinfo->tmplinit));
   14330 CBC          36 :     appendPQExpBuffer(q, "    LEXIZE = %s );\n",
   14331 GBC          36 :                       convertTSFunction(fout, tmplinfo->tmpllexize));
   14332                 : 
   14333 CBC          36 :     appendPQExpBuffer(delq, "DROP TEXT SEARCH TEMPLATE %s;\n",
   14334 GBC          36 :                       fmtQualifiedDumpable(tmplinfo));
   14335                 : 
   14336 CBC          36 :     if (dopt->binary_upgrade)
   14337 GBC           1 :         binary_upgrade_extension_member(q, &tmplinfo->dobj,
   14338                 :                                         "TEXT SEARCH TEMPLATE", qtmplname,
   14339 CBC           1 :                                         tmplinfo->dobj.namespace->dobj.name);
   14340                 : 
   14341              36 :     if (tmplinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   14342 GIC          36 :         ArchiveEntry(fout, tmplinfo->dobj.catId, tmplinfo->dobj.dumpId,
   14343              36 :                      ARCHIVE_OPTS(.tag = tmplinfo->dobj.name,
   14344                 :                                   .namespace = tmplinfo->dobj.namespace->dobj.name,
   14345                 :                                   .description = "TEXT SEARCH TEMPLATE",
   14346                 :                                   .section = SECTION_PRE_DATA,
   14347 ECB             :                                   .createStmt = q->data,
   14348                 :                                   .dropStmt = delq->data));
   14349 EUB             : 
   14350                 :     /* Dump Template Comments */
   14351 GIC          36 :     if (tmplinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   14352              36 :         dumpComment(fout, "TEXT SEARCH TEMPLATE", qtmplname,
   14353 CBC          36 :                     tmplinfo->dobj.namespace->dobj.name, "",
   14354 GIC          36 :                     tmplinfo->dobj.catId, 0, tmplinfo->dobj.dumpId);
   14355 ECB             : 
   14356 CBC          36 :     destroyPQExpBuffer(q);
   14357 GIC          36 :     destroyPQExpBuffer(delq);
   14358              36 :     free(qtmplname);
   14359 ECB             : }
   14360                 : 
   14361 EUB             : /*
   14362                 :  * dumpTSConfig
   14363                 :  *    write out a single text search configuration
   14364                 :  */
   14365                 : static void
   14366 GIC          59 : dumpTSConfig(Archive *fout, const TSConfigInfo *cfginfo)
   14367 EUB             : {
   14368 GIC          59 :     DumpOptions *dopt = fout->dopt;
   14369 EUB             :     PQExpBuffer q;
   14370                 :     PQExpBuffer delq;
   14371                 :     PQExpBuffer query;
   14372                 :     char       *qcfgname;
   14373                 :     PGresult   *res;
   14374                 :     char       *nspname;
   14375                 :     char       *prsname;
   14376                 :     int         ntups,
   14377                 :                 i;
   14378                 :     int         i_tokenname;
   14379                 :     int         i_dictname;
   14380                 : 
   14381                 :     /* Do nothing in data-only dump */
   14382 GIC          59 :     if (dopt->dataOnly)
   14383               3 :         return;
   14384                 : 
   14385              56 :     q = createPQExpBuffer();
   14386 CBC          56 :     delq = createPQExpBuffer();
   14387              56 :     query = createPQExpBuffer();
   14388                 : 
   14389 GBC          56 :     qcfgname = pg_strdup(fmtId(cfginfo->dobj.name));
   14390                 : 
   14391 EUB             :     /* Fetch name and namespace of the config's parser */
   14392 GIC          56 :     appendPQExpBuffer(query, "SELECT nspname, prsname "
   14393                 :                       "FROM pg_ts_parser p, pg_namespace n "
   14394 ECB             :                       "WHERE p.oid = '%u' AND n.oid = prsnamespace",
   14395 CBC          56 :                       cfginfo->cfgparser);
   14396 GIC          56 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   14397 CBC          56 :     nspname = PQgetvalue(res, 0, 0);
   14398 GIC          56 :     prsname = PQgetvalue(res, 0, 1);
   14399 ECB             : 
   14400 CBC          56 :     appendPQExpBuffer(q, "CREATE TEXT SEARCH CONFIGURATION %s (\n",
   14401 GBC          56 :                       fmtQualifiedDumpable(cfginfo));
   14402 EUB             : 
   14403 GBC          56 :     appendPQExpBuffer(q, "    PARSER = %s.", fmtId(nspname));
   14404              56 :     appendPQExpBuffer(q, "%s );\n", fmtId(prsname));
   14405                 : 
   14406 GIC          56 :     PQclear(res);
   14407                 : 
   14408 CBC          56 :     resetPQExpBuffer(query);
   14409              56 :     appendPQExpBuffer(query,
   14410                 :                       "SELECT\n"
   14411                 :                       "  ( SELECT alias FROM pg_catalog.ts_token_type('%u'::pg_catalog.oid) AS t\n"
   14412 ECB             :                       "    WHERE t.tokid = m.maptokentype ) AS tokenname,\n"
   14413                 :                       "  m.mapdict::pg_catalog.regdictionary AS dictname\n"
   14414                 :                       "FROM pg_catalog.pg_ts_config_map AS m\n"
   14415                 :                       "WHERE m.mapcfg = '%u'\n"
   14416                 :                       "ORDER BY m.mapcfg, m.maptokentype, m.mapseqno",
   14417 CBC          56 :                       cfginfo->cfgparser, cfginfo->dobj.catId.oid);
   14418                 : 
   14419              56 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   14420 GIC          56 :     ntups = PQntuples(res);
   14421 ECB             : 
   14422 CBC          56 :     i_tokenname = PQfnumber(res, "tokenname");
   14423              56 :     i_dictname = PQfnumber(res, "dictname");
   14424 ECB             : 
   14425 GIC        1255 :     for (i = 0; i < ntups; i++)
   14426                 :     {
   14427            1199 :         char       *tokenname = PQgetvalue(res, i, i_tokenname);
   14428            1199 :         char       *dictname = PQgetvalue(res, i, i_dictname);
   14429                 : 
   14430            1199 :         if (i == 0 ||
   14431            1143 :             strcmp(tokenname, PQgetvalue(res, i - 1, i_tokenname)) != 0)
   14432                 :         {
   14433 ECB             :             /* starting a new token type, so start a new command */
   14434 CBC        1064 :             if (i > 0)
   14435            1008 :                 appendPQExpBufferStr(q, ";\n");
   14436            1064 :             appendPQExpBuffer(q, "\nALTER TEXT SEARCH CONFIGURATION %s\n",
   14437            1064 :                               fmtQualifiedDumpable(cfginfo));
   14438                 :             /* tokenname needs quoting, dictname does NOT */
   14439            1064 :             appendPQExpBuffer(q, "    ADD MAPPING FOR %s WITH %s",
   14440 EUB             :                               fmtId(tokenname), dictname);
   14441                 :         }
   14442                 :         else
   14443 GBC         135 :             appendPQExpBuffer(q, ", %s", dictname);
   14444                 :     }
   14445                 : 
   14446 GIC          56 :     if (ntups > 0)
   14447              56 :         appendPQExpBufferStr(q, ";\n");
   14448                 : 
   14449              56 :     PQclear(res);
   14450 ECB             : 
   14451 GIC          56 :     appendPQExpBuffer(delq, "DROP TEXT SEARCH CONFIGURATION %s;\n",
   14452 CBC          56 :                       fmtQualifiedDumpable(cfginfo));
   14453                 : 
   14454              56 :     if (dopt->binary_upgrade)
   14455               5 :         binary_upgrade_extension_member(q, &cfginfo->dobj,
   14456                 :                                         "TEXT SEARCH CONFIGURATION", qcfgname,
   14457               5 :                                         cfginfo->dobj.namespace->dobj.name);
   14458 ECB             : 
   14459 GIC          56 :     if (cfginfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   14460 CBC          56 :         ArchiveEntry(fout, cfginfo->dobj.catId, cfginfo->dobj.dumpId,
   14461              56 :                      ARCHIVE_OPTS(.tag = cfginfo->dobj.name,
   14462 ECB             :                                   .namespace = cfginfo->dobj.namespace->dobj.name,
   14463                 :                                   .owner = cfginfo->rolname,
   14464                 :                                   .description = "TEXT SEARCH CONFIGURATION",
   14465                 :                                   .section = SECTION_PRE_DATA,
   14466                 :                                   .createStmt = q->data,
   14467                 :                                   .dropStmt = delq->data));
   14468                 : 
   14469                 :     /* Dump Configuration Comments */
   14470 GIC          56 :     if (cfginfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   14471              36 :         dumpComment(fout, "TEXT SEARCH CONFIGURATION", qcfgname,
   14472              36 :                     cfginfo->dobj.namespace->dobj.name, cfginfo->rolname,
   14473              36 :                     cfginfo->dobj.catId, 0, cfginfo->dobj.dumpId);
   14474                 : 
   14475              56 :     destroyPQExpBuffer(q);
   14476              56 :     destroyPQExpBuffer(delq);
   14477 CBC          56 :     destroyPQExpBuffer(query);
   14478 GIC          56 :     free(qcfgname);
   14479 ECB             : }
   14480                 : 
   14481                 : /*
   14482                 :  * dumpForeignDataWrapper
   14483                 :  *    write out a single foreign-data wrapper definition
   14484                 :  */
   14485                 : static void
   14486 CBC          45 : dumpForeignDataWrapper(Archive *fout, const FdwInfo *fdwinfo)
   14487                 : {
   14488              45 :     DumpOptions *dopt = fout->dopt;
   14489 ECB             :     PQExpBuffer q;
   14490                 :     PQExpBuffer delq;
   14491                 :     char       *qfdwname;
   14492                 : 
   14493                 :     /* Do nothing in data-only dump */
   14494 CBC          45 :     if (dopt->dataOnly)
   14495 GIC           4 :         return;
   14496 ECB             : 
   14497 CBC          41 :     q = createPQExpBuffer();
   14498              41 :     delq = createPQExpBuffer();
   14499 ECB             : 
   14500 CBC          41 :     qfdwname = pg_strdup(fmtId(fdwinfo->dobj.name));
   14501 ECB             : 
   14502 CBC          41 :     appendPQExpBuffer(q, "CREATE FOREIGN DATA WRAPPER %s",
   14503 EUB             :                       qfdwname);
   14504                 : 
   14505 CBC          41 :     if (strcmp(fdwinfo->fdwhandler, "-") != 0)
   14506 LBC           0 :         appendPQExpBuffer(q, " HANDLER %s", fdwinfo->fdwhandler);
   14507                 : 
   14508 CBC          41 :     if (strcmp(fdwinfo->fdwvalidator, "-") != 0)
   14509 LBC           0 :         appendPQExpBuffer(q, " VALIDATOR %s", fdwinfo->fdwvalidator);
   14510                 : 
   14511 CBC          41 :     if (strlen(fdwinfo->fdwoptions) > 0)
   14512 LBC           0 :         appendPQExpBuffer(q, " OPTIONS (\n    %s\n)", fdwinfo->fdwoptions);
   14513                 : 
   14514 CBC          41 :     appendPQExpBufferStr(q, ";\n");
   14515                 : 
   14516              41 :     appendPQExpBuffer(delq, "DROP FOREIGN DATA WRAPPER %s;\n",
   14517 ECB             :                       qfdwname);
   14518                 : 
   14519 GIC          41 :     if (dopt->binary_upgrade)
   14520               2 :         binary_upgrade_extension_member(q, &fdwinfo->dobj,
   14521                 :                                         "FOREIGN DATA WRAPPER", qfdwname,
   14522                 :                                         NULL);
   14523                 : 
   14524              41 :     if (fdwinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   14525              41 :         ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
   14526 CBC          41 :                      ARCHIVE_OPTS(.tag = fdwinfo->dobj.name,
   14527 ECB             :                                   .owner = fdwinfo->rolname,
   14528                 :                                   .description = "FOREIGN DATA WRAPPER",
   14529                 :                                   .section = SECTION_PRE_DATA,
   14530                 :                                   .createStmt = q->data,
   14531                 :                                   .dropStmt = delq->data));
   14532                 : 
   14533                 :     /* Dump Foreign Data Wrapper Comments */
   14534 GIC          41 :     if (fdwinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   14535 UIC           0 :         dumpComment(fout, "FOREIGN DATA WRAPPER", qfdwname,
   14536               0 :                     NULL, fdwinfo->rolname,
   14537               0 :                     fdwinfo->dobj.catId, 0, fdwinfo->dobj.dumpId);
   14538                 : 
   14539                 :     /* Handle the ACL */
   14540 GIC          41 :     if (fdwinfo->dobj.dump & DUMP_COMPONENT_ACL)
   14541 CBC          35 :         dumpACL(fout, fdwinfo->dobj.dumpId, InvalidDumpId,
   14542                 :                 "FOREIGN DATA WRAPPER", qfdwname, NULL,
   14543              35 :                 NULL, fdwinfo->rolname, &fdwinfo->dacl);
   14544                 : 
   14545 GIC          41 :     free(qfdwname);
   14546                 : 
   14547              41 :     destroyPQExpBuffer(q);
   14548              41 :     destroyPQExpBuffer(delq);
   14549                 : }
   14550                 : 
   14551                 : /*
   14552                 :  * dumpForeignServer
   14553 ECB             :  *    write out a foreign server definition
   14554                 :  */
   14555                 : static void
   14556 CBC          49 : dumpForeignServer(Archive *fout, const ForeignServerInfo *srvinfo)
   14557 ECB             : {
   14558 CBC          49 :     DumpOptions *dopt = fout->dopt;
   14559                 :     PQExpBuffer q;
   14560 ECB             :     PQExpBuffer delq;
   14561                 :     PQExpBuffer query;
   14562                 :     PGresult   *res;
   14563                 :     char       *qsrvname;
   14564                 :     char       *fdwname;
   14565                 : 
   14566                 :     /* Do nothing in data-only dump */
   14567 CBC          49 :     if (dopt->dataOnly)
   14568               6 :         return;
   14569 ECB             : 
   14570 GIC          43 :     q = createPQExpBuffer();
   14571 CBC          43 :     delq = createPQExpBuffer();
   14572              43 :     query = createPQExpBuffer();
   14573                 : 
   14574              43 :     qsrvname = pg_strdup(fmtId(srvinfo->dobj.name));
   14575 ECB             : 
   14576                 :     /* look up the foreign-data wrapper */
   14577 GIC          43 :     appendPQExpBuffer(query, "SELECT fdwname "
   14578 ECB             :                       "FROM pg_foreign_data_wrapper w "
   14579                 :                       "WHERE w.oid = '%u'",
   14580 GIC          43 :                       srvinfo->srvfdw);
   14581 CBC          43 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   14582              43 :     fdwname = PQgetvalue(res, 0, 0);
   14583                 : 
   14584              43 :     appendPQExpBuffer(q, "CREATE SERVER %s", qsrvname);
   14585 GIC          43 :     if (srvinfo->srvtype && strlen(srvinfo->srvtype) > 0)
   14586 ECB             :     {
   14587 LBC           0 :         appendPQExpBufferStr(q, " TYPE ");
   14588 UIC           0 :         appendStringLiteralAH(q, srvinfo->srvtype, fout);
   14589 ECB             :     }
   14590 CBC          43 :     if (srvinfo->srvversion && strlen(srvinfo->srvversion) > 0)
   14591                 :     {
   14592 LBC           0 :         appendPQExpBufferStr(q, " VERSION ");
   14593 UIC           0 :         appendStringLiteralAH(q, srvinfo->srvversion, fout);
   14594 ECB             :     }
   14595                 : 
   14596 CBC          43 :     appendPQExpBufferStr(q, " FOREIGN DATA WRAPPER ");
   14597 GIC          43 :     appendPQExpBufferStr(q, fmtId(fdwname));
   14598                 : 
   14599              43 :     if (srvinfo->srvoptions && strlen(srvinfo->srvoptions) > 0)
   14600 UIC           0 :         appendPQExpBuffer(q, " OPTIONS (\n    %s\n)", srvinfo->srvoptions);
   14601                 : 
   14602 GIC          43 :     appendPQExpBufferStr(q, ";\n");
   14603                 : 
   14604              43 :     appendPQExpBuffer(delq, "DROP SERVER %s;\n",
   14605 ECB             :                       qsrvname);
   14606                 : 
   14607 CBC          43 :     if (dopt->binary_upgrade)
   14608               2 :         binary_upgrade_extension_member(q, &srvinfo->dobj,
   14609                 :                                         "SERVER", qsrvname, NULL);
   14610 ECB             : 
   14611 CBC          43 :     if (srvinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   14612              43 :         ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
   14613              43 :                      ARCHIVE_OPTS(.tag = srvinfo->dobj.name,
   14614                 :                                   .owner = srvinfo->rolname,
   14615                 :                                   .description = "SERVER",
   14616                 :                                   .section = SECTION_PRE_DATA,
   14617                 :                                   .createStmt = q->data,
   14618                 :                                   .dropStmt = delq->data));
   14619                 : 
   14620                 :     /* Dump Foreign Server Comments */
   14621              43 :     if (srvinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   14622 UIC           0 :         dumpComment(fout, "SERVER", qsrvname,
   14623 LBC           0 :                     NULL, srvinfo->rolname,
   14624 UIC           0 :                     srvinfo->dobj.catId, 0, srvinfo->dobj.dumpId);
   14625                 : 
   14626                 :     /* Handle the ACL */
   14627 GIC          43 :     if (srvinfo->dobj.dump & DUMP_COMPONENT_ACL)
   14628              35 :         dumpACL(fout, srvinfo->dobj.dumpId, InvalidDumpId,
   14629 ECB             :                 "FOREIGN SERVER", qsrvname, NULL,
   14630 CBC          35 :                 NULL, srvinfo->rolname, &srvinfo->dacl);
   14631                 : 
   14632 ECB             :     /* Dump user mappings */
   14633 CBC          43 :     if (srvinfo->dobj.dump & DUMP_COMPONENT_USERMAP)
   14634 GIC          43 :         dumpUserMappings(fout,
   14635 CBC          43 :                          srvinfo->dobj.name, NULL,
   14636 GIC          43 :                          srvinfo->rolname,
   14637 CBC          43 :                          srvinfo->dobj.catId, srvinfo->dobj.dumpId);
   14638 ECB             : 
   14639 GIC          43 :     PQclear(res);
   14640 ECB             : 
   14641 GBC          43 :     free(qsrvname);
   14642 EUB             : 
   14643 CBC          43 :     destroyPQExpBuffer(q);
   14644              43 :     destroyPQExpBuffer(delq);
   14645 GIC          43 :     destroyPQExpBuffer(query);
   14646 ECB             : }
   14647                 : 
   14648                 : /*
   14649                 :  * dumpUserMappings
   14650                 :  *
   14651                 :  * This routine is used to dump any user mappings associated with the
   14652                 :  * server handed to this routine. Should be called after ArchiveEntry()
   14653                 :  * for the server.
   14654                 :  */
   14655                 : static void
   14656 CBC          43 : dumpUserMappings(Archive *fout,
   14657                 :                  const char *servername, const char *namespace,
   14658                 :                  const char *owner,
   14659                 :                  CatalogId catalogId, DumpId dumpId)
   14660                 : {
   14661                 :     PQExpBuffer q;
   14662                 :     PQExpBuffer delq;
   14663                 :     PQExpBuffer query;
   14664 ECB             :     PQExpBuffer tag;
   14665                 :     PGresult   *res;
   14666                 :     int         ntups;
   14667                 :     int         i_usename;
   14668                 :     int         i_umoptions;
   14669                 :     int         i;
   14670                 : 
   14671 CBC          43 :     q = createPQExpBuffer();
   14672 GIC          43 :     tag = createPQExpBuffer();
   14673              43 :     delq = createPQExpBuffer();
   14674              43 :     query = createPQExpBuffer();
   14675                 : 
   14676                 :     /*
   14677                 :      * We read from the publicly accessible view pg_user_mappings, so as not
   14678                 :      * to fail if run by a non-superuser.  Note that the view will show
   14679 ECB             :      * umoptions as null if the user hasn't got privileges for the associated
   14680                 :      * server; this means that pg_dump will dump such a mapping, but with no
   14681                 :      * OPTIONS clause.  A possible alternative is to skip such mappings
   14682                 :      * altogether, but it's not clear that that's an improvement.
   14683                 :      */
   14684 GIC          43 :     appendPQExpBuffer(query,
   14685                 :                       "SELECT usename, "
   14686                 :                       "array_to_string(ARRAY("
   14687                 :                       "SELECT quote_ident(option_name) || ' ' || "
   14688                 :                       "quote_literal(option_value) "
   14689                 :                       "FROM pg_options_to_table(umoptions) "
   14690                 :                       "ORDER BY option_name"
   14691                 :                       "), E',\n    ') AS umoptions "
   14692                 :                       "FROM pg_user_mappings "
   14693                 :                       "WHERE srvid = '%u' "
   14694                 :                       "ORDER BY usename",
   14695 ECB             :                       catalogId.oid);
   14696                 : 
   14697 GIC          43 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   14698 ECB             : 
   14699 CBC          43 :     ntups = PQntuples(res);
   14700              43 :     i_usename = PQfnumber(res, "usename");
   14701 GIC          43 :     i_umoptions = PQfnumber(res, "umoptions");
   14702 ECB             : 
   14703 GIC          78 :     for (i = 0; i < ntups; i++)
   14704                 :     {
   14705 ECB             :         char       *usename;
   14706                 :         char       *umoptions;
   14707                 : 
   14708 CBC          35 :         usename = PQgetvalue(res, i, i_usename);
   14709              35 :         umoptions = PQgetvalue(res, i, i_umoptions);
   14710 ECB             : 
   14711 CBC          35 :         resetPQExpBuffer(q);
   14712 GIC          35 :         appendPQExpBuffer(q, "CREATE USER MAPPING FOR %s", fmtId(usename));
   14713 CBC          35 :         appendPQExpBuffer(q, " SERVER %s", fmtId(servername));
   14714 ECB             : 
   14715 GIC          35 :         if (umoptions && strlen(umoptions) > 0)
   14716 LBC           0 :             appendPQExpBuffer(q, " OPTIONS (\n    %s\n)", umoptions);
   14717 ECB             : 
   14718 GIC          35 :         appendPQExpBufferStr(q, ";\n");
   14719 ECB             : 
   14720 GIC          35 :         resetPQExpBuffer(delq);
   14721 CBC          35 :         appendPQExpBuffer(delq, "DROP USER MAPPING FOR %s", fmtId(usename));
   14722              35 :         appendPQExpBuffer(delq, " SERVER %s;\n", fmtId(servername));
   14723                 : 
   14724 GIC          35 :         resetPQExpBuffer(tag);
   14725              35 :         appendPQExpBuffer(tag, "USER MAPPING %s SERVER %s",
   14726                 :                           usename, servername);
   14727                 : 
   14728              35 :         ArchiveEntry(fout, nilCatalogId, createDumpId(),
   14729              35 :                      ARCHIVE_OPTS(.tag = tag->data,
   14730 ECB             :                                   .namespace = namespace,
   14731                 :                                   .owner = owner,
   14732                 :                                   .description = "USER MAPPING",
   14733                 :                                   .section = SECTION_PRE_DATA,
   14734                 :                                   .createStmt = q->data,
   14735                 :                                   .dropStmt = delq->data));
   14736                 :     }
   14737                 : 
   14738 CBC          43 :     PQclear(res);
   14739                 : 
   14740              43 :     destroyPQExpBuffer(query);
   14741              43 :     destroyPQExpBuffer(delq);
   14742 GIC          43 :     destroyPQExpBuffer(tag);
   14743 CBC          43 :     destroyPQExpBuffer(q);
   14744              43 : }
   14745                 : 
   14746                 : /*
   14747 ECB             :  * Write out default privileges information
   14748                 :  */
   14749                 : static void
   14750 CBC         154 : dumpDefaultACL(Archive *fout, const DefaultACLInfo *daclinfo)
   14751                 : {
   14752             154 :     DumpOptions *dopt = fout->dopt;
   14753                 :     PQExpBuffer q;
   14754                 :     PQExpBuffer tag;
   14755                 :     const char *type;
   14756 ECB             : 
   14757                 :     /* Do nothing in data-only dump, or if we're skipping ACLs */
   14758 GIC         154 :     if (dopt->dataOnly || dopt->aclsSkip)
   14759 CBC          16 :         return;
   14760 ECB             : 
   14761 GIC         138 :     q = createPQExpBuffer();
   14762 CBC         138 :     tag = createPQExpBuffer();
   14763                 : 
   14764             138 :     switch (daclinfo->defaclobjtype)
   14765 ECB             :     {
   14766 GIC          69 :         case DEFACLOBJ_RELATION:
   14767 CBC          69 :             type = "TABLES";
   14768              69 :             break;
   14769 UIC           0 :         case DEFACLOBJ_SEQUENCE:
   14770 LBC           0 :             type = "SEQUENCES";
   14771 UIC           0 :             break;
   14772 CBC          69 :         case DEFACLOBJ_FUNCTION:
   14773              69 :             type = "FUNCTIONS";
   14774              69 :             break;
   14775 UIC           0 :         case DEFACLOBJ_TYPE:
   14776               0 :             type = "TYPES";
   14777               0 :             break;
   14778               0 :         case DEFACLOBJ_NAMESPACE:
   14779               0 :             type = "SCHEMAS";
   14780               0 :             break;
   14781               0 :         default:
   14782                 :             /* shouldn't get here */
   14783 LBC           0 :             pg_fatal("unrecognized object type in default privileges: %d",
   14784 ECB             :                      (int) daclinfo->defaclobjtype);
   14785                 :             type = "";            /* keep compiler quiet */
   14786                 :     }
   14787                 : 
   14788 CBC         138 :     appendPQExpBuffer(tag, "DEFAULT PRIVILEGES FOR %s", type);
   14789 ECB             : 
   14790                 :     /* build the actual command(s) for this tuple */
   14791 CBC         138 :     if (!buildDefaultACLCommands(type,
   14792 GIC         138 :                                  daclinfo->dobj.namespace != NULL ?
   14793              70 :                                  daclinfo->dobj.namespace->dobj.name : NULL,
   14794             138 :                                  daclinfo->dacl.acl,
   14795             138 :                                  daclinfo->dacl.acldefault,
   14796             138 :                                  daclinfo->defaclrole,
   14797                 :                                  fout->remoteVersion,
   14798                 :                                  q))
   14799 LBC           0 :         pg_fatal("could not parse default ACL list (%s)",
   14800                 :                  daclinfo->dacl.acl);
   14801 ECB             : 
   14802 GIC         138 :     if (daclinfo->dobj.dump & DUMP_COMPONENT_ACL)
   14803             138 :         ArchiveEntry(fout, daclinfo->dobj.catId, daclinfo->dobj.dumpId,
   14804             138 :                      ARCHIVE_OPTS(.tag = tag->data,
   14805                 :                                   .namespace = daclinfo->dobj.namespace ?
   14806                 :                                   daclinfo->dobj.namespace->dobj.name : NULL,
   14807 ECB             :                                   .owner = daclinfo->defaclrole,
   14808                 :                                   .description = "DEFAULT ACL",
   14809                 :                                   .section = SECTION_POST_DATA,
   14810                 :                                   .createStmt = q->data));
   14811                 : 
   14812 GIC         138 :     destroyPQExpBuffer(tag);
   14813 CBC         138 :     destroyPQExpBuffer(q);
   14814                 : }
   14815 ECB             : 
   14816                 : /*----------
   14817                 :  * Write out grant/revoke information
   14818                 :  *
   14819 EUB             :  * 'objDumpId' is the dump ID of the underlying object.
   14820                 :  * 'altDumpId' can be a second dumpId that the ACL entry must also depend on,
   14821 ECB             :  *      or InvalidDumpId if there is no need for a second dependency.
   14822 EUB             :  * 'type' must be one of
   14823                 :  *      TABLE, SEQUENCE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, TABLESPACE,
   14824 ECB             :  *      FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT.
   14825 EUB             :  * 'name' is the formatted name of the object.  Must be quoted etc. already.
   14826                 :  * 'subname' is the formatted name of the sub-object, if any.  Must be quoted.
   14827 ECB             :  *      (Currently we assume that subname is only provided for table columns.)
   14828                 :  * 'nspname' is the namespace the object is in (NULL if none).
   14829                 :  * 'owner' is the owner, NULL if there is no owner (for languages).
   14830                 :  * 'dacl' is the DumpableAcl struct fpr the object.
   14831                 :  *
   14832                 :  * Returns the dump ID assigned to the ACL TocEntry, or InvalidDumpId if
   14833                 :  * no ACL entry was created.
   14834                 :  *----------
   14835                 :  */
   14836                 : static DumpId
   14837 CBC       18280 : dumpACL(Archive *fout, DumpId objDumpId, DumpId altDumpId,
   14838 ECB             :         const char *type, const char *name, const char *subname,
   14839                 :         const char *nspname, const char *owner,
   14840                 :         const DumpableAcl *dacl)
   14841                 : {
   14842 GIC       18280 :     DumpId      aclDumpId = InvalidDumpId;
   14843           18280 :     DumpOptions *dopt = fout->dopt;
   14844           18280 :     const char *acls = dacl->acl;
   14845           18280 :     const char *acldefault = dacl->acldefault;
   14846           18280 :     char        privtype = dacl->privtype;
   14847 CBC       18280 :     const char *initprivs = dacl->initprivs;
   14848 EUB             :     const char *baseacls;
   14849                 :     PQExpBuffer sql;
   14850                 : 
   14851                 :     /* Do nothing if ACL dump is not enabled */
   14852 GIC       18280 :     if (dopt->aclsSkip)
   14853 CBC         312 :         return InvalidDumpId;
   14854 ECB             : 
   14855                 :     /* --data-only skips ACLs *except* large object ACLs */
   14856 CBC       17968 :     if (dopt->dataOnly && strcmp(type, "LARGE OBJECT") != 0)
   14857 UIC           0 :         return InvalidDumpId;
   14858 ECB             : 
   14859 GIC       17968 :     sql = createPQExpBuffer();
   14860 ECB             : 
   14861                 :     /*
   14862                 :      * In binary upgrade mode, we don't run an extension's script but instead
   14863                 :      * dump out the objects independently and then recreate them.  To preserve
   14864                 :      * any initial privileges which were set on extension objects, we need to
   14865                 :      * compute the set of GRANT and REVOKE commands necessary to get from the
   14866                 :      * default privileges of an object to its initial privileges as recorded
   14867                 :      * in pg_init_privs.
   14868                 :      *
   14869                 :      * At restore time, we apply these commands after having called
   14870                 :      * binary_upgrade_set_record_init_privs(true).  That tells the backend to
   14871                 :      * copy the results into pg_init_privs.  This is how we preserve the
   14872                 :      * contents of that catalog across binary upgrades.
   14873                 :      */
   14874 GIC       17968 :     if (dopt->binary_upgrade && privtype == 'e' &&
   14875              11 :         initprivs && *initprivs != '\0')
   14876                 :     {
   14877              11 :         appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n");
   14878              11 :         if (!buildACLCommands(name, subname, nspname, type,
   14879                 :                               initprivs, acldefault, owner,
   14880 ECB             :                               "", fout->remoteVersion, sql))
   14881 LBC           0 :             pg_fatal("could not parse initial ACL list (%s) or default (%s) for object \"%s\" (%s)",
   14882                 :                      initprivs, acldefault, name, type);
   14883 CBC          11 :         appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n");
   14884 ECB             :     }
   14885                 : 
   14886                 :     /*
   14887                 :      * Now figure the GRANT and REVOKE commands needed to get to the object's
   14888                 :      * actual current ACL, starting from the initprivs if given, else from the
   14889                 :      * object-type-specific default.  Also, while buildACLCommands will assume
   14890                 :      * that a NULL/empty acls string means it needn't do anything, what that
   14891                 :      * actually represents is the object-type-specific default; so we need to
   14892                 :      * substitute the acldefault string to get the right results in that case.
   14893                 :      */
   14894 CBC       17968 :     if (initprivs && *initprivs != '\0')
   14895 ECB             :     {
   14896 GIC       16166 :         baseacls = initprivs;
   14897 CBC       16166 :         if (acls == NULL || *acls == '\0')
   14898              16 :             acls = acldefault;
   14899                 :     }
   14900 EUB             :     else
   14901 GBC        1802 :         baseacls = acldefault;
   14902                 : 
   14903 CBC       17968 :     if (!buildACLCommands(name, subname, nspname, type,
   14904                 :                           acls, baseacls, owner,
   14905 EUB             :                           "", fout->remoteVersion, sql))
   14906 UBC           0 :         pg_fatal("could not parse ACL list (%s) or default (%s) for object \"%s\" (%s)",
   14907                 :                  acls, baseacls, name, type);
   14908                 : 
   14909 CBC       17968 :     if (sql->len > 0)
   14910 ECB             :     {
   14911 GIC        1886 :         PQExpBuffer tag = createPQExpBuffer();
   14912 ECB             :         DumpId      aclDeps[2];
   14913 GBC        1886 :         int         nDeps = 0;
   14914                 : 
   14915 CBC        1886 :         if (subname)
   14916 GIC        1102 :             appendPQExpBuffer(tag, "COLUMN %s.%s", name, subname);
   14917 ECB             :         else
   14918 GIC         784 :             appendPQExpBuffer(tag, "%s %s", type, name);
   14919                 : 
   14920 CBC        1886 :         aclDeps[nDeps++] = objDumpId;
   14921            1886 :         if (altDumpId != InvalidDumpId)
   14922 GIC        1022 :             aclDeps[nDeps++] = altDumpId;
   14923                 : 
   14924 CBC        1886 :         aclDumpId = createDumpId();
   14925 ECB             : 
   14926 CBC        1886 :         ArchiveEntry(fout, nilCatalogId, aclDumpId,
   14927 GIC        1886 :                      ARCHIVE_OPTS(.tag = tag->data,
   14928                 :                                   .namespace = nspname,
   14929                 :                                   .owner = owner,
   14930                 :                                   .description = "ACL",
   14931                 :                                   .section = SECTION_NONE,
   14932                 :                                   .createStmt = sql->data,
   14933                 :                                   .deps = aclDeps,
   14934 ECB             :                                   .nDeps = nDeps));
   14935 EUB             : 
   14936 GBC        1886 :         destroyPQExpBuffer(tag);
   14937 EUB             :     }
   14938                 : 
   14939 GIC       17968 :     destroyPQExpBuffer(sql);
   14940 ECB             : 
   14941 CBC       17968 :     return aclDumpId;
   14942                 : }
   14943 ECB             : 
   14944                 : /*
   14945                 :  * dumpSecLabel
   14946                 :  *
   14947                 :  * This routine is used to dump any security labels associated with the
   14948                 :  * object handed to this routine. The routine takes the object type
   14949                 :  * and object name (ready to print, except for schema decoration), plus
   14950                 :  * the namespace and owner of the object (for labeling the ArchiveEntry),
   14951                 :  * plus catalog ID and subid which are the lookup key for pg_seclabel,
   14952                 :  * plus the dump ID for the object (for setting a dependency).
   14953                 :  * If a matching pg_seclabel entry is found, it is dumped.
   14954                 :  *
   14955                 :  * Note: although this routine takes a dumpId for dependency purposes,
   14956                 :  * that purpose is just to mark the dependency in the emitted dump file
   14957                 :  * for possible future use by pg_restore.  We do NOT use it for determining
   14958                 :  * ordering of the label in the dump file, because this routine is called
   14959                 :  * after dependency sorting occurs.  This routine should be called just after
   14960                 :  * calling ArchiveEntry() for the specified object.
   14961                 :  */
   14962                 : static void
   14963 UIC           0 : dumpSecLabel(Archive *fout, const char *type, const char *name,
   14964                 :              const char *namespace, const char *owner,
   14965                 :              CatalogId catalogId, int subid, DumpId dumpId)
   14966                 : {
   14967               0 :     DumpOptions *dopt = fout->dopt;
   14968                 :     SecLabelItem *labels;
   14969 ECB             :     int         nlabels;
   14970                 :     int         i;
   14971                 :     PQExpBuffer query;
   14972                 : 
   14973                 :     /* do nothing, if --no-security-labels is supplied */
   14974 UIC           0 :     if (dopt->no_security_labels)
   14975               0 :         return;
   14976                 : 
   14977                 :     /* Security labels are schema not data ... except large object labels are data */
   14978               0 :     if (strcmp(type, "LARGE OBJECT") != 0)
   14979                 :     {
   14980               0 :         if (dopt->dataOnly)
   14981               0 :             return;
   14982                 :     }
   14983                 :     else
   14984 ECB             :     {
   14985                 :         /* We do dump large object security labels in binary-upgrade mode */
   14986 LBC           0 :         if (dopt->schemaOnly && !dopt->binary_upgrade)
   14987               0 :             return;
   14988                 :     }
   14989                 : 
   14990                 :     /* Search for security labels associated with catalogId, using table */
   14991 UIC           0 :     nlabels = findSecLabels(catalogId.tableoid, catalogId.oid, &labels);
   14992                 : 
   14993               0 :     query = createPQExpBuffer();
   14994                 : 
   14995               0 :     for (i = 0; i < nlabels; i++)
   14996                 :     {
   14997 ECB             :         /*
   14998                 :          * Ignore label entries for which the subid doesn't match.
   14999                 :          */
   15000 UIC           0 :         if (labels[i].objsubid != subid)
   15001               0 :             continue;
   15002                 : 
   15003               0 :         appendPQExpBuffer(query,
   15004                 :                           "SECURITY LABEL FOR %s ON %s ",
   15005               0 :                           fmtId(labels[i].provider), type);
   15006               0 :         if (namespace && *namespace)
   15007               0 :             appendPQExpBuffer(query, "%s.", fmtId(namespace));
   15008               0 :         appendPQExpBuffer(query, "%s IS ", name);
   15009               0 :         appendStringLiteralAH(query, labels[i].label, fout);
   15010 LBC           0 :         appendPQExpBufferStr(query, ";\n");
   15011                 :     }
   15012 ECB             : 
   15013 LBC           0 :     if (query->len > 0)
   15014 ECB             :     {
   15015 UIC           0 :         PQExpBuffer tag = createPQExpBuffer();
   15016 ECB             : 
   15017 UIC           0 :         appendPQExpBuffer(tag, "%s %s", type, name);
   15018               0 :         ArchiveEntry(fout, nilCatalogId, createDumpId(),
   15019               0 :                      ARCHIVE_OPTS(.tag = tag->data,
   15020                 :                                   .namespace = namespace,
   15021 ECB             :                                   .owner = owner,
   15022                 :                                   .description = "SECURITY LABEL",
   15023                 :                                   .section = SECTION_NONE,
   15024                 :                                   .createStmt = query->data,
   15025                 :                                   .deps = &dumpId,
   15026                 :                                   .nDeps = 1));
   15027 UIC           0 :         destroyPQExpBuffer(tag);
   15028 ECB             :     }
   15029 EUB             : 
   15030 UIC           0 :     destroyPQExpBuffer(query);
   15031 ECB             : }
   15032                 : 
   15033                 : /*
   15034                 :  * dumpTableSecLabel
   15035                 :  *
   15036                 :  * As above, but dump security label for both the specified table (or view)
   15037                 :  * and its columns.
   15038                 :  */
   15039                 : static void
   15040 UIC           0 : dumpTableSecLabel(Archive *fout, const TableInfo *tbinfo, const char *reltypename)
   15041 ECB             : {
   15042 LBC           0 :     DumpOptions *dopt = fout->dopt;
   15043                 :     SecLabelItem *labels;
   15044                 :     int         nlabels;
   15045                 :     int         i;
   15046                 :     PQExpBuffer query;
   15047                 :     PQExpBuffer target;
   15048                 : 
   15049                 :     /* do nothing, if --no-security-labels is supplied */
   15050 UIC           0 :     if (dopt->no_security_labels)
   15051 LBC           0 :         return;
   15052                 : 
   15053 ECB             :     /* SecLabel are SCHEMA not data */
   15054 LBC           0 :     if (dopt->dataOnly)
   15055               0 :         return;
   15056 ECB             : 
   15057                 :     /* Search for comments associated with relation, using table */
   15058 UIC           0 :     nlabels = findSecLabels(tbinfo->dobj.catId.tableoid,
   15059               0 :                             tbinfo->dobj.catId.oid,
   15060                 :                             &labels);
   15061                 : 
   15062                 :     /* If security labels exist, build SECURITY LABEL statements */
   15063 LBC           0 :     if (nlabels <= 0)
   15064 UIC           0 :         return;
   15065 ECB             : 
   15066 UIC           0 :     query = createPQExpBuffer();
   15067               0 :     target = createPQExpBuffer();
   15068                 : 
   15069               0 :     for (i = 0; i < nlabels; i++)
   15070                 :     {
   15071 ECB             :         const char *colname;
   15072 LBC           0 :         const char *provider = labels[i].provider;
   15073 UIC           0 :         const char *label = labels[i].label;
   15074 LBC           0 :         int         objsubid = labels[i].objsubid;
   15075 ECB             : 
   15076 UIC           0 :         resetPQExpBuffer(target);
   15077 LBC           0 :         if (objsubid == 0)
   15078                 :         {
   15079               0 :             appendPQExpBuffer(target, "%s %s", reltypename,
   15080               0 :                               fmtQualifiedDumpable(tbinfo));
   15081 ECB             :         }
   15082 EUB             :         else
   15083                 :         {
   15084 UBC           0 :             colname = getAttrName(objsubid, tbinfo);
   15085 ECB             :             /* first fmtXXX result must be consumed before calling again */
   15086 LBC           0 :             appendPQExpBuffer(target, "COLUMN %s",
   15087               0 :                               fmtQualifiedDumpable(tbinfo));
   15088 UBC           0 :             appendPQExpBuffer(target, ".%s", fmtId(colname));
   15089 EUB             :         }
   15090 UBC           0 :         appendPQExpBuffer(query, "SECURITY LABEL FOR %s ON %s IS ",
   15091 EUB             :                           fmtId(provider), target->data);
   15092 UBC           0 :         appendStringLiteralAH(query, label, fout);
   15093               0 :         appendPQExpBufferStr(query, ";\n");
   15094 EUB             :     }
   15095 UIC           0 :     if (query->len > 0)
   15096 EUB             :     {
   15097 UIC           0 :         resetPQExpBuffer(target);
   15098               0 :         appendPQExpBuffer(target, "%s %s", reltypename,
   15099               0 :                           fmtId(tbinfo->dobj.name));
   15100               0 :         ArchiveEntry(fout, nilCatalogId, createDumpId(),
   15101 LBC           0 :                      ARCHIVE_OPTS(.tag = target->data,
   15102                 :                                   .namespace = tbinfo->dobj.namespace->dobj.name,
   15103                 :                                   .owner = tbinfo->rolname,
   15104 ECB             :                                   .description = "SECURITY LABEL",
   15105                 :                                   .section = SECTION_NONE,
   15106                 :                                   .createStmt = query->data,
   15107                 :                                   .deps = &(tbinfo->dobj.dumpId),
   15108                 :                                   .nDeps = 1));
   15109                 :     }
   15110 UIC           0 :     destroyPQExpBuffer(query);
   15111               0 :     destroyPQExpBuffer(target);
   15112 EUB             : }
   15113                 : 
   15114                 : /*
   15115 ECB             :  * findSecLabels
   15116                 :  *
   15117                 :  * Find the security label(s), if any, associated with the given object.
   15118                 :  * All the objsubid values associated with the given classoid/objoid are
   15119                 :  * found with one search.
   15120                 :  */
   15121                 : static int
   15122 UIC           0 : findSecLabels(Oid classoid, Oid objoid, SecLabelItem **items)
   15123                 : {
   15124               0 :     SecLabelItem *middle = NULL;
   15125 ECB             :     SecLabelItem *low;
   15126                 :     SecLabelItem *high;
   15127                 :     int         nmatch;
   15128                 : 
   15129 UIC           0 :     if (nseclabels <= 0)     /* no labels, so no match is possible */
   15130                 :     {
   15131               0 :         *items = NULL;
   15132               0 :         return 0;
   15133                 :     }
   15134                 : 
   15135                 :     /*
   15136                 :      * Do binary search to find some item matching the object.
   15137                 :      */
   15138               0 :     low = &seclabels[0];
   15139               0 :     high = &seclabels[nseclabels - 1];
   15140               0 :     while (low <= high)
   15141                 :     {
   15142               0 :         middle = low + (high - low) / 2;
   15143                 : 
   15144               0 :         if (classoid < middle->classoid)
   15145               0 :             high = middle - 1;
   15146               0 :         else if (classoid > middle->classoid)
   15147               0 :             low = middle + 1;
   15148               0 :         else if (objoid < middle->objoid)
   15149               0 :             high = middle - 1;
   15150 LBC           0 :         else if (objoid > middle->objoid)
   15151 UIC           0 :             low = middle + 1;
   15152                 :         else
   15153               0 :             break;              /* found a match */
   15154                 :     }
   15155 ECB             : 
   15156 LBC           0 :     if (low > high)              /* no matches */
   15157 ECB             :     {
   15158 LBC           0 :         *items = NULL;
   15159               0 :         return 0;
   15160 ECB             :     }
   15161                 : 
   15162                 :     /*
   15163                 :      * Now determine how many items match the object.  The search loop
   15164                 :      * invariant still holds: only items between low and high inclusive could
   15165                 :      * match.
   15166                 :      */
   15167 UIC           0 :     nmatch = 1;
   15168               0 :     while (middle > low)
   15169 ECB             :     {
   15170 UBC           0 :         if (classoid != middle[-1].classoid ||
   15171 UIC           0 :             objoid != middle[-1].objoid)
   15172 ECB             :             break;
   15173 UIC           0 :         middle--;
   15174               0 :         nmatch++;
   15175                 :     }
   15176                 : 
   15177               0 :     *items = middle;
   15178                 : 
   15179               0 :     middle += nmatch;
   15180               0 :     while (middle <= high)
   15181                 :     {
   15182               0 :         if (classoid != middle->classoid ||
   15183               0 :             objoid != middle->objoid)
   15184                 :             break;
   15185               0 :         middle++;
   15186               0 :         nmatch++;
   15187 ECB             :     }
   15188                 : 
   15189 UIC           0 :     return nmatch;
   15190 ECB             : }
   15191                 : 
   15192                 : /*
   15193                 :  * collectSecLabels
   15194 EUB             :  *
   15195                 :  * Construct a table of all security labels available for database objects;
   15196 ECB             :  * also set the has-seclabel component flag for each relevant object.
   15197                 :  *
   15198                 :  * The table is sorted by classoid/objid/objsubid for speed in lookup.
   15199                 :  */
   15200                 : static void
   15201 GIC         118 : collectSecLabels(Archive *fout)
   15202                 : {
   15203                 :     PGresult   *res;
   15204                 :     PQExpBuffer query;
   15205                 :     int         i_label;
   15206                 :     int         i_provider;
   15207 ECB             :     int         i_classoid;
   15208                 :     int         i_objoid;
   15209                 :     int         i_objsubid;
   15210                 :     int         ntups;
   15211                 :     int         i;
   15212                 :     DumpableObject *dobj;
   15213                 : 
   15214 CBC         118 :     query = createPQExpBuffer();
   15215                 : 
   15216             118 :     appendPQExpBufferStr(query,
   15217                 :                          "SELECT label, provider, classoid, objoid, objsubid "
   15218                 :                          "FROM pg_catalog.pg_seclabel "
   15219 EUB             :                          "ORDER BY classoid, objoid, objsubid");
   15220                 : 
   15221 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   15222 ECB             : 
   15223                 :     /* Construct lookup table containing OIDs in numeric form */
   15224 CBC         118 :     i_label = PQfnumber(res, "label");
   15225 GIC         118 :     i_provider = PQfnumber(res, "provider");
   15226 CBC         118 :     i_classoid = PQfnumber(res, "classoid");
   15227 GIC         118 :     i_objoid = PQfnumber(res, "objoid");
   15228 CBC         118 :     i_objsubid = PQfnumber(res, "objsubid");
   15229 ECB             : 
   15230 GIC         118 :     ntups = PQntuples(res);
   15231 ECB             : 
   15232 GIC         118 :     seclabels = (SecLabelItem *) pg_malloc(ntups * sizeof(SecLabelItem));
   15233 CBC         118 :     nseclabels = 0;
   15234             118 :     dobj = NULL;
   15235 ECB             : 
   15236 GIC         118 :     for (i = 0; i < ntups; i++)
   15237 ECB             :     {
   15238                 :         CatalogId   objId;
   15239                 :         int         subid;
   15240                 : 
   15241 UIC           0 :         objId.tableoid = atooid(PQgetvalue(res, i, i_classoid));
   15242               0 :         objId.oid = atooid(PQgetvalue(res, i, i_objoid));
   15243               0 :         subid = atoi(PQgetvalue(res, i, i_objsubid));
   15244                 : 
   15245                 :         /* We needn't remember labels that don't match any dumpable object */
   15246               0 :         if (dobj == NULL ||
   15247               0 :             dobj->catId.tableoid != objId.tableoid ||
   15248               0 :             dobj->catId.oid != objId.oid)
   15249 LBC           0 :             dobj = findObjectByCatalogId(objId);
   15250 UIC           0 :         if (dobj == NULL)
   15251               0 :             continue;
   15252 ECB             : 
   15253                 :         /*
   15254                 :          * Labels on columns of composite types are linked to the type's
   15255                 :          * pg_class entry, but we need to set the DUMP_COMPONENT_SECLABEL flag
   15256                 :          * in the type's own DumpableObject.
   15257                 :          */
   15258 UIC           0 :         if (subid != 0 && dobj->objType == DO_TABLE &&
   15259               0 :             ((TableInfo *) dobj)->relkind == RELKIND_COMPOSITE_TYPE)
   15260               0 :         {
   15261                 :             TypeInfo   *cTypeInfo;
   15262                 : 
   15263               0 :             cTypeInfo = findTypeByOid(((TableInfo *) dobj)->reltype);
   15264               0 :             if (cTypeInfo)
   15265               0 :                 cTypeInfo->dobj.components |= DUMP_COMPONENT_SECLABEL;
   15266                 :         }
   15267                 :         else
   15268               0 :             dobj->components |= DUMP_COMPONENT_SECLABEL;
   15269                 : 
   15270               0 :         seclabels[nseclabels].label = pg_strdup(PQgetvalue(res, i, i_label));
   15271               0 :         seclabels[nseclabels].provider = pg_strdup(PQgetvalue(res, i, i_provider));
   15272               0 :         seclabels[nseclabels].classoid = objId.tableoid;
   15273               0 :         seclabels[nseclabels].objoid = objId.oid;
   15274               0 :         seclabels[nseclabels].objsubid = subid;
   15275               0 :         nseclabels++;
   15276 EUB             :     }
   15277                 : 
   15278 GIC         118 :     PQclear(res);
   15279             118 :     destroyPQExpBuffer(query);
   15280 GBC         118 : }
   15281                 : 
   15282                 : /*
   15283                 :  * dumpTable
   15284                 :  *    write out to fout the declarations (not data) of a user-defined table
   15285                 :  */
   15286                 : static void
   15287           20378 : dumpTable(Archive *fout, const TableInfo *tbinfo)
   15288 EUB             : {
   15289 GIC       20378 :     DumpOptions *dopt = fout->dopt;
   15290           20378 :     DumpId      tableAclDumpId = InvalidDumpId;
   15291 EUB             :     char       *namecopy;
   15292                 : 
   15293                 :     /* Do nothing in data-only dump */
   15294 GBC       20378 :     if (dopt->dataOnly)
   15295 GIC         831 :         return;
   15296                 : 
   15297           19547 :     if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   15298                 :     {
   15299 GBC        5015 :         if (tbinfo->relkind == RELKIND_SEQUENCE)
   15300             315 :             dumpSequence(fout, tbinfo);
   15301                 :         else
   15302 GIC        4700 :             dumpTableSchema(fout, tbinfo);
   15303                 :     }
   15304 EUB             : 
   15305                 :     /* Handle the ACL here */
   15306 GBC       19547 :     namecopy = pg_strdup(fmtId(tbinfo->dobj.name));
   15307 GIC       19547 :     if (tbinfo->dobj.dump & DUMP_COMPONENT_ACL)
   15308 EUB             :     {
   15309 GIC       14841 :         const char *objtype =
   15310           14841 :         (tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" : "TABLE";
   15311                 : 
   15312                 :         tableAclDumpId =
   15313 GBC       14841 :             dumpACL(fout, tbinfo->dobj.dumpId, InvalidDumpId,
   15314 EUB             :                     objtype, namecopy, NULL,
   15315 GIC       14841 :                     tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
   15316 EUB             :                     &tbinfo->dacl);
   15317                 :     }
   15318                 : 
   15319                 :     /*
   15320                 :      * Handle column ACLs, if any.  Note: we pull these with a separate query
   15321                 :      * rather than trying to fetch them during getTableAttrs, so that we won't
   15322                 :      * miss ACLs on system columns.  Doing it this way also allows us to dump
   15323                 :      * ACLs for catalogs that we didn't mark "interesting" back in getTables.
   15324                 :      */
   15325 GIC       19547 :     if ((tbinfo->dobj.dump & DUMP_COMPONENT_ACL) && tbinfo->hascolumnACLs)
   15326 EUB             :     {
   15327 GIC         196 :         PQExpBuffer query = createPQExpBuffer();
   15328 EUB             :         PGresult   *res;
   15329                 :         int         i;
   15330                 : 
   15331 GBC         196 :         if (!fout->is_prepared[PREPQUERY_GETCOLUMNACLS])
   15332 EUB             :         {
   15333                 :             /* Set up query for column ACLs */
   15334 GIC         103 :             appendPQExpBufferStr(query,
   15335                 :                                  "PREPARE getColumnACLs(pg_catalog.oid) AS\n");
   15336                 : 
   15337             103 :             if (fout->remoteVersion >= 90600)
   15338                 :             {
   15339                 :                 /*
   15340 EUB             :                  * In principle we should call acldefault('c', relowner) to
   15341                 :                  * get the default ACL for a column.  However, we don't
   15342                 :                  * currently store the numeric OID of the relowner in
   15343                 :                  * TableInfo.  We could convert the owner name using regrole,
   15344                 :                  * but that creates a risk of failure due to concurrent role
   15345                 :                  * renames.  Given that the default ACL for columns is empty
   15346                 :                  * and is likely to stay that way, it's not worth extra cycles
   15347                 :                  * and risk to avoid hard-wiring that knowledge here.
   15348                 :                  */
   15349 GIC         103 :                 appendPQExpBufferStr(query,
   15350                 :                                      "SELECT at.attname, "
   15351                 :                                      "at.attacl, "
   15352                 :                                      "'{}' AS acldefault, "
   15353 EUB             :                                      "pip.privtype, pip.initprivs "
   15354                 :                                      "FROM pg_catalog.pg_attribute at "
   15355                 :                                      "LEFT JOIN pg_catalog.pg_init_privs pip ON "
   15356                 :                                      "(at.attrelid = pip.objoid "
   15357                 :                                      "AND pip.classoid = 'pg_catalog.pg_class'::pg_catalog.regclass "
   15358                 :                                      "AND at.attnum = pip.objsubid) "
   15359                 :                                      "WHERE at.attrelid = $1 AND "
   15360                 :                                      "NOT at.attisdropped "
   15361                 :                                      "AND (at.attacl IS NOT NULL OR pip.initprivs IS NOT NULL) "
   15362                 :                                      "ORDER BY at.attnum");
   15363                 :             }
   15364                 :             else
   15365                 :             {
   15366 UIC           0 :                 appendPQExpBufferStr(query,
   15367 EUB             :                                      "SELECT attname, attacl, '{}' AS acldefault, "
   15368                 :                                      "NULL AS privtype, NULL AS initprivs "
   15369                 :                                      "FROM pg_catalog.pg_attribute "
   15370                 :                                      "WHERE attrelid = $1 AND NOT attisdropped "
   15371                 :                                      "AND attacl IS NOT NULL "
   15372                 :                                      "ORDER BY attnum");
   15373                 :             }
   15374                 : 
   15375 GIC         103 :             ExecuteSqlStatement(fout, query->data);
   15376 EUB             : 
   15377 GBC         103 :             fout->is_prepared[PREPQUERY_GETCOLUMNACLS] = true;
   15378                 :         }
   15379 EUB             : 
   15380 GBC         196 :         printfPQExpBuffer(query,
   15381                 :                           "EXECUTE getColumnACLs('%u')",
   15382             196 :                           tbinfo->dobj.catId.oid);
   15383                 : 
   15384 GIC         196 :         res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   15385 EUB             : 
   15386 GBC        2914 :         for (i = 0; i < PQntuples(res); i++)
   15387 EUB             :         {
   15388 GIC        2718 :             char       *attname = PQgetvalue(res, i, 0);
   15389 GBC        2718 :             char       *attacl = PQgetvalue(res, i, 1);
   15390            2718 :             char       *acldefault = PQgetvalue(res, i, 2);
   15391 GIC        2718 :             char        privtype = *(PQgetvalue(res, i, 3));
   15392 GBC        2718 :             char       *initprivs = PQgetvalue(res, i, 4);
   15393 EUB             :             DumpableAcl coldacl;
   15394                 :             char       *attnamecopy;
   15395                 : 
   15396 GIC        2718 :             coldacl.acl = attacl;
   15397 GBC        2718 :             coldacl.acldefault = acldefault;
   15398 GIC        2718 :             coldacl.privtype = privtype;
   15399 GBC        2718 :             coldacl.initprivs = initprivs;
   15400            2718 :             attnamecopy = pg_strdup(fmtId(attname));
   15401 EUB             : 
   15402                 :             /*
   15403                 :              * Column's GRANT type is always TABLE.  Each column ACL depends
   15404                 :              * on the table-level ACL, since we can restore column ACLs in
   15405                 :              * parallel but the table-level ACL has to be done first.
   15406                 :              */
   15407 GIC        2718 :             dumpACL(fout, tbinfo->dobj.dumpId, tableAclDumpId,
   15408 EUB             :                     "TABLE", namecopy, attnamecopy,
   15409 GIC        2718 :                     tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
   15410 EUB             :                     &coldacl);
   15411 GBC        2718 :             free(attnamecopy);
   15412 EUB             :         }
   15413 GBC         196 :         PQclear(res);
   15414             196 :         destroyPQExpBuffer(query);
   15415                 :     }
   15416                 : 
   15417 GIC       19547 :     free(namecopy);
   15418                 : }
   15419                 : 
   15420                 : /*
   15421                 :  * Create the AS clause for a view or materialized view. The semicolon is
   15422                 :  * stripped because a materialized view must add a WITH NO DATA clause.
   15423 EUB             :  *
   15424                 :  * This returns a new buffer which must be freed by the caller.
   15425                 :  */
   15426                 : static PQExpBuffer
   15427 GIC         599 : createViewAsClause(Archive *fout, const TableInfo *tbinfo)
   15428                 : {
   15429             599 :     PQExpBuffer query = createPQExpBuffer();
   15430             599 :     PQExpBuffer result = createPQExpBuffer();
   15431                 :     PGresult   *res;
   15432                 :     int         len;
   15433                 : 
   15434                 :     /* Fetch the view definition */
   15435 GBC         599 :     appendPQExpBuffer(query,
   15436                 :                       "SELECT pg_catalog.pg_get_viewdef('%u'::pg_catalog.oid) AS viewdef",
   15437             599 :                       tbinfo->dobj.catId.oid);
   15438                 : 
   15439 GIC         599 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   15440                 : 
   15441             599 :     if (PQntuples(res) != 1)
   15442 EUB             :     {
   15443 UIC           0 :         if (PQntuples(res) < 1)
   15444 UBC           0 :             pg_fatal("query to obtain definition of view \"%s\" returned no data",
   15445 EUB             :                      tbinfo->dobj.name);
   15446                 :         else
   15447 UIC           0 :             pg_fatal("query to obtain definition of view \"%s\" returned more than one definition",
   15448                 :                      tbinfo->dobj.name);
   15449                 :     }
   15450                 : 
   15451 GBC         599 :     len = PQgetlength(res, 0, 0);
   15452 EUB             : 
   15453 GBC         599 :     if (len == 0)
   15454 UIC           0 :         pg_fatal("definition of view \"%s\" appears to be empty (length zero)",
   15455 EUB             :                  tbinfo->dobj.name);
   15456                 : 
   15457                 :     /* Strip off the trailing semicolon so that other things may follow. */
   15458 GBC         599 :     Assert(PQgetvalue(res, 0, 0)[len - 1] == ';');
   15459             599 :     appendBinaryPQExpBuffer(result, PQgetvalue(res, 0, 0), len - 1);
   15460 EUB             : 
   15461 GBC         599 :     PQclear(res);
   15462             599 :     destroyPQExpBuffer(query);
   15463 EUB             : 
   15464 GBC         599 :     return result;
   15465                 : }
   15466 EUB             : 
   15467                 : /*
   15468                 :  * Create a dummy AS clause for a view.  This is used when the real view
   15469                 :  * definition has to be postponed because of circular dependencies.
   15470                 :  * We must duplicate the view's external properties -- column names and types
   15471                 :  * (including collation) -- so that it works for subsequent references.
   15472                 :  *
   15473                 :  * This returns a new buffer which must be freed by the caller.
   15474                 :  */
   15475                 : static PQExpBuffer
   15476 GIC          20 : createDummyViewAsClause(Archive *fout, const TableInfo *tbinfo)
   15477                 : {
   15478              20 :     PQExpBuffer result = createPQExpBuffer();
   15479                 :     int         j;
   15480 EUB             : 
   15481 GBC          20 :     appendPQExpBufferStr(result, "SELECT");
   15482                 : 
   15483              40 :     for (j = 0; j < tbinfo->numatts; j++)
   15484 EUB             :     {
   15485 GIC          20 :         if (j > 0)
   15486 GBC          10 :             appendPQExpBufferChar(result, ',');
   15487              20 :         appendPQExpBufferStr(result, "\n    ");
   15488                 : 
   15489 GIC          20 :         appendPQExpBuffer(result, "NULL::%s", tbinfo->atttypnames[j]);
   15490 EUB             : 
   15491                 :         /*
   15492                 :          * Must add collation if not default for the type, because CREATE OR
   15493                 :          * REPLACE VIEW won't change it
   15494                 :          */
   15495 GBC          20 :         if (OidIsValid(tbinfo->attcollation[j]))
   15496 EUB             :         {
   15497                 :             CollInfo   *coll;
   15498                 : 
   15499 UBC           0 :             coll = findCollationByOid(tbinfo->attcollation[j]);
   15500 UIC           0 :             if (coll)
   15501               0 :                 appendPQExpBuffer(result, " COLLATE %s",
   15502 UBC           0 :                                   fmtQualifiedDumpable(coll));
   15503                 :         }
   15504                 : 
   15505 GIC          20 :         appendPQExpBuffer(result, " AS %s", fmtId(tbinfo->attnames[j]));
   15506                 :     }
   15507                 : 
   15508              20 :     return result;
   15509                 : }
   15510                 : 
   15511                 : /*
   15512                 :  * dumpTableSchema
   15513                 :  *    write the declaration (not data) of one user-defined table or view
   15514 ECB             :  */
   15515                 : static void
   15516 GIC        4700 : dumpTableSchema(Archive *fout, const TableInfo *tbinfo)
   15517                 : {
   15518            4700 :     DumpOptions *dopt = fout->dopt;
   15519            4700 :     PQExpBuffer q = createPQExpBuffer();
   15520            4700 :     PQExpBuffer delq = createPQExpBuffer();
   15521                 :     char       *qrelname;
   15522                 :     char       *qualrelname;
   15523                 :     int         numParents;
   15524                 :     TableInfo **parents;
   15525                 :     int         actual_atts;    /* number of attrs in this CREATE statement */
   15526                 :     const char *reltypename;
   15527 ECB             :     char       *storage;
   15528                 :     int         j,
   15529                 :                 k;
   15530                 : 
   15531                 :     /* We had better have loaded per-column details about this table */
   15532 GIC        4700 :     Assert(tbinfo->interesting);
   15533                 : 
   15534 CBC        4700 :     qrelname = pg_strdup(fmtId(tbinfo->dobj.name));
   15535 GIC        4700 :     qualrelname = pg_strdup(fmtQualifiedDumpable(tbinfo));
   15536                 : 
   15537 CBC        4700 :     if (tbinfo->hasoids)
   15538 LBC           0 :         pg_log_warning("WITH OIDS is not supported anymore (table \"%s\")",
   15539 ECB             :                        qrelname);
   15540                 : 
   15541 CBC        4700 :     if (dopt->binary_upgrade)
   15542 GIC         709 :         binary_upgrade_set_type_oids_by_rel(fout, q, tbinfo);
   15543 ECB             : 
   15544                 :     /* Is it a table or a view? */
   15545 CBC        4700 :     if (tbinfo->relkind == RELKIND_VIEW)
   15546 ECB             :     {
   15547                 :         PQExpBuffer result;
   15548                 : 
   15549                 :         /*
   15550                 :          * Note: keep this code in sync with the is_view case in dumpRule()
   15551                 :          */
   15552                 : 
   15553 GIC         271 :         reltypename = "VIEW";
   15554 EUB             : 
   15555 GBC         271 :         appendPQExpBuffer(delq, "DROP VIEW %s;\n", qualrelname);
   15556 EUB             : 
   15557 GIC         271 :         if (dopt->binary_upgrade)
   15558              48 :             binary_upgrade_set_pg_class_oids(fout, q,
   15559 GBC          48 :                                              tbinfo->dobj.catId.oid, false);
   15560 EUB             : 
   15561 GBC         271 :         appendPQExpBuffer(q, "CREATE VIEW %s", qualrelname);
   15562 EUB             : 
   15563 GBC         271 :         if (tbinfo->dummy_view)
   15564              10 :             result = createDummyViewAsClause(fout, tbinfo);
   15565                 :         else
   15566                 :         {
   15567 GIC         261 :             if (nonemptyReloptions(tbinfo->reloptions))
   15568                 :             {
   15569              56 :                 appendPQExpBufferStr(q, " WITH (");
   15570              56 :                 appendReloptionsArrayAH(q, tbinfo->reloptions, "", fout);
   15571 GBC          56 :                 appendPQExpBufferChar(q, ')');
   15572 EUB             :             }
   15573 GBC         261 :             result = createViewAsClause(fout, tbinfo);
   15574                 :         }
   15575 GIC         271 :         appendPQExpBuffer(q, " AS\n%s", result->data);
   15576 GBC         271 :         destroyPQExpBuffer(result);
   15577 EUB             : 
   15578 GBC         271 :         if (tbinfo->checkoption != NULL && !tbinfo->dummy_view)
   15579 GIC          36 :             appendPQExpBuffer(q, "\n  WITH %s CHECK OPTION", tbinfo->checkoption);
   15580             271 :         appendPQExpBufferStr(q, ";\n");
   15581 EUB             :     }
   15582                 :     else
   15583                 :     {
   15584 GBC        4429 :         char       *partkeydef = NULL;
   15585            4429 :         char       *ftoptions = NULL;
   15586            4429 :         char       *srvname = NULL;
   15587            4429 :         char       *foreign = "";
   15588 EUB             : 
   15589                 :         /*
   15590                 :          * Set reltypename, and collect any relkind-specific data that we
   15591 ECB             :          * didn't fetch during getTables().
   15592                 :          */
   15593 CBC        4429 :         switch (tbinfo->relkind)
   15594                 :         {
   15595 GIC         466 :             case RELKIND_PARTITIONED_TABLE:
   15596                 :                 {
   15597             466 :                     PQExpBuffer query = createPQExpBuffer();
   15598                 :                     PGresult   *res;
   15599                 : 
   15600 CBC         466 :                     reltypename = "TABLE";
   15601                 : 
   15602 ECB             :                     /* retrieve partition key definition */
   15603 CBC         466 :                     appendPQExpBuffer(query,
   15604                 :                                       "SELECT pg_get_partkeydef('%u')",
   15605 GIC         466 :                                       tbinfo->dobj.catId.oid);
   15606             466 :                     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   15607 CBC         466 :                     partkeydef = pg_strdup(PQgetvalue(res, 0, 0));
   15608             466 :                     PQclear(res);
   15609 GIC         466 :                     destroyPQExpBuffer(query);
   15610 CBC         466 :                     break;
   15611                 :                 }
   15612              38 :             case RELKIND_FOREIGN_TABLE:
   15613 ECB             :                 {
   15614 GIC          38 :                     PQExpBuffer query = createPQExpBuffer();
   15615 ECB             :                     PGresult   *res;
   15616                 :                     int         i_srvname;
   15617                 :                     int         i_ftoptions;
   15618                 : 
   15619 CBC          38 :                     reltypename = "FOREIGN TABLE";
   15620 ECB             : 
   15621                 :                     /* retrieve name of foreign server and generic options */
   15622 CBC          38 :                     appendPQExpBuffer(query,
   15623 ECB             :                                       "SELECT fs.srvname, "
   15624                 :                                       "pg_catalog.array_to_string(ARRAY("
   15625                 :                                       "SELECT pg_catalog.quote_ident(option_name) || "
   15626                 :                                       "' ' || pg_catalog.quote_literal(option_value) "
   15627                 :                                       "FROM pg_catalog.pg_options_to_table(ftoptions) "
   15628                 :                                       "ORDER BY option_name"
   15629                 :                                       "), E',\n    ') AS ftoptions "
   15630                 :                                       "FROM pg_catalog.pg_foreign_table ft "
   15631                 :                                       "JOIN pg_catalog.pg_foreign_server fs "
   15632                 :                                       "ON (fs.oid = ft.ftserver) "
   15633                 :                                       "WHERE ft.ftrelid = '%u'",
   15634 GIC          38 :                                       tbinfo->dobj.catId.oid);
   15635              38 :                     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   15636              38 :                     i_srvname = PQfnumber(res, "srvname");
   15637              38 :                     i_ftoptions = PQfnumber(res, "ftoptions");
   15638 CBC          38 :                     srvname = pg_strdup(PQgetvalue(res, 0, i_srvname));
   15639 GIC          38 :                     ftoptions = pg_strdup(PQgetvalue(res, 0, i_ftoptions));
   15640 CBC          38 :                     PQclear(res);
   15641 GIC          38 :                     destroyPQExpBuffer(query);
   15642                 : 
   15643              38 :                     foreign = "FOREIGN ";
   15644 CBC          38 :                     break;
   15645                 :                 }
   15646 GIC         328 :             case RELKIND_MATVIEW:
   15647 CBC         328 :                 reltypename = "MATERIALIZED VIEW";
   15648 GIC         328 :                 break;
   15649            3597 :             default:
   15650 CBC        3597 :                 reltypename = "TABLE";
   15651 GIC        3597 :                 break;
   15652                 :         }
   15653                 : 
   15654            4429 :         numParents = tbinfo->numParents;
   15655            4429 :         parents = tbinfo->parents;
   15656                 : 
   15657            4429 :         appendPQExpBuffer(delq, "DROP %s %s;\n", reltypename, qualrelname);
   15658                 : 
   15659            4429 :         if (dopt->binary_upgrade)
   15660             661 :             binary_upgrade_set_pg_class_oids(fout, q,
   15661             661 :                                              tbinfo->dobj.catId.oid, false);
   15662 ECB             : 
   15663 GIC        4429 :         appendPQExpBuffer(q, "CREATE %s%s %s",
   15664            4429 :                           tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ?
   15665                 :                           "UNLOGGED " : "",
   15666                 :                           reltypename,
   15667                 :                           qualrelname);
   15668                 : 
   15669                 :         /*
   15670                 :          * Attach to type, if reloftype; except in case of a binary upgrade,
   15671                 :          * we dump the table normally and attach it to the type afterward.
   15672                 :          */
   15673            4429 :         if (OidIsValid(tbinfo->reloftype) && !dopt->binary_upgrade)
   15674              24 :             appendPQExpBuffer(q, " OF %s",
   15675              24 :                               getFormattedTypeName(fout, tbinfo->reloftype,
   15676                 :                                                    zeroIsError));
   15677                 : 
   15678            4429 :         if (tbinfo->relkind != RELKIND_MATVIEW)
   15679 EUB             :         {
   15680                 :             /* Dump the attributes */
   15681 GIC        4101 :             actual_atts = 0;
   15682           20258 :             for (j = 0; j < tbinfo->numatts; j++)
   15683                 :             {
   15684                 :                 /*
   15685                 :                  * Normally, dump if it's locally defined in this table, and
   15686                 :                  * not dropped.  But for binary upgrade, we'll dump all the
   15687                 :                  * columns, and then fix up the dropped and nonlocal cases
   15688 ECB             :                  * below.
   15689                 :                  */
   15690 CBC       16157 :                 if (shouldPrintColumn(dopt, tbinfo, j))
   15691                 :                 {
   15692                 :                     bool        print_default;
   15693 ECB             :                     bool        print_notnull;
   15694                 : 
   15695                 :                     /*
   15696                 :                      * Default value --- suppress if to be printed separately
   15697                 :                      * or not at all.
   15698                 :                      */
   15699 GIC       31614 :                     print_default = (tbinfo->attrdefs[j] != NULL &&
   15700 GNC       16162 :                                      tbinfo->attrdefs[j]->dobj.dump &&
   15701 CBC         753 :                                      !tbinfo->attrdefs[j]->separate);
   15702                 : 
   15703 ECB             :                     /*
   15704                 :                      * Not Null constraint --- suppress unless it is locally
   15705                 :                      * defined, except if partition, or in binary-upgrade case
   15706                 :                      * where that won't work.
   15707                 :                      */
   15708 GIC       16327 :                     print_notnull = (tbinfo->notnull[j] &&
   15709 GNC         918 :                                      (tbinfo->localNotNull[j] ||
   15710 GIC         425 :                                       tbinfo->ispartition || dopt->binary_upgrade));
   15711 ECB             : 
   15712                 :                     /*
   15713                 :                      * Skip column if fully defined by reloftype, except in
   15714                 :                      * binary upgrade
   15715                 :                      */
   15716 GIC       15409 :                     if (OidIsValid(tbinfo->reloftype) &&
   15717              50 :                         !print_default && !print_notnull &&
   15718              40 :                         !dopt->binary_upgrade)
   15719              32 :                         continue;
   15720                 : 
   15721                 :                     /* Format properly if not first attr */
   15722 CBC       15377 :                     if (actual_atts == 0)
   15723 GIC        3877 :                         appendPQExpBufferStr(q, " (");
   15724 ECB             :                     else
   15725 GIC       11500 :                         appendPQExpBufferChar(q, ',');
   15726 CBC       15377 :                     appendPQExpBufferStr(q, "\n    ");
   15727 GIC       15377 :                     actual_atts++;
   15728 ECB             : 
   15729                 :                     /* Attribute name */
   15730 GIC       15377 :                     appendPQExpBufferStr(q, fmtId(tbinfo->attnames[j]));
   15731                 : 
   15732 CBC       15377 :                     if (tbinfo->attisdropped[j])
   15733                 :                     {
   15734                 :                         /*
   15735                 :                          * ALTER TABLE DROP COLUMN clears
   15736                 :                          * pg_attribute.atttypid, so we will not have gotten a
   15737                 :                          * valid type name; insert INTEGER as a stopgap. We'll
   15738                 :                          * clean things up later.
   15739                 :                          */
   15740 GIC          79 :                         appendPQExpBufferStr(q, " INTEGER /* dummy */");
   15741                 :                         /* and skip to the next column */
   15742 CBC          79 :                         continue;
   15743                 :                     }
   15744 ECB             : 
   15745                 :                     /*
   15746                 :                      * Attribute type; print it except when creating a typed
   15747                 :                      * table ('OF type_name'), but in binary-upgrade mode,
   15748                 :                      * print it in that case too.
   15749                 :                      */
   15750 CBC       15298 :                     if (dopt->binary_upgrade || !OidIsValid(tbinfo->reloftype))
   15751                 :                     {
   15752           15290 :                         appendPQExpBuffer(q, " %s",
   15753 GIC       15290 :                                           tbinfo->atttypnames[j]);
   15754 ECB             :                     }
   15755                 : 
   15756 CBC       15298 :                     if (print_default)
   15757                 :                     {
   15758 GBC         640 :                         if (tbinfo->attgenerated[j] == ATTRIBUTE_GENERATED_STORED)
   15759             274 :                             appendPQExpBuffer(q, " GENERATED ALWAYS AS (%s) STORED",
   15760 GIC         274 :                                               tbinfo->attrdefs[j]->adef_expr);
   15761                 :                         else
   15762 GBC         366 :                             appendPQExpBuffer(q, " DEFAULT %s",
   15763 GIC         366 :                                               tbinfo->attrdefs[j]->adef_expr);
   15764                 :                     }
   15765                 : 
   15766 ECB             : 
   15767 GIC       15298 :                     if (print_notnull)
   15768 CBC         883 :                         appendPQExpBufferStr(q, " NOT NULL");
   15769 EUB             : 
   15770                 :                     /* Add collation if not default for the type */
   15771 GIC       15298 :                     if (OidIsValid(tbinfo->attcollation[j]))
   15772                 :                     {
   15773 ECB             :                         CollInfo   *coll;
   15774                 : 
   15775 GIC           5 :                         coll = findCollationByOid(tbinfo->attcollation[j]);
   15776 CBC           5 :                         if (coll)
   15777               5 :                             appendPQExpBuffer(q, " COLLATE %s",
   15778 GIC           5 :                                               fmtQualifiedDumpable(coll));
   15779 ECB             :                     }
   15780                 :                 }
   15781                 :             }
   15782                 : 
   15783                 :             /*
   15784                 :              * Add non-inherited CHECK constraints, if any.
   15785                 :              *
   15786                 :              * For partitions, we need to include check constraints even if
   15787                 :              * they're not defined locally, because the ALTER TABLE ATTACH
   15788                 :              * PARTITION that we'll emit later expects the constraint to be
   15789                 :              * there.  (No need to fix conislocal: ATTACH PARTITION does that)
   15790                 :              */
   15791 CBC        4659 :             for (j = 0; j < tbinfo->ncheck; j++)
   15792                 :             {
   15793             558 :                 ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
   15794                 : 
   15795 GIC         558 :                 if (constr->separate ||
   15796 CBC         518 :                     (!constr->conislocal && !tbinfo->ispartition))
   15797 GIC          81 :                     continue;
   15798 ECB             : 
   15799 GIC         477 :                 if (actual_atts == 0)
   15800 CBC          16 :                     appendPQExpBufferStr(q, " (\n    ");
   15801 ECB             :                 else
   15802 CBC         461 :                     appendPQExpBufferStr(q, ",\n    ");
   15803                 : 
   15804             477 :                 appendPQExpBuffer(q, "CONSTRAINT %s ",
   15805 GIC         477 :                                   fmtId(constr->dobj.name));
   15806             477 :                 appendPQExpBufferStr(q, constr->condef);
   15807                 : 
   15808             477 :                 actual_atts++;
   15809                 :             }
   15810 ECB             : 
   15811 GIC        4101 :             if (actual_atts)
   15812            3893 :                 appendPQExpBufferStr(q, "\n)");
   15813             208 :             else if (!(OidIsValid(tbinfo->reloftype) && !dopt->binary_upgrade))
   15814 EUB             :             {
   15815                 :                 /*
   15816                 :                  * No attributes? we must have a parenthesized attribute list,
   15817                 :                  * even though empty, when not using the OF TYPE syntax.
   15818                 :                  */
   15819 GIC         192 :                 appendPQExpBufferStr(q, " (\n)");
   15820 ECB             :             }
   15821                 : 
   15822                 :             /*
   15823                 :              * Emit the INHERITS clause (not for partitions), except in
   15824                 :              * binary-upgrade mode.
   15825                 :              */
   15826 GIC        4101 :             if (numParents > 0 && !tbinfo->ispartition &&
   15827             303 :                 !dopt->binary_upgrade)
   15828                 :             {
   15829             261 :                 appendPQExpBufferStr(q, "\nINHERITS (");
   15830             542 :                 for (k = 0; k < numParents; k++)
   15831 ECB             :                 {
   15832 GIC         281 :                     TableInfo  *parentRel = parents[k];
   15833 ECB             : 
   15834 CBC         281 :                     if (k > 0)
   15835              20 :                         appendPQExpBufferStr(q, ", ");
   15836 GIC         281 :                     appendPQExpBufferStr(q, fmtQualifiedDumpable(parentRel));
   15837                 :                 }
   15838             261 :                 appendPQExpBufferChar(q, ')');
   15839                 :             }
   15840                 : 
   15841            4101 :             if (tbinfo->relkind == RELKIND_PARTITIONED_TABLE)
   15842             466 :                 appendPQExpBuffer(q, "\nPARTITION BY %s", partkeydef);
   15843                 : 
   15844            4101 :             if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
   15845              38 :                 appendPQExpBuffer(q, "\nSERVER %s", fmtId(srvname));
   15846                 :         }
   15847 ECB             : 
   15848 GIC        8712 :         if (nonemptyReloptions(tbinfo->reloptions) ||
   15849 CBC        4283 :             nonemptyReloptions(tbinfo->toast_reloptions))
   15850 ECB             :         {
   15851 GIC         146 :             bool        addcomma = false;
   15852 ECB             : 
   15853 GBC         146 :             appendPQExpBufferStr(q, "\nWITH (");
   15854 GIC         146 :             if (nonemptyReloptions(tbinfo->reloptions))
   15855                 :             {
   15856 CBC         146 :                 addcomma = true;
   15857             146 :                 appendReloptionsArrayAH(q, tbinfo->reloptions, "", fout);
   15858                 :             }
   15859 GIC         146 :             if (nonemptyReloptions(tbinfo->toast_reloptions))
   15860 ECB             :             {
   15861 GIC           5 :                 if (addcomma)
   15862               5 :                     appendPQExpBufferStr(q, ", ");
   15863               5 :                 appendReloptionsArrayAH(q, tbinfo->toast_reloptions, "toast.",
   15864                 :                                         fout);
   15865                 :             }
   15866             146 :             appendPQExpBufferChar(q, ')');
   15867                 :         }
   15868 ECB             : 
   15869                 :         /* Dump generic options if any */
   15870 CBC        4429 :         if (ftoptions && ftoptions[0])
   15871 GIC          36 :             appendPQExpBuffer(q, "\nOPTIONS (\n    %s\n)", ftoptions);
   15872 ECB             : 
   15873                 :         /*
   15874                 :          * For materialized views, create the AS clause just like a view. At
   15875                 :          * this point, we always mark the view as not populated.
   15876                 :          */
   15877 GIC        4429 :         if (tbinfo->relkind == RELKIND_MATVIEW)
   15878 ECB             :         {
   15879                 :             PQExpBuffer result;
   15880                 : 
   15881 GIC         328 :             result = createViewAsClause(fout, tbinfo);
   15882 CBC         328 :             appendPQExpBuffer(q, " AS\n%s\n  WITH NO DATA;\n",
   15883                 :                               result->data);
   15884             328 :             destroyPQExpBuffer(result);
   15885 ECB             :         }
   15886                 :         else
   15887 GIC        4101 :             appendPQExpBufferStr(q, ";\n");
   15888 ECB             : 
   15889                 :         /* Materialized views can depend on extensions */
   15890 CBC        4429 :         if (tbinfo->relkind == RELKIND_MATVIEW)
   15891             328 :             append_depends_on_extension(fout, q, &tbinfo->dobj,
   15892                 :                                         "pg_catalog.pg_class",
   15893                 :                                         "MATERIALIZED VIEW",
   15894 ECB             :                                         qualrelname);
   15895                 : 
   15896                 :         /*
   15897                 :          * in binary upgrade mode, update the catalog with any missing values
   15898                 :          * that might be present.
   15899                 :          */
   15900 CBC        4429 :         if (dopt->binary_upgrade)
   15901 ECB             :         {
   15902 GIC        3500 :             for (j = 0; j < tbinfo->numatts; j++)
   15903                 :             {
   15904            2839 :                 if (tbinfo->attmissingval[j][0] != '\0')
   15905                 :                 {
   15906               2 :                     appendPQExpBufferStr(q, "\n-- set missing value.\n");
   15907 CBC           2 :                     appendPQExpBufferStr(q,
   15908                 :                                          "SELECT pg_catalog.binary_upgrade_set_missing_value(");
   15909               2 :                     appendStringLiteralAH(q, qualrelname, fout);
   15910 GIC           2 :                     appendPQExpBufferStr(q, "::pg_catalog.regclass,");
   15911 CBC           2 :                     appendStringLiteralAH(q, tbinfo->attnames[j], fout);
   15912 GNC           2 :                     appendPQExpBufferChar(q, ',');
   15913 GIC           2 :                     appendStringLiteralAH(q, tbinfo->attmissingval[j], fout);
   15914 CBC           2 :                     appendPQExpBufferStr(q, ");\n\n");
   15915                 :                 }
   15916                 :             }
   15917 ECB             :         }
   15918                 : 
   15919                 :         /*
   15920                 :          * To create binary-compatible heap files, we have to ensure the same
   15921                 :          * physical column order, including dropped columns, as in the
   15922                 :          * original.  Therefore, we create dropped columns above and drop them
   15923                 :          * here, also updating their attlen/attalign values so that the
   15924                 :          * dropped column can be skipped properly.  (We do not bother with
   15925                 :          * restoring the original attbyval setting.)  Also, inheritance
   15926                 :          * relationships are set up by doing ALTER TABLE INHERIT rather than
   15927                 :          * using an INHERITS clause --- the latter would possibly mess up the
   15928                 :          * column order.  That also means we have to take care about setting
   15929                 :          * attislocal correctly, plus fix up any inherited CHECK constraints.
   15930                 :          * Analogously, we set up typed tables using ALTER TABLE / OF here.
   15931                 :          *
   15932                 :          * We process foreign and partitioned tables here, even though they
   15933                 :          * lack heap storage, because they can participate in inheritance
   15934                 :          * relationships and we want this stuff to be consistent across the
   15935                 :          * inheritance tree.  We can exclude indexes, toast tables, sequences
   15936                 :          * and matviews, even though they have storage, because we don't
   15937                 :          * support altering or dropping columns in them, nor can they be part
   15938                 :          * of inheritance trees.
   15939                 :          */
   15940 GIC        4429 :         if (dopt->binary_upgrade &&
   15941             661 :             (tbinfo->relkind == RELKIND_RELATION ||
   15942              97 :              tbinfo->relkind == RELKIND_FOREIGN_TABLE ||
   15943              96 :              tbinfo->relkind == RELKIND_PARTITIONED_TABLE))
   15944                 :         {
   15945            3466 :             for (j = 0; j < tbinfo->numatts; j++)
   15946                 :             {
   15947            2821 :                 if (tbinfo->attisdropped[j])
   15948 ECB             :                 {
   15949 CBC          79 :                     appendPQExpBufferStr(q, "\n-- For binary upgrade, recreate dropped column.\n");
   15950              79 :                     appendPQExpBuffer(q, "UPDATE pg_catalog.pg_attribute\n"
   15951 ECB             :                                       "SET attlen = %d, "
   15952                 :                                       "attalign = '%c', attbyval = false\n"
   15953                 :                                       "WHERE attname = ",
   15954 CBC          79 :                                       tbinfo->attlen[j],
   15955              79 :                                       tbinfo->attalign[j]);
   15956 GIC          79 :                     appendStringLiteralAH(q, tbinfo->attnames[j], fout);
   15957 CBC          79 :                     appendPQExpBufferStr(q, "\n  AND attrelid = ");
   15958              79 :                     appendStringLiteralAH(q, qualrelname, fout);
   15959 GIC          79 :                     appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
   15960 ECB             : 
   15961 CBC          79 :                     if (tbinfo->relkind == RELKIND_RELATION ||
   15962              16 :                         tbinfo->relkind == RELKIND_PARTITIONED_TABLE)
   15963              79 :                         appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
   15964 ECB             :                                           qualrelname);
   15965                 :                     else
   15966 UIC           0 :                         appendPQExpBuffer(q, "ALTER FOREIGN TABLE ONLY %s ",
   15967                 :                                           qualrelname);
   15968 CBC          79 :                     appendPQExpBuffer(q, "DROP COLUMN %s;\n",
   15969              79 :                                       fmtId(tbinfo->attnames[j]));
   15970                 :                 }
   15971            2742 :                 else if (!tbinfo->attislocal[j])
   15972                 :                 {
   15973             534 :                     appendPQExpBufferStr(q, "\n-- For binary upgrade, recreate inherited column.\n");
   15974             534 :                     appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_attribute\n"
   15975 ECB             :                                          "SET attislocal = false\n"
   15976                 :                                          "WHERE attname = ");
   15977 CBC         534 :                     appendStringLiteralAH(q, tbinfo->attnames[j], fout);
   15978             534 :                     appendPQExpBufferStr(q, "\n  AND attrelid = ");
   15979 GIC         534 :                     appendStringLiteralAH(q, qualrelname, fout);
   15980             534 :                     appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
   15981                 :                 }
   15982                 :             }
   15983                 : 
   15984                 :             /*
   15985                 :              * Add inherited CHECK constraints, if any.
   15986                 :              *
   15987 ECB             :              * For partitions, they were already dumped, and conislocal
   15988                 :              * doesn't need fixing.
   15989                 :              */
   15990 GIC         696 :             for (k = 0; k < tbinfo->ncheck; k++)
   15991                 :             {
   15992 CBC          51 :                 ConstraintInfo *constr = &(tbinfo->checkexprs[k]);
   15993                 : 
   15994 GIC          51 :                 if (constr->separate || constr->conislocal || tbinfo->ispartition)
   15995 CBC          49 :                     continue;
   15996 ECB             : 
   15997 GIC           2 :                 appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inherited constraint.\n");
   15998               2 :                 appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ADD CONSTRAINT %s %s;\n",
   15999                 :                                   foreign, qualrelname,
   16000               2 :                                   fmtId(constr->dobj.name),
   16001                 :                                   constr->condef);
   16002               2 :                 appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_constraint\n"
   16003                 :                                      "SET conislocal = false\n"
   16004 ECB             :                                      "WHERE contype = 'c' AND conname = ");
   16005 GIC           2 :                 appendStringLiteralAH(q, constr->dobj.name, fout);
   16006               2 :                 appendPQExpBufferStr(q, "\n  AND conrelid = ");
   16007               2 :                 appendStringLiteralAH(q, qualrelname, fout);
   16008               2 :                 appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
   16009                 :             }
   16010                 : 
   16011             645 :             if (numParents > 0 && !tbinfo->ispartition)
   16012                 :             {
   16013 CBC          42 :                 appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inheritance this way.\n");
   16014              89 :                 for (k = 0; k < numParents; k++)
   16015 ECB             :                 {
   16016 GIC          47 :                     TableInfo  *parentRel = parents[k];
   16017                 : 
   16018              47 :                     appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s INHERIT %s;\n", foreign,
   16019                 :                                       qualrelname,
   16020              47 :                                       fmtQualifiedDumpable(parentRel));
   16021                 :                 }
   16022 ECB             :             }
   16023                 : 
   16024 CBC         645 :             if (OidIsValid(tbinfo->reloftype))
   16025                 :             {
   16026 GIC           6 :                 appendPQExpBufferStr(q, "\n-- For binary upgrade, set up typed tables this way.\n");
   16027               6 :                 appendPQExpBuffer(q, "ALTER TABLE ONLY %s OF %s;\n",
   16028                 :                                   qualrelname,
   16029               6 :                                   getFormattedTypeName(fout, tbinfo->reloftype,
   16030 ECB             :                                                        zeroIsError));
   16031                 :             }
   16032                 :         }
   16033                 : 
   16034                 :         /*
   16035                 :          * In binary_upgrade mode, arrange to restore the old relfrozenxid and
   16036                 :          * relminmxid of all vacuumable relations.  (While vacuum.c processes
   16037                 :          * TOAST tables semi-independently, here we see them only as children
   16038                 :          * of other relations; so this "if" lacks RELKIND_TOASTVALUE, and the
   16039                 :          * child toast table is handled below.)
   16040                 :          */
   16041 CBC        4429 :         if (dopt->binary_upgrade &&
   16042 GIC         661 :             (tbinfo->relkind == RELKIND_RELATION ||
   16043              97 :              tbinfo->relkind == RELKIND_MATVIEW))
   16044 ECB             :         {
   16045 GIC         580 :             appendPQExpBufferStr(q, "\n-- For binary upgrade, set heap's relfrozenxid and relminmxid\n");
   16046 CBC         580 :             appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n"
   16047                 :                               "SET relfrozenxid = '%u', relminmxid = '%u'\n"
   16048                 :                               "WHERE oid = ",
   16049 GIC         580 :                               tbinfo->frozenxid, tbinfo->minmxid);
   16050             580 :             appendStringLiteralAH(q, qualrelname, fout);
   16051             580 :             appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
   16052                 : 
   16053             580 :             if (tbinfo->toast_oid)
   16054 ECB             :             {
   16055                 :                 /*
   16056                 :                  * The toast table will have the same OID at restore, so we
   16057                 :                  * can safely target it by OID.
   16058                 :                  */
   16059 GIC         251 :                 appendPQExpBufferStr(q, "\n-- For binary upgrade, set toast's relfrozenxid and relminmxid\n");
   16060             251 :                 appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n"
   16061                 :                                   "SET relfrozenxid = '%u', relminmxid = '%u'\n"
   16062                 :                                   "WHERE oid = '%u';\n",
   16063             251 :                                   tbinfo->toast_frozenxid,
   16064 CBC         251 :                                   tbinfo->toast_minmxid, tbinfo->toast_oid);
   16065                 :             }
   16066 ECB             :         }
   16067                 : 
   16068                 :         /*
   16069                 :          * In binary_upgrade mode, restore matviews' populated status by
   16070                 :          * poking pg_class directly.  This is pretty ugly, but we can't use
   16071                 :          * REFRESH MATERIALIZED VIEW since it's possible that some underlying
   16072                 :          * matview is not populated even though this matview is; in any case,
   16073                 :          * we want to transfer the matview's heap storage, not run REFRESH.
   16074                 :          */
   16075 GIC        4429 :         if (dopt->binary_upgrade && tbinfo->relkind == RELKIND_MATVIEW &&
   16076 CBC          16 :             tbinfo->relispopulated)
   16077 ECB             :         {
   16078 GIC          14 :             appendPQExpBufferStr(q, "\n-- For binary upgrade, mark materialized view as populated\n");
   16079              14 :             appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_class\n"
   16080                 :                                  "SET relispopulated = 't'\n"
   16081 ECB             :                                  "WHERE oid = ");
   16082 CBC          14 :             appendStringLiteralAH(q, qualrelname, fout);
   16083 GIC          14 :             appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
   16084                 :         }
   16085 ECB             : 
   16086                 :         /*
   16087                 :          * Dump additional per-column properties that we can't handle in the
   16088                 :          * main CREATE TABLE command.
   16089                 :          */
   16090 CBC       20924 :         for (j = 0; j < tbinfo->numatts; j++)
   16091 ECB             :         {
   16092                 :             /* None of this applies to dropped columns */
   16093 GIC       16495 :             if (tbinfo->attisdropped[j])
   16094             426 :                 continue;
   16095                 : 
   16096                 :             /*
   16097                 :              * If we didn't dump the column definition explicitly above, and
   16098                 :              * it is NOT NULL and did not inherit that property from a parent,
   16099                 :              * we have to mark it separately.
   16100                 :              */
   16101           16069 :             if (!shouldPrintColumn(dopt, tbinfo, j) &&
   16102 GNC         401 :                 tbinfo->notnull[j] && tbinfo->localNotNull[j] &&
   16103               7 :                 tbinfo->ispartition)
   16104 UIC           0 :                 appendPQExpBuffer(q,
   16105                 :                                   "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET NOT NULL;\n",
   16106 ECB             :                                   foreign, qualrelname,
   16107 UIC           0 :                                   fmtId(tbinfo->attnames[j]));
   16108 ECB             : 
   16109                 :             /*
   16110                 :              * Dump per-column statistics information. We only issue an ALTER
   16111                 :              * TABLE statement if the attstattarget entry for this column is
   16112                 :              * non-negative (i.e. it's not the default value)
   16113                 :              */
   16114 CBC       16069 :             if (tbinfo->attstattarget[j] >= 0)
   16115              36 :                 appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET STATISTICS %d;\n",
   16116                 :                                   foreign, qualrelname,
   16117              36 :                                   fmtId(tbinfo->attnames[j]),
   16118 GIC          36 :                                   tbinfo->attstattarget[j]);
   16119 ECB             : 
   16120                 :             /*
   16121                 :              * Dump per-column storage information.  The statement is only
   16122                 :              * dumped if the storage has been changed from the type's default.
   16123                 :              */
   16124 GIC       16069 :             if (tbinfo->attstorage[j] != tbinfo->typstorage[j])
   16125                 :             {
   16126 CBC          87 :                 switch (tbinfo->attstorage[j])
   16127 ECB             :                 {
   16128 CBC          10 :                     case TYPSTORAGE_PLAIN:
   16129 GIC          10 :                         storage = "PLAIN";
   16130              10 :                         break;
   16131              41 :                     case TYPSTORAGE_EXTERNAL:
   16132              41 :                         storage = "EXTERNAL";
   16133              41 :                         break;
   16134 LBC           0 :                     case TYPSTORAGE_EXTENDED:
   16135 UIC           0 :                         storage = "EXTENDED";
   16136               0 :                         break;
   16137 GIC          36 :                     case TYPSTORAGE_MAIN:
   16138              36 :                         storage = "MAIN";
   16139              36 :                         break;
   16140 UIC           0 :                     default:
   16141 LBC           0 :                         storage = NULL;
   16142 ECB             :                 }
   16143                 : 
   16144                 :                 /*
   16145                 :                  * Only dump the statement if it's a storage type we recognize
   16146                 :                  */
   16147 CBC          87 :                 if (storage != NULL)
   16148 GIC          87 :                     appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET STORAGE %s;\n",
   16149 ECB             :                                       foreign, qualrelname,
   16150 CBC          87 :                                       fmtId(tbinfo->attnames[j]),
   16151 ECB             :                                       storage);
   16152                 :             }
   16153                 : 
   16154                 :             /*
   16155                 :              * Dump per-column compression, if it's been set.
   16156                 :              */
   16157 CBC       16069 :             if (!dopt->no_toast_compression)
   16158                 :             {
   16159 ECB             :                 const char *cmname;
   16160                 : 
   16161 GIC       15998 :                 switch (tbinfo->attcompression[j])
   16162                 :                 {
   16163 CBC          55 :                     case 'p':
   16164              55 :                         cmname = "pglz";
   16165 GIC          55 :                         break;
   16166 CBC         100 :                     case 'l':
   16167 GIC         100 :                         cmname = "lz4";
   16168 CBC         100 :                         break;
   16169           15843 :                     default:
   16170 GIC       15843 :                         cmname = NULL;
   16171 CBC       15843 :                         break;
   16172 ECB             :                 }
   16173                 : 
   16174 CBC       15998 :                 if (cmname != NULL)
   16175 GIC         155 :                     appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET COMPRESSION %s;\n",
   16176 ECB             :                                       foreign, qualrelname,
   16177 CBC         155 :                                       fmtId(tbinfo->attnames[j]),
   16178 ECB             :                                       cmname);
   16179                 :             }
   16180                 : 
   16181                 :             /*
   16182                 :              * Dump per-column attributes.
   16183                 :              */
   16184 GIC       16069 :             if (tbinfo->attoptions[j][0] != '\0')
   16185 CBC          36 :                 appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET (%s);\n",
   16186 ECB             :                                   foreign, qualrelname,
   16187 GIC          36 :                                   fmtId(tbinfo->attnames[j]),
   16188              36 :                                   tbinfo->attoptions[j]);
   16189                 : 
   16190                 :             /*
   16191                 :              * Dump per-column fdw options.
   16192 ECB             :              */
   16193 GIC       16069 :             if (tbinfo->relkind == RELKIND_FOREIGN_TABLE &&
   16194              38 :                 tbinfo->attfdwoptions[j][0] != '\0')
   16195              36 :                 appendPQExpBuffer(q,
   16196 ECB             :                                   "ALTER FOREIGN TABLE %s ALTER COLUMN %s OPTIONS (\n"
   16197                 :                                   "    %s\n"
   16198                 :                                   ");\n",
   16199                 :                                   qualrelname,
   16200 GIC          36 :                                   fmtId(tbinfo->attnames[j]),
   16201              36 :                                   tbinfo->attfdwoptions[j]);
   16202 ECB             :         }                       /* end loop over columns */
   16203                 : 
   16204 GNC        4429 :         free(partkeydef);
   16205            4429 :         free(ftoptions);
   16206            4429 :         free(srvname);
   16207                 :     }
   16208                 : 
   16209                 :     /*
   16210                 :      * dump properties we only have ALTER TABLE syntax for
   16211                 :      */
   16212 CBC        4700 :     if ((tbinfo->relkind == RELKIND_RELATION ||
   16213 GIC        1103 :          tbinfo->relkind == RELKIND_PARTITIONED_TABLE ||
   16214 CBC         637 :          tbinfo->relkind == RELKIND_MATVIEW) &&
   16215 GIC        4391 :         tbinfo->relreplident != REPLICA_IDENTITY_DEFAULT)
   16216 ECB             :     {
   16217 UIC           0 :         if (tbinfo->relreplident == REPLICA_IDENTITY_INDEX)
   16218 ECB             :         {
   16219                 :             /* nothing to do, will be set when the index is dumped */
   16220                 :         }
   16221 LBC           0 :         else if (tbinfo->relreplident == REPLICA_IDENTITY_NOTHING)
   16222 ECB             :         {
   16223 LBC           0 :             appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY NOTHING;\n",
   16224 ECB             :                               qualrelname);
   16225                 :         }
   16226 LBC           0 :         else if (tbinfo->relreplident == REPLICA_IDENTITY_FULL)
   16227                 :         {
   16228 UIC           0 :             appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY FULL;\n",
   16229                 :                               qualrelname);
   16230                 :         }
   16231                 :     }
   16232                 : 
   16233 GIC        4700 :     if (tbinfo->forcerowsec)
   16234               5 :         appendPQExpBuffer(q, "\nALTER TABLE ONLY %s FORCE ROW LEVEL SECURITY;\n",
   16235                 :                           qualrelname);
   16236                 : 
   16237            4700 :     if (dopt->binary_upgrade)
   16238             709 :         binary_upgrade_extension_member(q, &tbinfo->dobj,
   16239                 :                                         reltypename, qrelname,
   16240             709 :                                         tbinfo->dobj.namespace->dobj.name);
   16241                 : 
   16242            4700 :     if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   16243                 :     {
   16244            4700 :         char       *tablespace = NULL;
   16245            4700 :         char       *tableam = NULL;
   16246                 : 
   16247                 :         /*
   16248                 :          * _selectTablespace() relies on tablespace-enabled objects in the
   16249                 :          * default tablespace to have a tablespace of "" (empty string) versus
   16250                 :          * non-tablespace-enabled objects to have a tablespace of NULL.
   16251                 :          * getTables() sets tbinfo->reltablespace to "" for the default
   16252 ECB             :          * tablespace (not NULL).
   16253                 :          */
   16254 CBC        4700 :         if (RELKIND_HAS_TABLESPACE(tbinfo->relkind))
   16255            4391 :             tablespace = tbinfo->reltablespace;
   16256                 : 
   16257            4700 :         if (RELKIND_HAS_TABLE_AM(tbinfo->relkind))
   16258 GIC        3925 :             tableam = tbinfo->amname;
   16259 ECB             : 
   16260 GIC        4700 :         ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
   16261 CBC        4700 :                      ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
   16262 ECB             :                                   .namespace = tbinfo->dobj.namespace->dobj.name,
   16263                 :                                   .tablespace = tablespace,
   16264                 :                                   .tableam = tableam,
   16265                 :                                   .owner = tbinfo->rolname,
   16266                 :                                   .description = reltypename,
   16267                 :                                   .section = tbinfo->postponed_def ?
   16268                 :                                   SECTION_POST_DATA : SECTION_PRE_DATA,
   16269                 :                                   .createStmt = q->data,
   16270                 :                                   .dropStmt = delq->data));
   16271                 :     }
   16272                 : 
   16273                 :     /* Dump Table Comments */
   16274 CBC        4700 :     if (tbinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   16275              82 :         dumpTableComment(fout, tbinfo, reltypename);
   16276                 : 
   16277                 :     /* Dump Table Security Labels */
   16278 GBC        4700 :     if (tbinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
   16279 UIC           0 :         dumpTableSecLabel(fout, tbinfo, reltypename);
   16280 ECB             : 
   16281                 :     /* Dump comments on inlined table constraints */
   16282 GIC        5258 :     for (j = 0; j < tbinfo->ncheck; j++)
   16283 ECB             :     {
   16284 GIC         558 :         ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
   16285 ECB             : 
   16286 CBC         558 :         if (constr->separate || !constr->conislocal)
   16287 GIC         229 :             continue;
   16288                 : 
   16289 CBC         329 :         if (constr->dobj.dump & DUMP_COMPONENT_COMMENT)
   16290              41 :             dumpTableConstraintComment(fout, constr);
   16291 ECB             :     }
   16292                 : 
   16293 GIC        4700 :     destroyPQExpBuffer(q);
   16294            4700 :     destroyPQExpBuffer(delq);
   16295            4700 :     free(qrelname);
   16296            4700 :     free(qualrelname);
   16297            4700 : }
   16298                 : 
   16299                 : /*
   16300                 :  * dumpTableAttach
   16301                 :  *    write to fout the commands to attach a child partition
   16302 ECB             :  *
   16303                 :  * Child partitions are always made by creating them separately
   16304                 :  * and then using ATTACH PARTITION, rather than using
   16305                 :  * CREATE TABLE ... PARTITION OF.  This is important for preserving
   16306                 :  * any possible discrepancy in column layout, to allow assigning the
   16307                 :  * correct tablespace if different, and so that it's possible to restore
   16308                 :  * a partition without restoring its parent.  (You'll get an error from
   16309                 :  * the ATTACH PARTITION command, but that can be ignored, or skipped
   16310                 :  * using "pg_restore -L" if you prefer.)  The last point motivates
   16311                 :  * treating ATTACH PARTITION as a completely separate ArchiveEntry
   16312                 :  * rather than emitting it within the child partition's ArchiveEntry.
   16313                 :  */
   16314                 : static void
   16315 GIC        1166 : dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo)
   16316                 : {
   16317 CBC        1166 :     DumpOptions *dopt = fout->dopt;
   16318 ECB             :     PQExpBuffer q;
   16319                 :     PGresult   *res;
   16320                 :     char       *partbound;
   16321                 : 
   16322                 :     /* Do nothing in data-only dump */
   16323 CBC        1166 :     if (dopt->dataOnly)
   16324 GIC          15 :         return;
   16325 ECB             : 
   16326 GIC        1151 :     q = createPQExpBuffer();
   16327 ECB             : 
   16328 GIC        1151 :     if (!fout->is_prepared[PREPQUERY_DUMPTABLEATTACH])
   16329 ECB             :     {
   16330                 :         /* Set up query for partbound details */
   16331 GIC          47 :         appendPQExpBufferStr(q,
   16332                 :                              "PREPARE dumpTableAttach(pg_catalog.oid) AS\n");
   16333 ECB             : 
   16334 GIC          47 :         appendPQExpBufferStr(q,
   16335 ECB             :                              "SELECT pg_get_expr(c.relpartbound, c.oid) "
   16336                 :                              "FROM pg_class c "
   16337                 :                              "WHERE c.oid = $1");
   16338                 : 
   16339 GIC          47 :         ExecuteSqlStatement(fout, q->data);
   16340                 : 
   16341              47 :         fout->is_prepared[PREPQUERY_DUMPTABLEATTACH] = true;
   16342                 :     }
   16343                 : 
   16344            1151 :     printfPQExpBuffer(q,
   16345                 :                       "EXECUTE dumpTableAttach('%u')",
   16346            1151 :                       attachinfo->partitionTbl->dobj.catId.oid);
   16347                 : 
   16348            1151 :     res = ExecuteSqlQueryForSingleRow(fout, q->data);
   16349            1151 :     partbound = PQgetvalue(res, 0, 0);
   16350 ECB             : 
   16351                 :     /* Perform ALTER TABLE on the parent */
   16352 CBC        1151 :     printfPQExpBuffer(q,
   16353                 :                       "ALTER TABLE ONLY %s ",
   16354            1151 :                       fmtQualifiedDumpable(attachinfo->parentTbl));
   16355            1151 :     appendPQExpBuffer(q,
   16356                 :                       "ATTACH PARTITION %s %s;\n",
   16357 GIC        1151 :                       fmtQualifiedDumpable(attachinfo->partitionTbl),
   16358 ECB             :                       partbound);
   16359                 : 
   16360                 :     /*
   16361                 :      * There is no point in creating a drop query as the drop is done by table
   16362                 :      * drop.  (If you think to change this, see also _printTocEntry().)
   16363                 :      * Although this object doesn't really have ownership as such, set the
   16364                 :      * owner field anyway to ensure that the command is run by the correct
   16365                 :      * role at restore time.
   16366                 :      */
   16367 GIC        1151 :     ArchiveEntry(fout, attachinfo->dobj.catId, attachinfo->dobj.dumpId,
   16368 CBC        1151 :                  ARCHIVE_OPTS(.tag = attachinfo->dobj.name,
   16369 ECB             :                               .namespace = attachinfo->dobj.namespace->dobj.name,
   16370                 :                               .owner = attachinfo->partitionTbl->rolname,
   16371                 :                               .description = "TABLE ATTACH",
   16372                 :                               .section = SECTION_PRE_DATA,
   16373                 :                               .createStmt = q->data));
   16374                 : 
   16375 GIC        1151 :     PQclear(res);
   16376            1151 :     destroyPQExpBuffer(q);
   16377                 : }
   16378                 : 
   16379                 : /*
   16380                 :  * dumpAttrDef --- dump an attribute's default-value declaration
   16381                 :  */
   16382                 : static void
   16383             793 : dumpAttrDef(Archive *fout, const AttrDefInfo *adinfo)
   16384 ECB             : {
   16385 CBC         793 :     DumpOptions *dopt = fout->dopt;
   16386 GIC         793 :     TableInfo  *tbinfo = adinfo->adtable;
   16387 CBC         793 :     int         adnum = adinfo->adnum;
   16388 ECB             :     PQExpBuffer q;
   16389                 :     PQExpBuffer delq;
   16390                 :     char       *qualrelname;
   16391                 :     char       *tag;
   16392                 :     char       *foreign;
   16393                 : 
   16394                 :     /* Do nothing in data-only dump */
   16395 GIC         793 :     if (dopt->dataOnly)
   16396 UIC           0 :         return;
   16397                 : 
   16398                 :     /* Skip if not "separate"; it was dumped in the table's definition */
   16399 CBC         793 :     if (!adinfo->separate)
   16400 GIC         640 :         return;
   16401                 : 
   16402 CBC         153 :     q = createPQExpBuffer();
   16403             153 :     delq = createPQExpBuffer();
   16404                 : 
   16405 GIC         153 :     qualrelname = pg_strdup(fmtQualifiedDumpable(tbinfo));
   16406                 : 
   16407             153 :     foreign = tbinfo->relkind == RELKIND_FOREIGN_TABLE ? "FOREIGN " : "";
   16408                 : 
   16409             153 :     appendPQExpBuffer(q,
   16410 ECB             :                       "ALTER %sTABLE ONLY %s ALTER COLUMN %s SET DEFAULT %s;\n",
   16411 CBC         153 :                       foreign, qualrelname, fmtId(tbinfo->attnames[adnum - 1]),
   16412             153 :                       adinfo->adef_expr);
   16413 EUB             : 
   16414 GIC         153 :     appendPQExpBuffer(delq, "ALTER %sTABLE %s ALTER COLUMN %s DROP DEFAULT;\n",
   16415                 :                       foreign, qualrelname,
   16416 GBC         153 :                       fmtId(tbinfo->attnames[adnum - 1]));
   16417                 : 
   16418 GIC         153 :     tag = psprintf("%s %s", tbinfo->dobj.name, tbinfo->attnames[adnum - 1]);
   16419                 : 
   16420             153 :     if (adinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   16421             153 :         ArchiveEntry(fout, adinfo->dobj.catId, adinfo->dobj.dumpId,
   16422             153 :                      ARCHIVE_OPTS(.tag = tag,
   16423 ECB             :                                   .namespace = tbinfo->dobj.namespace->dobj.name,
   16424                 :                                   .owner = tbinfo->rolname,
   16425                 :                                   .description = "DEFAULT",
   16426                 :                                   .section = SECTION_PRE_DATA,
   16427                 :                                   .createStmt = q->data,
   16428                 :                                   .dropStmt = delq->data));
   16429                 : 
   16430 GIC         153 :     free(tag);
   16431             153 :     destroyPQExpBuffer(q);
   16432             153 :     destroyPQExpBuffer(delq);
   16433 CBC         153 :     free(qualrelname);
   16434                 : }
   16435 ECB             : 
   16436                 : /*
   16437                 :  * getAttrName: extract the correct name for an attribute
   16438                 :  *
   16439                 :  * The array tblInfo->attnames[] only provides names of user attributes;
   16440                 :  * if a system attribute number is supplied, we have to fake it.
   16441                 :  * We also do a little bit of bounds checking for safety's sake.
   16442                 :  */
   16443 EUB             : static const char *
   16444 GBC        1165 : getAttrName(int attrnum, const TableInfo *tblInfo)
   16445 EUB             : {
   16446 CBC        1165 :     if (attrnum > 0 && attrnum <= tblInfo->numatts)
   16447            1165 :         return tblInfo->attnames[attrnum - 1];
   16448 LBC           0 :     switch (attrnum)
   16449 EUB             :     {
   16450 UBC           0 :         case SelfItemPointerAttributeNumber:
   16451 UIC           0 :             return "ctid";
   16452               0 :         case MinTransactionIdAttributeNumber:
   16453               0 :             return "xmin";
   16454               0 :         case MinCommandIdAttributeNumber:
   16455               0 :             return "cmin";
   16456 LBC           0 :         case MaxTransactionIdAttributeNumber:
   16457               0 :             return "xmax";
   16458 UIC           0 :         case MaxCommandIdAttributeNumber:
   16459 LBC           0 :             return "cmax";
   16460 UIC           0 :         case TableOidAttributeNumber:
   16461               0 :             return "tableoid";
   16462                 :     }
   16463               0 :     pg_fatal("invalid column number %d for table \"%s\"",
   16464                 :              attrnum, tblInfo->dobj.name);
   16465                 :     return NULL;                /* keep compiler quiet */
   16466 ECB             : }
   16467                 : 
   16468                 : /*
   16469                 :  * dumpIndex
   16470                 :  *    write out to fout a user-defined index
   16471                 :  */
   16472                 : static void
   16473 CBC        1842 : dumpIndex(Archive *fout, const IndxInfo *indxinfo)
   16474 ECB             : {
   16475 CBC        1842 :     DumpOptions *dopt = fout->dopt;
   16476            1842 :     TableInfo  *tbinfo = indxinfo->indextable;
   16477            1842 :     bool        is_constraint = (indxinfo->indexconstraint != 0);
   16478 ECB             :     PQExpBuffer q;
   16479                 :     PQExpBuffer delq;
   16480                 :     char       *qindxname;
   16481                 :     char       *qqindxname;
   16482                 : 
   16483                 :     /* Do nothing in data-only dump */
   16484 CBC        1842 :     if (dopt->dataOnly)
   16485 GIC          48 :         return;
   16486 ECB             : 
   16487 GIC        1794 :     q = createPQExpBuffer();
   16488            1794 :     delq = createPQExpBuffer();
   16489                 : 
   16490            1794 :     qindxname = pg_strdup(fmtId(indxinfo->dobj.name));
   16491            1794 :     qqindxname = pg_strdup(fmtQualifiedDumpable(indxinfo));
   16492                 : 
   16493 ECB             :     /*
   16494                 :      * If there's an associated constraint, don't dump the index per se, but
   16495                 :      * do dump any comment for it.  (This is safe because dependency ordering
   16496                 :      * will have ensured the constraint is emitted first.)  Note that the
   16497                 :      * emitted comment has to be shown as depending on the constraint, not the
   16498                 :      * index, in such cases.
   16499                 :      */
   16500 GIC        1794 :     if (!is_constraint)
   16501                 :     {
   16502 CBC         939 :         char       *indstatcols = indxinfo->indstatcols;
   16503             939 :         char       *indstatvals = indxinfo->indstatvals;
   16504             939 :         char      **indstatcolsarray = NULL;
   16505 GIC         939 :         char      **indstatvalsarray = NULL;
   16506             939 :         int         nstatcols = 0;
   16507             939 :         int         nstatvals = 0;
   16508                 : 
   16509 CBC         939 :         if (dopt->binary_upgrade)
   16510             147 :             binary_upgrade_set_pg_class_oids(fout, q,
   16511 GIC         147 :                                              indxinfo->dobj.catId.oid, true);
   16512                 : 
   16513 ECB             :         /* Plain secondary index */
   16514 CBC         939 :         appendPQExpBuffer(q, "%s;\n", indxinfo->indexdef);
   16515 ECB             : 
   16516                 :         /*
   16517                 :          * Append ALTER TABLE commands as needed to set properties that we
   16518                 :          * only have ALTER TABLE syntax for.  Keep this in sync with the
   16519                 :          * similar code in dumpConstraint!
   16520                 :          */
   16521                 : 
   16522                 :         /* If the index is clustered, we need to record that. */
   16523 CBC         939 :         if (indxinfo->indisclustered)
   16524 ECB             :         {
   16525 UIC           0 :             appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
   16526 UBC           0 :                               fmtQualifiedDumpable(tbinfo));
   16527                 :             /* index name is not qualified in this syntax */
   16528 UIC           0 :             appendPQExpBuffer(q, " ON %s;\n",
   16529                 :                               qindxname);
   16530 EUB             :         }
   16531                 : 
   16532                 :         /*
   16533                 :          * If the index has any statistics on some of its columns, generate
   16534                 :          * the associated ALTER INDEX queries.
   16535                 :          */
   16536 GIC         939 :         if (strlen(indstatcols) != 0 || strlen(indstatvals) != 0)
   16537 EUB             :         {
   16538                 :             int         j;
   16539                 : 
   16540 GIC          36 :             if (!parsePGArray(indstatcols, &indstatcolsarray, &nstatcols))
   16541 UIC           0 :                 pg_fatal("could not parse index statistic columns");
   16542 CBC          36 :             if (!parsePGArray(indstatvals, &indstatvalsarray, &nstatvals))
   16543 LBC           0 :                 pg_fatal("could not parse index statistic values");
   16544 GIC          36 :             if (nstatcols != nstatvals)
   16545 UIC           0 :                 pg_fatal("mismatched number of columns and values for index statistics");
   16546 ECB             : 
   16547 CBC         108 :             for (j = 0; j < nstatcols; j++)
   16548                 :             {
   16549              72 :                 appendPQExpBuffer(q, "ALTER INDEX %s ", qqindxname);
   16550                 : 
   16551 ECB             :                 /*
   16552                 :                  * Note that this is a column number, so no quotes should be
   16553                 :                  * used.
   16554                 :                  */
   16555 GIC          72 :                 appendPQExpBuffer(q, "ALTER COLUMN %s ",
   16556              72 :                                   indstatcolsarray[j]);
   16557              72 :                 appendPQExpBuffer(q, "SET STATISTICS %s;\n",
   16558              72 :                                   indstatvalsarray[j]);
   16559                 :             }
   16560                 :         }
   16561                 : 
   16562                 :         /* Indexes can depend on extensions */
   16563 CBC         939 :         append_depends_on_extension(fout, q, &indxinfo->dobj,
   16564 ECB             :                                     "pg_catalog.pg_class",
   16565                 :                                     "INDEX", qqindxname);
   16566                 : 
   16567                 :         /* If the index defines identity, we need to record that. */
   16568 GIC         939 :         if (indxinfo->indisreplident)
   16569 ECB             :         {
   16570 LBC           0 :             appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY USING",
   16571 UIC           0 :                               fmtQualifiedDumpable(tbinfo));
   16572                 :             /* index name is not qualified in this syntax */
   16573               0 :             appendPQExpBuffer(q, " INDEX %s;\n",
   16574                 :                               qindxname);
   16575                 :         }
   16576                 : 
   16577 GIC         939 :         appendPQExpBuffer(delq, "DROP INDEX %s;\n", qqindxname);
   16578                 : 
   16579             939 :         if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   16580             939 :             ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
   16581             939 :                          ARCHIVE_OPTS(.tag = indxinfo->dobj.name,
   16582                 :                                       .namespace = tbinfo->dobj.namespace->dobj.name,
   16583 ECB             :                                       .tablespace = indxinfo->tablespace,
   16584                 :                                       .owner = tbinfo->rolname,
   16585                 :                                       .description = "INDEX",
   16586                 :                                       .section = SECTION_POST_DATA,
   16587                 :                                       .createStmt = q->data,
   16588 EUB             :                                       .dropStmt = delq->data));
   16589                 : 
   16590 GNC         939 :         free(indstatcolsarray);
   16591             939 :         free(indstatvalsarray);
   16592                 :     }
   16593 ECB             : 
   16594                 :     /* Dump Index Comments */
   16595 GIC        1794 :     if (indxinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   16596 CBC          15 :         dumpComment(fout, "INDEX", qindxname,
   16597              15 :                     tbinfo->dobj.namespace->dobj.name,
   16598                 :                     tbinfo->rolname,
   16599                 :                     indxinfo->dobj.catId, 0,
   16600 ECB             :                     is_constraint ? indxinfo->indexconstraint :
   16601                 :                     indxinfo->dobj.dumpId);
   16602                 : 
   16603 CBC        1794 :     destroyPQExpBuffer(q);
   16604            1794 :     destroyPQExpBuffer(delq);
   16605 GIC        1794 :     free(qindxname);
   16606            1794 :     free(qqindxname);
   16607                 : }
   16608                 : 
   16609                 : /*
   16610                 :  * dumpIndexAttach
   16611                 :  *    write out to fout a partitioned-index attachment clause
   16612                 :  */
   16613                 : static void
   16614             567 : dumpIndexAttach(Archive *fout, const IndexAttachInfo *attachinfo)
   16615                 : {
   16616                 :     /* Do nothing in data-only dump */
   16617             567 :     if (fout->dopt->dataOnly)
   16618              24 :         return;
   16619                 : 
   16620             543 :     if (attachinfo->partitionIdx->dobj.dump & DUMP_COMPONENT_DEFINITION)
   16621                 :     {
   16622 CBC         543 :         PQExpBuffer q = createPQExpBuffer();
   16623                 : 
   16624             543 :         appendPQExpBuffer(q, "ALTER INDEX %s ",
   16625 GIC         543 :                           fmtQualifiedDumpable(attachinfo->parentIdx));
   16626             543 :         appendPQExpBuffer(q, "ATTACH PARTITION %s;\n",
   16627             543 :                           fmtQualifiedDumpable(attachinfo->partitionIdx));
   16628                 : 
   16629                 :         /*
   16630 ECB             :          * There is no point in creating a drop query as the drop is done by
   16631                 :          * index drop.  (If you think to change this, see also
   16632                 :          * _printTocEntry().)  Although this object doesn't really have
   16633                 :          * ownership as such, set the owner field anyway to ensure that the
   16634                 :          * command is run by the correct role at restore time.
   16635                 :          */
   16636 GIC         543 :         ArchiveEntry(fout, attachinfo->dobj.catId, attachinfo->dobj.dumpId,
   16637             543 :                      ARCHIVE_OPTS(.tag = attachinfo->dobj.name,
   16638 ECB             :                                   .namespace = attachinfo->dobj.namespace->dobj.name,
   16639                 :                                   .owner = attachinfo->parentIdx->indextable->rolname,
   16640                 :                                   .description = "INDEX ATTACH",
   16641                 :                                   .section = SECTION_POST_DATA,
   16642                 :                                   .createStmt = q->data));
   16643                 : 
   16644 GIC         543 :         destroyPQExpBuffer(q);
   16645                 :     }
   16646 ECB             : }
   16647                 : 
   16648                 : /*
   16649                 :  * dumpStatisticsExt
   16650                 :  *    write out to fout an extended statistics object
   16651                 :  */
   16652                 : static void
   16653 CBC         137 : dumpStatisticsExt(Archive *fout, const StatsExtInfo *statsextinfo)
   16654                 : {
   16655             137 :     DumpOptions *dopt = fout->dopt;
   16656 ECB             :     PQExpBuffer q;
   16657                 :     PQExpBuffer delq;
   16658                 :     PQExpBuffer query;
   16659                 :     char       *qstatsextname;
   16660                 :     PGresult   *res;
   16661                 :     char       *stxdef;
   16662                 : 
   16663                 :     /* Do nothing in data-only dump */
   16664 CBC         137 :     if (dopt->dataOnly)
   16665 GIC           9 :         return;
   16666                 : 
   16667             128 :     q = createPQExpBuffer();
   16668             128 :     delq = createPQExpBuffer();
   16669             128 :     query = createPQExpBuffer();
   16670                 : 
   16671             128 :     qstatsextname = pg_strdup(fmtId(statsextinfo->dobj.name));
   16672                 : 
   16673             128 :     appendPQExpBuffer(query, "SELECT "
   16674 ECB             :                       "pg_catalog.pg_get_statisticsobjdef('%u'::pg_catalog.oid)",
   16675 CBC         128 :                       statsextinfo->dobj.catId.oid);
   16676                 : 
   16677 GIC         128 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   16678                 : 
   16679             128 :     stxdef = PQgetvalue(res, 0, 0);
   16680                 : 
   16681                 :     /* Result of pg_get_statisticsobjdef is complete except for semicolon */
   16682 CBC         128 :     appendPQExpBuffer(q, "%s;\n", stxdef);
   16683 ECB             : 
   16684                 :     /*
   16685                 :      * We only issue an ALTER STATISTICS statement if the stxstattarget entry
   16686                 :      * for this statistics object is non-negative (i.e. it's not the default
   16687                 :      * value).
   16688                 :      */
   16689 GIC         128 :     if (statsextinfo->stattarget >= 0)
   16690 ECB             :     {
   16691 GIC          36 :         appendPQExpBuffer(q, "ALTER STATISTICS %s ",
   16692 CBC          36 :                           fmtQualifiedDumpable(statsextinfo));
   16693              36 :         appendPQExpBuffer(q, "SET STATISTICS %d;\n",
   16694              36 :                           statsextinfo->stattarget);
   16695                 :     }
   16696                 : 
   16697 GIC         128 :     appendPQExpBuffer(delq, "DROP STATISTICS %s;\n",
   16698             128 :                       fmtQualifiedDumpable(statsextinfo));
   16699                 : 
   16700             128 :     if (statsextinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   16701             128 :         ArchiveEntry(fout, statsextinfo->dobj.catId,
   16702 CBC         128 :                      statsextinfo->dobj.dumpId,
   16703 GBC         128 :                      ARCHIVE_OPTS(.tag = statsextinfo->dobj.name,
   16704                 :                                   .namespace = statsextinfo->dobj.namespace->dobj.name,
   16705                 :                                   .owner = statsextinfo->rolname,
   16706 ECB             :                                   .description = "STATISTICS",
   16707                 :                                   .section = SECTION_POST_DATA,
   16708                 :                                   .createStmt = q->data,
   16709                 :                                   .dropStmt = delq->data));
   16710                 : 
   16711                 :     /* Dump Statistics Comments */
   16712 CBC         128 :     if (statsextinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   16713 UIC           0 :         dumpComment(fout, "STATISTICS", qstatsextname,
   16714 LBC           0 :                     statsextinfo->dobj.namespace->dobj.name,
   16715 UIC           0 :                     statsextinfo->rolname,
   16716 ECB             :                     statsextinfo->dobj.catId, 0,
   16717 UIC           0 :                     statsextinfo->dobj.dumpId);
   16718 ECB             : 
   16719 CBC         128 :     PQclear(res);
   16720 GIC         128 :     destroyPQExpBuffer(q);
   16721 CBC         128 :     destroyPQExpBuffer(delq);
   16722 GIC         128 :     destroyPQExpBuffer(query);
   16723 CBC         128 :     free(qstatsextname);
   16724                 : }
   16725 ECB             : 
   16726                 : /*
   16727                 :  * dumpConstraint
   16728                 :  *    write out to fout a user-defined constraint
   16729                 :  */
   16730                 : static void
   16731 GIC        1684 : dumpConstraint(Archive *fout, const ConstraintInfo *coninfo)
   16732                 : {
   16733            1684 :     DumpOptions *dopt = fout->dopt;
   16734            1684 :     TableInfo  *tbinfo = coninfo->contable;
   16735                 :     PQExpBuffer q;
   16736                 :     PQExpBuffer delq;
   16737 CBC        1684 :     char       *tag = NULL;
   16738 ECB             :     char       *foreign;
   16739                 : 
   16740                 :     /* Do nothing in data-only dump */
   16741 GIC        1684 :     if (dopt->dataOnly)
   16742              38 :         return;
   16743                 : 
   16744            1646 :     q = createPQExpBuffer();
   16745            1646 :     delq = createPQExpBuffer();
   16746                 : 
   16747            3211 :     foreign = tbinfo &&
   16748            1646 :         tbinfo->relkind == RELKIND_FOREIGN_TABLE ? "FOREIGN " : "";
   16749                 : 
   16750            1646 :     if (coninfo->contype == 'p' ||
   16751 CBC         839 :         coninfo->contype == 'u' ||
   16752 GIC         801 :         coninfo->contype == 'x')
   16753 CBC         855 :     {
   16754 ECB             :         /* Index-related constraint */
   16755 EUB             :         IndxInfo   *indxinfo;
   16756                 :         int         k;
   16757                 : 
   16758 GBC         855 :         indxinfo = (IndxInfo *) findObjectByDumpId(coninfo->conindex);
   16759 EUB             : 
   16760 GBC         855 :         if (indxinfo == NULL)
   16761 UBC           0 :             pg_fatal("missing index for constraint \"%s\"",
   16762 EUB             :                      coninfo->dobj.name);
   16763                 : 
   16764 GBC         855 :         if (dopt->binary_upgrade)
   16765             108 :             binary_upgrade_set_pg_class_oids(fout, q,
   16766 EUB             :                                              indxinfo->dobj.catId.oid, true);
   16767                 : 
   16768 GBC         855 :         appendPQExpBuffer(q, "ALTER %sTABLE ONLY %s\n", foreign,
   16769 GIC         855 :                           fmtQualifiedDumpable(tbinfo));
   16770 GBC         855 :         appendPQExpBuffer(q, "    ADD CONSTRAINT %s ",
   16771 GIC         855 :                           fmtId(coninfo->dobj.name));
   16772                 : 
   16773             855 :         if (coninfo->condef)
   16774                 :         {
   16775                 :             /* pg_get_constraintdef should have provided everything */
   16776              10 :             appendPQExpBuffer(q, "%s;\n", coninfo->condef);
   16777                 :         }
   16778                 :         else
   16779                 :         {
   16780 GNC         845 :             appendPQExpBufferStr(q,
   16781             845 :                                  coninfo->contype == 'p' ? "PRIMARY KEY" : "UNIQUE");
   16782                 :             /*
   16783                 :              * PRIMARY KEY constraints should not be using NULLS NOT DISTINCT
   16784                 :              * indexes. Being able to create this was fixed, but we need to
   16785                 :              * make the index distinct in order to be able to restore the dump.
   16786                 :              */
   16787             845 :             if (indxinfo->indnullsnotdistinct && coninfo->contype != 'p')
   16788 UNC           0 :                 appendPQExpBufferStr(q, " NULLS NOT DISTINCT");
   16789 GNC         845 :             appendPQExpBufferStr(q, " (");
   16790 GIC        1970 :             for (k = 0; k < indxinfo->indnkeyattrs; k++)
   16791                 :             {
   16792            1125 :                 int         indkey = (int) indxinfo->indkeys[k];
   16793                 :                 const char *attname;
   16794                 : 
   16795            1125 :                 if (indkey == InvalidAttrNumber)
   16796 LBC           0 :                     break;
   16797 CBC        1125 :                 attname = getAttrName(indkey, tbinfo);
   16798                 : 
   16799            1125 :                 appendPQExpBuffer(q, "%s%s",
   16800 ECB             :                                   (k == 0) ? "" : ", ",
   16801                 :                                   fmtId(attname));
   16802                 :             }
   16803                 : 
   16804 GIC         845 :             if (indxinfo->indnkeyattrs < indxinfo->indnattrs)
   16805              20 :                 appendPQExpBufferStr(q, ") INCLUDE (");
   16806                 : 
   16807             885 :             for (k = indxinfo->indnkeyattrs; k < indxinfo->indnattrs; k++)
   16808                 :             {
   16809              40 :                 int         indkey = (int) indxinfo->indkeys[k];
   16810                 :                 const char *attname;
   16811                 : 
   16812 CBC          40 :                 if (indkey == InvalidAttrNumber)
   16813 UIC           0 :                     break;
   16814 CBC          40 :                 attname = getAttrName(indkey, tbinfo);
   16815 ECB             : 
   16816 CBC          80 :                 appendPQExpBuffer(q, "%s%s",
   16817              40 :                                   (k == indxinfo->indnkeyattrs) ? "" : ", ",
   16818 ECB             :                                   fmtId(attname));
   16819                 :             }
   16820                 : 
   16821 CBC         845 :             appendPQExpBufferChar(q, ')');
   16822 ECB             : 
   16823 CBC         845 :             if (nonemptyReloptions(indxinfo->indreloptions))
   16824                 :             {
   16825 UIC           0 :                 appendPQExpBufferStr(q, " WITH (");
   16826 LBC           0 :                 appendReloptionsArrayAH(q, indxinfo->indreloptions, "", fout);
   16827 UIC           0 :                 appendPQExpBufferChar(q, ')');
   16828                 :             }
   16829                 : 
   16830 GIC         845 :             if (coninfo->condeferrable)
   16831                 :             {
   16832 UIC           0 :                 appendPQExpBufferStr(q, " DEFERRABLE");
   16833               0 :                 if (coninfo->condeferred)
   16834               0 :                     appendPQExpBufferStr(q, " INITIALLY DEFERRED");
   16835 ECB             :             }
   16836                 : 
   16837 GBC         845 :             appendPQExpBufferStr(q, ";\n");
   16838 EUB             :         }
   16839                 : 
   16840                 :         /*
   16841                 :          * Append ALTER TABLE commands as needed to set properties that we
   16842                 :          * only have ALTER TABLE syntax for.  Keep this in sync with the
   16843                 :          * similar code in dumpIndex!
   16844                 :          */
   16845                 : 
   16846                 :         /* If the index is clustered, we need to record that. */
   16847 GIC         855 :         if (indxinfo->indisclustered)
   16848 ECB             :         {
   16849 GIC          36 :             appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
   16850              36 :                               fmtQualifiedDumpable(tbinfo));
   16851                 :             /* index name is not qualified in this syntax */
   16852 CBC          36 :             appendPQExpBuffer(q, " ON %s;\n",
   16853 GBC          36 :                               fmtId(indxinfo->dobj.name));
   16854 ECB             :         }
   16855 EUB             : 
   16856 ECB             :         /* If the index defines identity, we need to record that. */
   16857 GBC         855 :         if (indxinfo->indisreplident)
   16858                 :         {
   16859 LBC           0 :             appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY USING",
   16860 UIC           0 :                               fmtQualifiedDumpable(tbinfo));
   16861 ECB             :             /* index name is not qualified in this syntax */
   16862 UIC           0 :             appendPQExpBuffer(q, " INDEX %s;\n",
   16863               0 :                               fmtId(indxinfo->dobj.name));
   16864                 :         }
   16865                 : 
   16866                 :         /* Indexes can depend on extensions */
   16867 CBC         855 :         append_depends_on_extension(fout, q, &indxinfo->dobj,
   16868 ECB             :                                     "pg_catalog.pg_class", "INDEX",
   16869 CBC         855 :                                     fmtQualifiedDumpable(indxinfo));
   16870 ECB             : 
   16871 GIC         855 :         appendPQExpBuffer(delq, "ALTER %sTABLE ONLY %s ", foreign,
   16872             855 :                           fmtQualifiedDumpable(tbinfo));
   16873             855 :         appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
   16874             855 :                           fmtId(coninfo->dobj.name));
   16875 ECB             : 
   16876 GIC         855 :         tag = psprintf("%s %s", tbinfo->dobj.name, coninfo->dobj.name);
   16877                 : 
   16878             855 :         if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   16879             855 :             ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
   16880 CBC         855 :                          ARCHIVE_OPTS(.tag = tag,
   16881                 :                                       .namespace = tbinfo->dobj.namespace->dobj.name,
   16882 EUB             :                                       .tablespace = indxinfo->tablespace,
   16883                 :                                       .owner = tbinfo->rolname,
   16884                 :                                       .description = "CONSTRAINT",
   16885                 :                                       .section = SECTION_POST_DATA,
   16886                 :                                       .createStmt = q->data,
   16887                 :                                       .dropStmt = delq->data));
   16888                 :     }
   16889 CBC         791 :     else if (coninfo->contype == 'f')
   16890                 :     {
   16891 ECB             :         char       *only;
   16892                 : 
   16893                 :         /*
   16894                 :          * Foreign keys on partitioned tables are always declared as
   16895                 :          * inheriting to partitions; for all other cases, emit them as
   16896                 :          * applying ONLY directly to the named table, because that's how they
   16897                 :          * work for regular inherited tables.
   16898                 :          */
   16899 GIC         152 :         only = tbinfo->relkind == RELKIND_PARTITIONED_TABLE ? "" : "ONLY ";
   16900                 : 
   16901                 :         /*
   16902 ECB             :          * XXX Potentially wrap in a 'SET CONSTRAINTS OFF' block so that the
   16903                 :          * current table data is not processed
   16904                 :          */
   16905 GIC         152 :         appendPQExpBuffer(q, "ALTER %sTABLE %s%s\n", foreign,
   16906             152 :                           only, fmtQualifiedDumpable(tbinfo));
   16907 CBC         152 :         appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
   16908             152 :                           fmtId(coninfo->dobj.name),
   16909             152 :                           coninfo->condef);
   16910                 : 
   16911 GIC         152 :         appendPQExpBuffer(delq, "ALTER %sTABLE %s%s ", foreign,
   16912             152 :                           only, fmtQualifiedDumpable(tbinfo));
   16913             152 :         appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
   16914             152 :                           fmtId(coninfo->dobj.name));
   16915 ECB             : 
   16916 CBC         152 :         tag = psprintf("%s %s", tbinfo->dobj.name, coninfo->dobj.name);
   16917 ECB             : 
   16918 CBC         152 :         if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   16919 GIC         152 :             ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
   16920             152 :                          ARCHIVE_OPTS(.tag = tag,
   16921                 :                                       .namespace = tbinfo->dobj.namespace->dobj.name,
   16922                 :                                       .owner = tbinfo->rolname,
   16923                 :                                       .description = "FK CONSTRAINT",
   16924                 :                                       .section = SECTION_POST_DATA,
   16925                 :                                       .createStmt = q->data,
   16926 ECB             :                                       .dropStmt = delq->data));
   16927                 :     }
   16928 GNC         639 :     else if (coninfo->contype == 'n')
   16929                 :     {
   16930 UNC           0 :         appendPQExpBuffer(q, "ALTER %sTABLE %s\n", foreign,
   16931               0 :                           fmtQualifiedDumpable(tbinfo));
   16932               0 :         appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
   16933               0 :                           fmtId(coninfo->dobj.name),
   16934               0 :                           coninfo->condef);
   16935                 : 
   16936               0 :         appendPQExpBuffer(delq, "ALTER %sTABLE %s\n", foreign,
   16937               0 :                           fmtQualifiedDumpable(tbinfo));
   16938               0 :         appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
   16939               0 :                           fmtId(coninfo->dobj.name));
   16940                 : 
   16941               0 :         tag = psprintf("%s %s", tbinfo->dobj.name, coninfo->dobj.name);
   16942                 : 
   16943               0 :         if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   16944               0 :             ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
   16945               0 :                          ARCHIVE_OPTS(.tag = tag,
   16946                 :                                       .namespace = tbinfo->dobj.namespace->dobj.name,
   16947                 :                                       .owner = tbinfo->rolname,
   16948                 :                                       .description = "NOT NULL CONSTRAINT",
   16949                 :                                       .section = SECTION_POST_DATA,
   16950                 :                                       .createStmt = q->data,
   16951                 :                                       .dropStmt = delq->data));
   16952                 :     }
   16953 GIC         639 :     else if (coninfo->contype == 'c' && tbinfo)
   16954 ECB             :     {
   16955                 :         /* CHECK constraint on a table */
   16956                 : 
   16957                 :         /* Ignore if not to be dumped separately, or if it was inherited */
   16958 GIC         558 :         if (coninfo->separate && coninfo->conislocal)
   16959 ECB             :         {
   16960                 :             /* not ONLY since we want it to propagate to children */
   16961 CBC          25 :             appendPQExpBuffer(q, "ALTER %sTABLE %s\n", foreign,
   16962              25 :                               fmtQualifiedDumpable(tbinfo));
   16963              25 :             appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
   16964              25 :                               fmtId(coninfo->dobj.name),
   16965 GIC          25 :                               coninfo->condef);
   16966                 : 
   16967              25 :             appendPQExpBuffer(delq, "ALTER %sTABLE %s ", foreign,
   16968              25 :                               fmtQualifiedDumpable(tbinfo));
   16969              25 :             appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
   16970              25 :                               fmtId(coninfo->dobj.name));
   16971                 : 
   16972              25 :             tag = psprintf("%s %s", tbinfo->dobj.name, coninfo->dobj.name);
   16973 ECB             : 
   16974 CBC          25 :             if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   16975 GIC          25 :                 ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
   16976              25 :                              ARCHIVE_OPTS(.tag = tag,
   16977                 :                                           .namespace = tbinfo->dobj.namespace->dobj.name,
   16978                 :                                           .owner = tbinfo->rolname,
   16979                 :                                           .description = "CHECK CONSTRAINT",
   16980                 :                                           .section = SECTION_POST_DATA,
   16981 ECB             :                                           .createStmt = q->data,
   16982                 :                                           .dropStmt = delq->data));
   16983                 :         }
   16984                 :     }
   16985 GIC          81 :     else if (coninfo->contype == 'c' && tbinfo == NULL)
   16986              81 :     {
   16987                 :         /* CHECK constraint on a domain */
   16988              81 :         TypeInfo   *tyinfo = coninfo->condomain;
   16989                 : 
   16990 ECB             :         /* Ignore if not to be dumped separately */
   16991 GIC          81 :         if (coninfo->separate)
   16992 ECB             :         {
   16993 UIC           0 :             appendPQExpBuffer(q, "ALTER DOMAIN %s\n",
   16994               0 :                               fmtQualifiedDumpable(tyinfo));
   16995               0 :             appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
   16996               0 :                               fmtId(coninfo->dobj.name),
   16997               0 :                               coninfo->condef);
   16998                 : 
   16999               0 :             appendPQExpBuffer(delq, "ALTER DOMAIN %s ",
   17000               0 :                               fmtQualifiedDumpable(tyinfo));
   17001 LBC           0 :             appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
   17002               0 :                               fmtId(coninfo->dobj.name));
   17003                 : 
   17004               0 :             tag = psprintf("%s %s", tyinfo->dobj.name, coninfo->dobj.name);
   17005 ECB             : 
   17006 LBC           0 :             if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   17007 UIC           0 :                 ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
   17008 LBC           0 :                              ARCHIVE_OPTS(.tag = tag,
   17009                 :                                           .namespace = tyinfo->dobj.namespace->dobj.name,
   17010 ECB             :                                           .owner = tyinfo->rolname,
   17011                 :                                           .description = "CHECK CONSTRAINT",
   17012                 :                                           .section = SECTION_POST_DATA,
   17013                 :                                           .createStmt = q->data,
   17014                 :                                           .dropStmt = delq->data));
   17015                 :         }
   17016                 :     }
   17017                 :     else
   17018                 :     {
   17019 LBC           0 :         pg_fatal("unrecognized constraint type: %c",
   17020                 :                  coninfo->contype);
   17021                 :     }
   17022                 : 
   17023                 :     /* Dump Constraint Comments --- only works for table constraints */
   17024 GIC        1646 :     if (tbinfo && coninfo->separate &&
   17025            1047 :         coninfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   17026 CBC          10 :         dumpTableConstraintComment(fout, coninfo);
   17027                 : 
   17028            1646 :     free(tag);
   17029            1646 :     destroyPQExpBuffer(q);
   17030            1646 :     destroyPQExpBuffer(delq);
   17031 ECB             : }
   17032                 : 
   17033                 : /*
   17034                 :  * dumpTableConstraintComment --- dump a constraint's comment if any
   17035                 :  *
   17036                 :  * This is split out because we need the function in two different places
   17037                 :  * depending on whether the constraint is dumped as part of CREATE TABLE
   17038                 :  * or as a separate ALTER command.
   17039                 :  */
   17040                 : static void
   17041 GIC          51 : dumpTableConstraintComment(Archive *fout, const ConstraintInfo *coninfo)
   17042                 : {
   17043              51 :     TableInfo  *tbinfo = coninfo->contable;
   17044              51 :     PQExpBuffer conprefix = createPQExpBuffer();
   17045                 :     char       *qtabname;
   17046                 : 
   17047              51 :     qtabname = pg_strdup(fmtId(tbinfo->dobj.name));
   17048                 : 
   17049 CBC          51 :     appendPQExpBuffer(conprefix, "CONSTRAINT %s ON",
   17050 GBC          51 :                       fmtId(coninfo->dobj.name));
   17051 EUB             : 
   17052 GBC          51 :     if (coninfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   17053 GIC          51 :         dumpComment(fout, conprefix->data, qtabname,
   17054 GBC          51 :                     tbinfo->dobj.namespace->dobj.name,
   17055                 :                     tbinfo->rolname,
   17056 ECB             :                     coninfo->dobj.catId, 0,
   17057 CBC          51 :                     coninfo->separate ? coninfo->dobj.dumpId : tbinfo->dobj.dumpId);
   17058 ECB             : 
   17059 CBC          51 :     destroyPQExpBuffer(conprefix);
   17060              51 :     free(qtabname);
   17061 GIC          51 : }
   17062                 : 
   17063                 : /*
   17064                 :  * dumpSequence
   17065                 :  *    write the declaration (not data) of one user-defined sequence
   17066                 :  */
   17067                 : static void
   17068 CBC         315 : dumpSequence(Archive *fout, const TableInfo *tbinfo)
   17069                 : {
   17070             315 :     DumpOptions *dopt = fout->dopt;
   17071 ECB             :     PGresult   *res;
   17072                 :     char       *startv,
   17073                 :                *incby,
   17074                 :                *maxv,
   17075                 :                *minv,
   17076                 :                *cache,
   17077                 :                *seqtype;
   17078                 :     bool        cycled;
   17079                 :     bool        is_ascending;
   17080                 :     int64       default_minv,
   17081                 :                 default_maxv;
   17082                 :     char        bufm[32],
   17083                 :                 bufx[32];
   17084 CBC         315 :     PQExpBuffer query = createPQExpBuffer();
   17085             315 :     PQExpBuffer delqry = createPQExpBuffer();
   17086                 :     char       *qseqname;
   17087             315 :     TableInfo  *owning_tab = NULL;
   17088 ECB             : 
   17089 CBC         315 :     qseqname = pg_strdup(fmtId(tbinfo->dobj.name));
   17090 ECB             : 
   17091 GIC         315 :     if (fout->remoteVersion >= 100000)
   17092                 :     {
   17093             315 :         appendPQExpBuffer(query,
   17094                 :                           "SELECT format_type(seqtypid, NULL), "
   17095 ECB             :                           "seqstart, seqincrement, "
   17096                 :                           "seqmax, seqmin, "
   17097                 :                           "seqcache, seqcycle "
   17098 EUB             :                           "FROM pg_catalog.pg_sequence "
   17099                 :                           "WHERE seqrelid = '%u'::oid",
   17100 GIC         315 :                           tbinfo->dobj.catId.oid);
   17101 ECB             :     }
   17102                 :     else
   17103                 :     {
   17104                 :         /*
   17105                 :          * Before PostgreSQL 10, sequence metadata is in the sequence itself.
   17106                 :          *
   17107                 :          * Note: it might seem that 'bigint' potentially needs to be
   17108                 :          * schema-qualified, but actually that's a keyword.
   17109                 :          */
   17110 LBC           0 :         appendPQExpBuffer(query,
   17111                 :                           "SELECT 'bigint' AS sequence_type, "
   17112                 :                           "start_value, increment_by, max_value, min_value, "
   17113 ECB             :                           "cache_value, is_cycled FROM %s",
   17114 UIC           0 :                           fmtQualifiedDumpable(tbinfo));
   17115                 :     }
   17116                 : 
   17117 CBC         315 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   17118 ECB             : 
   17119 GIC         315 :     if (PQntuples(res) != 1)
   17120 UIC           0 :         pg_fatal(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)",
   17121                 :                           "query to get data of sequence \"%s\" returned %d rows (expected 1)",
   17122                 :                           PQntuples(res)),
   17123                 :                  tbinfo->dobj.name, PQntuples(res));
   17124 ECB             : 
   17125 GBC         315 :     seqtype = PQgetvalue(res, 0, 0);
   17126 CBC         315 :     startv = PQgetvalue(res, 0, 1);
   17127             315 :     incby = PQgetvalue(res, 0, 2);
   17128 GIC         315 :     maxv = PQgetvalue(res, 0, 3);
   17129 CBC         315 :     minv = PQgetvalue(res, 0, 4);
   17130 GIC         315 :     cache = PQgetvalue(res, 0, 5);
   17131             315 :     cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0);
   17132 ECB             : 
   17133 EUB             :     /* Calculate default limits for a sequence of this type */
   17134 CBC         315 :     is_ascending = (incby[0] != '-');
   17135 GIC         315 :     if (strcmp(seqtype, "smallint") == 0)
   17136 ECB             :     {
   17137 GIC          25 :         default_minv = is_ascending ? 1 : PG_INT16_MIN;
   17138              25 :         default_maxv = is_ascending ? PG_INT16_MAX : -1;
   17139                 :     }
   17140             290 :     else if (strcmp(seqtype, "integer") == 0)
   17141 ECB             :     {
   17142 CBC         241 :         default_minv = is_ascending ? 1 : PG_INT32_MIN;
   17143 GIC         241 :         default_maxv = is_ascending ? PG_INT32_MAX : -1;
   17144 ECB             :     }
   17145 GIC          49 :     else if (strcmp(seqtype, "bigint") == 0)
   17146 ECB             :     {
   17147 GIC          49 :         default_minv = is_ascending ? 1 : PG_INT64_MIN;
   17148              49 :         default_maxv = is_ascending ? PG_INT64_MAX : -1;
   17149 ECB             :     }
   17150 EUB             :     else
   17151 ECB             :     {
   17152 UIC           0 :         pg_fatal("unrecognized sequence type: %s", seqtype);
   17153 ECB             :         default_minv = default_maxv = 0;    /* keep compiler quiet */
   17154                 :     }
   17155                 : 
   17156                 :     /*
   17157                 :      * 64-bit strtol() isn't very portable, so convert the limits to strings
   17158                 :      * and compare that way.
   17159                 :      */
   17160 CBC         315 :     snprintf(bufm, sizeof(bufm), INT64_FORMAT, default_minv);
   17161 GIC         315 :     snprintf(bufx, sizeof(bufx), INT64_FORMAT, default_maxv);
   17162 EUB             : 
   17163                 :     /* Don't print minv/maxv if they match the respective default limit */
   17164 GBC         315 :     if (strcmp(minv, bufm) == 0)
   17165 GIC         300 :         minv = NULL;
   17166             315 :     if (strcmp(maxv, bufx) == 0)
   17167 CBC         300 :         maxv = NULL;
   17168                 : 
   17169 EUB             :     /*
   17170                 :      * Identity sequences are not to be dropped separately.
   17171                 :      */
   17172 GIC         315 :     if (!tbinfo->is_identity_sequence)
   17173                 :     {
   17174 CBC         209 :         appendPQExpBuffer(delqry, "DROP SEQUENCE %s;\n",
   17175 GIC         209 :                           fmtQualifiedDumpable(tbinfo));
   17176                 :     }
   17177                 : 
   17178             315 :     resetPQExpBuffer(query);
   17179                 : 
   17180             315 :     if (dopt->binary_upgrade)
   17181                 :     {
   17182              48 :         binary_upgrade_set_pg_class_oids(fout, query,
   17183              48 :                                          tbinfo->dobj.catId.oid, false);
   17184 ECB             : 
   17185                 :         /*
   17186                 :          * In older PG versions a sequence will have a pg_type entry, but v14
   17187                 :          * and up don't use that, so don't attempt to preserve the type OID.
   17188                 :          */
   17189                 :     }
   17190                 : 
   17191 GIC         315 :     if (tbinfo->is_identity_sequence)
   17192                 :     {
   17193             106 :         owning_tab = findTableByOid(tbinfo->owning_tab);
   17194 ECB             : 
   17195 GIC         106 :         appendPQExpBuffer(query,
   17196 EUB             :                           "ALTER TABLE %s ",
   17197 GBC         106 :                           fmtQualifiedDumpable(owning_tab));
   17198 GIC         106 :         appendPQExpBuffer(query,
   17199 EUB             :                           "ALTER COLUMN %s ADD GENERATED ",
   17200 GBC         106 :                           fmtId(owning_tab->attnames[tbinfo->owning_col - 1]));
   17201 GIC         106 :         if (owning_tab->attidentity[tbinfo->owning_col - 1] == ATTRIBUTE_IDENTITY_ALWAYS)
   17202              71 :             appendPQExpBufferStr(query, "ALWAYS");
   17203              35 :         else if (owning_tab->attidentity[tbinfo->owning_col - 1] == ATTRIBUTE_IDENTITY_BY_DEFAULT)
   17204 CBC          35 :             appendPQExpBufferStr(query, "BY DEFAULT");
   17205 GIC         106 :         appendPQExpBuffer(query, " AS IDENTITY (\n    SEQUENCE NAME %s\n",
   17206 CBC         106 :                           fmtQualifiedDumpable(tbinfo));
   17207                 :     }
   17208 ECB             :     else
   17209                 :     {
   17210 CBC         209 :         appendPQExpBuffer(query,
   17211 ECB             :                           "CREATE %sSEQUENCE %s\n",
   17212 GIC         209 :                           tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ?
   17213 ECB             :                           "UNLOGGED " : "",
   17214 GIC         209 :                           fmtQualifiedDumpable(tbinfo));
   17215 ECB             : 
   17216 CBC         209 :         if (strcmp(seqtype, "bigint") != 0)
   17217             165 :             appendPQExpBuffer(query, "    AS %s\n", seqtype);
   17218                 :     }
   17219                 : 
   17220 GIC         315 :     appendPQExpBuffer(query, "    START WITH %s\n", startv);
   17221                 : 
   17222             315 :     appendPQExpBuffer(query, "    INCREMENT BY %s\n", incby);
   17223                 : 
   17224             315 :     if (minv)
   17225              15 :         appendPQExpBuffer(query, "    MINVALUE %s\n", minv);
   17226 ECB             :     else
   17227 GIC         300 :         appendPQExpBufferStr(query, "    NO MINVALUE\n");
   17228                 : 
   17229             315 :     if (maxv)
   17230              15 :         appendPQExpBuffer(query, "    MAXVALUE %s\n", maxv);
   17231                 :     else
   17232             300 :         appendPQExpBufferStr(query, "    NO MAXVALUE\n");
   17233                 : 
   17234             315 :     appendPQExpBuffer(query,
   17235                 :                       "    CACHE %s%s",
   17236 ECB             :                       cache, (cycled ? "\n    CYCLE" : ""));
   17237                 : 
   17238 GIC         315 :     if (tbinfo->is_identity_sequence)
   17239                 :     {
   17240             106 :         appendPQExpBufferStr(query, "\n);\n");
   17241             106 :         if (tbinfo->relpersistence != owning_tab->relpersistence)
   17242 LBC           0 :             appendPQExpBuffer(query,
   17243 ECB             :                               "ALTER SEQUENCE %s SET %s;\n",
   17244 LBC           0 :                               fmtQualifiedDumpable(tbinfo),
   17245               0 :                               tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ?
   17246 ECB             :                               "UNLOGGED" : "LOGGED");
   17247                 :     }
   17248                 :     else
   17249 CBC         209 :         appendPQExpBufferStr(query, ";\n");
   17250 ECB             : 
   17251                 :     /* binary_upgrade:  no need to clear TOAST table oid */
   17252                 : 
   17253 CBC         315 :     if (dopt->binary_upgrade)
   17254 GIC          48 :         binary_upgrade_extension_member(query, &tbinfo->dobj,
   17255 ECB             :                                         "SEQUENCE", qseqname,
   17256 CBC          48 :                                         tbinfo->dobj.namespace->dobj.name);
   17257 ECB             : 
   17258 GIC         315 :     if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   17259             315 :         ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
   17260             315 :                      ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
   17261                 :                                   .namespace = tbinfo->dobj.namespace->dobj.name,
   17262                 :                                   .owner = tbinfo->rolname,
   17263                 :                                   .description = "SEQUENCE",
   17264                 :                                   .section = SECTION_PRE_DATA,
   17265 ECB             :                                   .createStmt = query->data,
   17266                 :                                   .dropStmt = delqry->data));
   17267 EUB             : 
   17268                 :     /*
   17269                 :      * If the sequence is owned by a table column, emit the ALTER for it as a
   17270                 :      * separate TOC entry immediately following the sequence's own entry. It's
   17271                 :      * OK to do this rather than using full sorting logic, because the
   17272                 :      * dependency that tells us it's owned will have forced the table to be
   17273                 :      * created first.  We can't just include the ALTER in the TOC entry
   17274                 :      * because it will fail if we haven't reassigned the sequence owner to
   17275                 :      * match the table's owner.
   17276                 :      *
   17277                 :      * We need not schema-qualify the table reference because both sequence
   17278                 :      * and table must be in the same schema.
   17279                 :      */
   17280 GBC         315 :     if (OidIsValid(tbinfo->owning_tab) && !tbinfo->is_identity_sequence)
   17281 EUB             :     {
   17282 GBC         120 :         owning_tab = findTableByOid(tbinfo->owning_tab);
   17283                 : 
   17284 GIC         120 :         if (owning_tab == NULL)
   17285 UIC           0 :             pg_fatal("failed sanity check, parent table with OID %u of sequence with OID %u not found",
   17286                 :                      tbinfo->owning_tab, tbinfo->dobj.catId.oid);
   17287                 : 
   17288 GIC         120 :         if (owning_tab->dobj.dump & DUMP_COMPONENT_DEFINITION)
   17289                 :         {
   17290 CBC         118 :             resetPQExpBuffer(query);
   17291 GIC         118 :             appendPQExpBuffer(query, "ALTER SEQUENCE %s",
   17292             118 :                               fmtQualifiedDumpable(tbinfo));
   17293             118 :             appendPQExpBuffer(query, " OWNED BY %s",
   17294             118 :                               fmtQualifiedDumpable(owning_tab));
   17295 CBC         118 :             appendPQExpBuffer(query, ".%s;\n",
   17296 GIC         118 :                               fmtId(owning_tab->attnames[tbinfo->owning_col - 1]));
   17297                 : 
   17298 CBC         118 :             if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   17299             118 :                 ArchiveEntry(fout, nilCatalogId, createDumpId(),
   17300             118 :                              ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
   17301 ECB             :                                           .namespace = tbinfo->dobj.namespace->dobj.name,
   17302                 :                                           .owner = tbinfo->rolname,
   17303                 :                                           .description = "SEQUENCE OWNED BY",
   17304                 :                                           .section = SECTION_PRE_DATA,
   17305                 :                                           .createStmt = query->data,
   17306                 :                                           .deps = &(tbinfo->dobj.dumpId),
   17307                 :                                           .nDeps = 1));
   17308                 :         }
   17309                 :     }
   17310                 : 
   17311                 :     /* Dump Sequence Comments and Security Labels */
   17312 CBC         315 :     if (tbinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   17313 LBC           0 :         dumpComment(fout, "SEQUENCE", qseqname,
   17314 UIC           0 :                     tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
   17315               0 :                     tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
   17316                 : 
   17317 GIC         315 :     if (tbinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
   17318 UIC           0 :         dumpSecLabel(fout, "SEQUENCE", qseqname,
   17319               0 :                      tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
   17320               0 :                      tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
   17321                 : 
   17322 CBC         315 :     PQclear(res);
   17323 ECB             : 
   17324 GIC         315 :     destroyPQExpBuffer(query);
   17325 CBC         315 :     destroyPQExpBuffer(delqry);
   17326 GIC         315 :     free(qseqname);
   17327             315 : }
   17328 ECB             : 
   17329                 : /*
   17330 EUB             :  * dumpSequenceData
   17331                 :  *    write the data of one user-defined sequence
   17332                 :  */
   17333                 : static void
   17334 GBC         338 : dumpSequenceData(Archive *fout, const TableDataInfo *tdinfo)
   17335                 : {
   17336             338 :     TableInfo  *tbinfo = tdinfo->tdtable;
   17337 EUB             :     PGresult   *res;
   17338                 :     char       *last;
   17339                 :     bool        called;
   17340 GIC         338 :     PQExpBuffer query = createPQExpBuffer();
   17341 EUB             : 
   17342 GIC         338 :     appendPQExpBuffer(query,
   17343 EUB             :                       "SELECT last_value, is_called FROM %s",
   17344 GBC         338 :                       fmtQualifiedDumpable(tbinfo));
   17345 EUB             : 
   17346 GIC         338 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   17347                 : 
   17348             338 :     if (PQntuples(res) != 1)
   17349 UIC           0 :         pg_fatal(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)",
   17350                 :                           "query to get data of sequence \"%s\" returned %d rows (expected 1)",
   17351                 :                           PQntuples(res)),
   17352                 :                  tbinfo->dobj.name, PQntuples(res));
   17353                 : 
   17354 GIC         338 :     last = PQgetvalue(res, 0, 0);
   17355             338 :     called = (strcmp(PQgetvalue(res, 0, 1), "t") == 0);
   17356 EUB             : 
   17357 GIC         338 :     resetPQExpBuffer(query);
   17358             338 :     appendPQExpBufferStr(query, "SELECT pg_catalog.setval(");
   17359             338 :     appendStringLiteralAH(query, fmtQualifiedDumpable(tbinfo), fout);
   17360             338 :     appendPQExpBuffer(query, ", %s, %s);\n",
   17361 ECB             :                       last, (called ? "true" : "false"));
   17362                 : 
   17363 CBC         338 :     if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA)
   17364 GIC         338 :         ArchiveEntry(fout, nilCatalogId, createDumpId(),
   17365 CBC         338 :                      ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
   17366 ECB             :                                   .namespace = tbinfo->dobj.namespace->dobj.name,
   17367                 :                                   .owner = tbinfo->rolname,
   17368                 :                                   .description = "SEQUENCE SET",
   17369                 :                                   .section = SECTION_DATA,
   17370                 :                                   .createStmt = query->data,
   17371                 :                                   .deps = &(tbinfo->dobj.dumpId),
   17372                 :                                   .nDeps = 1));
   17373                 : 
   17374 GIC         338 :     PQclear(res);
   17375                 : 
   17376             338 :     destroyPQExpBuffer(query);
   17377             338 : }
   17378 ECB             : 
   17379                 : /*
   17380                 :  * dumpTrigger
   17381                 :  *    write the declaration of one user-defined table trigger
   17382                 :  */
   17383                 : static void
   17384 CBC         504 : dumpTrigger(Archive *fout, const TriggerInfo *tginfo)
   17385                 : {
   17386             504 :     DumpOptions *dopt = fout->dopt;
   17387             504 :     TableInfo  *tbinfo = tginfo->tgtable;
   17388                 :     PQExpBuffer query;
   17389 ECB             :     PQExpBuffer delqry;
   17390                 :     PQExpBuffer trigprefix;
   17391                 :     PQExpBuffer trigidentity;
   17392                 :     char       *qtabname;
   17393                 :     char       *tgargs;
   17394                 :     size_t      lentgargs;
   17395                 :     const char *p;
   17396                 :     int         findx;
   17397                 :     char       *tag;
   17398                 : 
   17399                 :     /* Do nothing in data-only dump */
   17400 GIC         504 :     if (dopt->dataOnly)
   17401              16 :         return;
   17402                 : 
   17403             488 :     query = createPQExpBuffer();
   17404             488 :     delqry = createPQExpBuffer();
   17405 CBC         488 :     trigprefix = createPQExpBuffer();
   17406 GIC         488 :     trigidentity = createPQExpBuffer();
   17407 ECB             : 
   17408 GIC         488 :     qtabname = pg_strdup(fmtId(tbinfo->dobj.name));
   17409                 : 
   17410             488 :     appendPQExpBuffer(trigidentity, "%s ", fmtId(tginfo->dobj.name));
   17411             488 :     appendPQExpBuffer(trigidentity, "ON %s", fmtQualifiedDumpable(tbinfo));
   17412                 : 
   17413             488 :     appendPQExpBuffer(delqry, "DROP TRIGGER %s;\n", trigidentity->data);
   17414                 : 
   17415             488 :     if (tginfo->tgdef)
   17416                 :     {
   17417             488 :         appendPQExpBuffer(query, "%s;\n", tginfo->tgdef);
   17418                 :     }
   17419                 :     else
   17420                 :     {
   17421 LBC           0 :         if (tginfo->tgisconstraint)
   17422 ECB             :         {
   17423 UIC           0 :             appendPQExpBufferStr(query, "CREATE CONSTRAINT TRIGGER ");
   17424 LBC           0 :             appendPQExpBufferStr(query, fmtId(tginfo->tgconstrname));
   17425                 :         }
   17426 ECB             :         else
   17427                 :         {
   17428 LBC           0 :             appendPQExpBufferStr(query, "CREATE TRIGGER ");
   17429 UIC           0 :             appendPQExpBufferStr(query, fmtId(tginfo->dobj.name));
   17430 ECB             :         }
   17431 UIC           0 :         appendPQExpBufferStr(query, "\n    ");
   17432                 : 
   17433                 :         /* Trigger type */
   17434               0 :         if (TRIGGER_FOR_BEFORE(tginfo->tgtype))
   17435               0 :             appendPQExpBufferStr(query, "BEFORE");
   17436               0 :         else if (TRIGGER_FOR_AFTER(tginfo->tgtype))
   17437 LBC           0 :             appendPQExpBufferStr(query, "AFTER");
   17438 UIC           0 :         else if (TRIGGER_FOR_INSTEAD(tginfo->tgtype))
   17439               0 :             appendPQExpBufferStr(query, "INSTEAD OF");
   17440                 :         else
   17441               0 :             pg_fatal("unexpected tgtype value: %d", tginfo->tgtype);
   17442                 : 
   17443               0 :         findx = 0;
   17444               0 :         if (TRIGGER_FOR_INSERT(tginfo->tgtype))
   17445                 :         {
   17446               0 :             appendPQExpBufferStr(query, " INSERT");
   17447 UBC           0 :             findx++;
   17448                 :         }
   17449 UIC           0 :         if (TRIGGER_FOR_DELETE(tginfo->tgtype))
   17450                 :         {
   17451 UBC           0 :             if (findx > 0)
   17452 UIC           0 :                 appendPQExpBufferStr(query, " OR DELETE");
   17453                 :             else
   17454 LBC           0 :                 appendPQExpBufferStr(query, " DELETE");
   17455 UIC           0 :             findx++;
   17456 ECB             :         }
   17457 UBC           0 :         if (TRIGGER_FOR_UPDATE(tginfo->tgtype))
   17458                 :         {
   17459 UIC           0 :             if (findx > 0)
   17460               0 :                 appendPQExpBufferStr(query, " OR UPDATE");
   17461                 :             else
   17462 LBC           0 :                 appendPQExpBufferStr(query, " UPDATE");
   17463               0 :             findx++;
   17464 ECB             :         }
   17465 LBC           0 :         if (TRIGGER_FOR_TRUNCATE(tginfo->tgtype))
   17466 ECB             :         {
   17467 LBC           0 :             if (findx > 0)
   17468               0 :                 appendPQExpBufferStr(query, " OR TRUNCATE");
   17469                 :             else
   17470 UIC           0 :                 appendPQExpBufferStr(query, " TRUNCATE");
   17471 LBC           0 :             findx++;
   17472 ECB             :         }
   17473 UIC           0 :         appendPQExpBuffer(query, " ON %s\n",
   17474 LBC           0 :                           fmtQualifiedDumpable(tbinfo));
   17475 ECB             : 
   17476 UIC           0 :         if (tginfo->tgisconstraint)
   17477 ECB             :         {
   17478 UIC           0 :             if (OidIsValid(tginfo->tgconstrrelid))
   17479 ECB             :             {
   17480                 :                 /* regclass output is already quoted */
   17481 UIC           0 :                 appendPQExpBuffer(query, "    FROM %s\n    ",
   17482 LBC           0 :                                   tginfo->tgconstrrelname);
   17483                 :             }
   17484               0 :             if (!tginfo->tgdeferrable)
   17485               0 :                 appendPQExpBufferStr(query, "NOT ");
   17486 UIC           0 :             appendPQExpBufferStr(query, "DEFERRABLE INITIALLY ");
   17487               0 :             if (tginfo->tginitdeferred)
   17488               0 :                 appendPQExpBufferStr(query, "DEFERRED\n");
   17489 EUB             :             else
   17490 UIC           0 :                 appendPQExpBufferStr(query, "IMMEDIATE\n");
   17491                 :         }
   17492                 : 
   17493               0 :         if (TRIGGER_FOR_ROW(tginfo->tgtype))
   17494               0 :             appendPQExpBufferStr(query, "    FOR EACH ROW\n    ");
   17495                 :         else
   17496               0 :             appendPQExpBufferStr(query, "    FOR EACH STATEMENT\n    ");
   17497 ECB             : 
   17498                 :         /* regproc output is already sufficiently quoted */
   17499 UIC           0 :         appendPQExpBuffer(query, "EXECUTE FUNCTION %s(",
   17500               0 :                           tginfo->tgfname);
   17501 ECB             : 
   17502 LBC           0 :         tgargs = (char *) PQunescapeBytea((unsigned char *) tginfo->tgargs,
   17503 ECB             :                                           &lentgargs);
   17504 LBC           0 :         p = tgargs;
   17505 UIC           0 :         for (findx = 0; findx < tginfo->tgnargs; findx++)
   17506                 :         {
   17507                 :             /* find the embedded null that terminates this trigger argument */
   17508               0 :             size_t      tlen = strlen(p);
   17509 ECB             : 
   17510 UIC           0 :             if (p + tlen >= tgargs + lentgargs)
   17511 ECB             :             {
   17512                 :                 /* hm, not found before end of bytea value... */
   17513 UIC           0 :                 pg_fatal("invalid argument string (%s) for trigger \"%s\" on table \"%s\"",
   17514                 :                          tginfo->tgargs,
   17515 ECB             :                          tginfo->dobj.name,
   17516                 :                          tbinfo->dobj.name);
   17517                 :             }
   17518                 : 
   17519 LBC           0 :             if (findx > 0)
   17520               0 :                 appendPQExpBufferStr(query, ", ");
   17521 UIC           0 :             appendStringLiteralAH(query, p, fout);
   17522               0 :             p += tlen + 1;
   17523                 :         }
   17524               0 :         free(tgargs);
   17525               0 :         appendPQExpBufferStr(query, ");\n");
   17526                 :     }
   17527                 : 
   17528 ECB             :     /* Triggers can depend on extensions */
   17529 GIC         488 :     append_depends_on_extension(fout, query, &tginfo->dobj,
   17530 ECB             :                                 "pg_catalog.pg_trigger", "TRIGGER",
   17531 GIC         488 :                                 trigidentity->data);
   17532 ECB             : 
   17533 GIC         488 :     if (tginfo->tgispartition)
   17534 ECB             :     {
   17535 CBC         121 :         Assert(tbinfo->ispartition);
   17536                 : 
   17537 ECB             :         /*
   17538                 :          * Partition triggers only appear here because their 'tgenabled' flag
   17539                 :          * differs from its parent's.  The trigger is created already, so
   17540                 :          * remove the CREATE and replace it with an ALTER.  (Clear out the
   17541                 :          * DROP query too, so that pg_dump --create does not cause errors.)
   17542                 :          */
   17543 CBC         121 :         resetPQExpBuffer(query);
   17544 GIC         121 :         resetPQExpBuffer(delqry);
   17545             121 :         appendPQExpBuffer(query, "\nALTER %sTABLE %s ",
   17546             121 :                           tbinfo->relkind == RELKIND_FOREIGN_TABLE ? "FOREIGN " : "",
   17547 CBC         121 :                           fmtQualifiedDumpable(tbinfo));
   17548 GIC         121 :         switch (tginfo->tgenabled)
   17549 ECB             :         {
   17550 GIC          42 :             case 'f':
   17551 ECB             :             case 'D':
   17552 GIC          42 :                 appendPQExpBufferStr(query, "DISABLE");
   17553 CBC          42 :                 break;
   17554 LBC           0 :             case 't':
   17555                 :             case 'O':
   17556 UIC           0 :                 appendPQExpBufferStr(query, "ENABLE");
   17557 LBC           0 :                 break;
   17558 GIC          37 :             case 'R':
   17559 CBC          37 :                 appendPQExpBufferStr(query, "ENABLE REPLICA");
   17560 GIC          37 :                 break;
   17561 CBC          42 :             case 'A':
   17562              42 :                 appendPQExpBufferStr(query, "ENABLE ALWAYS");
   17563 GIC          42 :                 break;
   17564 ECB             :         }
   17565 GIC         121 :         appendPQExpBuffer(query, " TRIGGER %s;\n",
   17566 CBC         121 :                           fmtId(tginfo->dobj.name));
   17567 ECB             :     }
   17568 GIC         367 :     else if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
   17569 ECB             :     {
   17570 UIC           0 :         appendPQExpBuffer(query, "\nALTER %sTABLE %s ",
   17571 LBC           0 :                           tbinfo->relkind == RELKIND_FOREIGN_TABLE ? "FOREIGN " : "",
   17572 UIC           0 :                           fmtQualifiedDumpable(tbinfo));
   17573               0 :         switch (tginfo->tgenabled)
   17574                 :         {
   17575 LBC           0 :             case 'D':
   17576                 :             case 'f':
   17577               0 :                 appendPQExpBufferStr(query, "DISABLE");
   17578               0 :                 break;
   17579 UBC           0 :             case 'A':
   17580 UIC           0 :                 appendPQExpBufferStr(query, "ENABLE ALWAYS");
   17581 UBC           0 :                 break;
   17582               0 :             case 'R':
   17583 UIC           0 :                 appendPQExpBufferStr(query, "ENABLE REPLICA");
   17584               0 :                 break;
   17585               0 :             default:
   17586 LBC           0 :                 appendPQExpBufferStr(query, "ENABLE");
   17587 UIC           0 :                 break;
   17588                 :         }
   17589               0 :         appendPQExpBuffer(query, " TRIGGER %s;\n",
   17590 LBC           0 :                           fmtId(tginfo->dobj.name));
   17591 ECB             :     }
   17592                 : 
   17593 CBC         488 :     appendPQExpBuffer(trigprefix, "TRIGGER %s ON",
   17594 GIC         488 :                       fmtId(tginfo->dobj.name));
   17595 ECB             : 
   17596 CBC         488 :     tag = psprintf("%s %s", tbinfo->dobj.name, tginfo->dobj.name);
   17597 ECB             : 
   17598 GIC         488 :     if (tginfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   17599             488 :         ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId,
   17600             488 :                      ARCHIVE_OPTS(.tag = tag,
   17601                 :                                   .namespace = tbinfo->dobj.namespace->dobj.name,
   17602                 :                                   .owner = tbinfo->rolname,
   17603                 :                                   .description = "TRIGGER",
   17604                 :                                   .section = SECTION_POST_DATA,
   17605                 :                                   .createStmt = query->data,
   17606                 :                                   .dropStmt = delqry->data));
   17607                 : 
   17608             488 :     if (tginfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   17609 UIC           0 :         dumpComment(fout, trigprefix->data, qtabname,
   17610               0 :                     tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
   17611               0 :                     tginfo->dobj.catId, 0, tginfo->dobj.dumpId);
   17612                 : 
   17613 GIC         488 :     free(tag);
   17614             488 :     destroyPQExpBuffer(query);
   17615             488 :     destroyPQExpBuffer(delqry);
   17616             488 :     destroyPQExpBuffer(trigprefix);
   17617 CBC         488 :     destroyPQExpBuffer(trigidentity);
   17618 GIC         488 :     free(qtabname);
   17619 ECB             : }
   17620                 : 
   17621                 : /*
   17622 EUB             :  * dumpEventTrigger
   17623                 :  *    write the declaration of one user-defined event trigger
   17624                 :  */
   17625 ECB             : static void
   17626 GIC          38 : dumpEventTrigger(Archive *fout, const EventTriggerInfo *evtinfo)
   17627 ECB             : {
   17628 CBC          38 :     DumpOptions *dopt = fout->dopt;
   17629 ECB             :     PQExpBuffer query;
   17630                 :     PQExpBuffer delqry;
   17631                 :     char       *qevtname;
   17632                 : 
   17633                 :     /* Do nothing in data-only dump */
   17634 GIC          38 :     if (dopt->dataOnly)
   17635 CBC           3 :         return;
   17636 ECB             : 
   17637 CBC          35 :     query = createPQExpBuffer();
   17638 GIC          35 :     delqry = createPQExpBuffer();
   17639                 : 
   17640              35 :     qevtname = pg_strdup(fmtId(evtinfo->dobj.name));
   17641                 : 
   17642              35 :     appendPQExpBufferStr(query, "CREATE EVENT TRIGGER ");
   17643              35 :     appendPQExpBufferStr(query, qevtname);
   17644              35 :     appendPQExpBufferStr(query, " ON ");
   17645              35 :     appendPQExpBufferStr(query, fmtId(evtinfo->evtevent));
   17646                 : 
   17647              35 :     if (strcmp("", evtinfo->evttags) != 0)
   17648                 :     {
   17649 LBC           0 :         appendPQExpBufferStr(query, "\n         WHEN TAG IN (");
   17650 UBC           0 :         appendPQExpBufferStr(query, evtinfo->evttags);
   17651               0 :         appendPQExpBufferChar(query, ')');
   17652 EUB             :     }
   17653                 : 
   17654 CBC          35 :     appendPQExpBufferStr(query, "\n   EXECUTE FUNCTION ");
   17655 GBC          35 :     appendPQExpBufferStr(query, evtinfo->evtfname);
   17656              35 :     appendPQExpBufferStr(query, "();\n");
   17657 EUB             : 
   17658 GIC          35 :     if (evtinfo->evtenabled != 'O')
   17659 ECB             :     {
   17660 UIC           0 :         appendPQExpBuffer(query, "\nALTER EVENT TRIGGER %s ",
   17661 ECB             :                           qevtname);
   17662 LBC           0 :         switch (evtinfo->evtenabled)
   17663 ECB             :         {
   17664 LBC           0 :             case 'D':
   17665 UIC           0 :                 appendPQExpBufferStr(query, "DISABLE");
   17666               0 :                 break;
   17667               0 :             case 'A':
   17668               0 :                 appendPQExpBufferStr(query, "ENABLE ALWAYS");
   17669               0 :                 break;
   17670               0 :             case 'R':
   17671 LBC           0 :                 appendPQExpBufferStr(query, "ENABLE REPLICA");
   17672 UIC           0 :                 break;
   17673 LBC           0 :             default:
   17674 UIC           0 :                 appendPQExpBufferStr(query, "ENABLE");
   17675               0 :                 break;
   17676                 :         }
   17677 LBC           0 :         appendPQExpBufferStr(query, ";\n");
   17678                 :     }
   17679 ECB             : 
   17680 GIC          35 :     appendPQExpBuffer(delqry, "DROP EVENT TRIGGER %s;\n",
   17681 ECB             :                       qevtname);
   17682                 : 
   17683 CBC          35 :     if (dopt->binary_upgrade)
   17684 GIC           1 :         binary_upgrade_extension_member(query, &evtinfo->dobj,
   17685 ECB             :                                         "EVENT TRIGGER", qevtname, NULL);
   17686 EUB             : 
   17687 GIC          35 :     if (evtinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   17688              35 :         ArchiveEntry(fout, evtinfo->dobj.catId, evtinfo->dobj.dumpId,
   17689              35 :                      ARCHIVE_OPTS(.tag = evtinfo->dobj.name,
   17690                 :                                   .owner = evtinfo->evtowner,
   17691 ECB             :                                   .description = "EVENT TRIGGER",
   17692                 :                                   .section = SECTION_POST_DATA,
   17693                 :                                   .createStmt = query->data,
   17694                 :                                   .dropStmt = delqry->data));
   17695                 : 
   17696 CBC          35 :     if (evtinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   17697 LBC           0 :         dumpComment(fout, "EVENT TRIGGER", qevtname,
   17698 UIC           0 :                     NULL, evtinfo->evtowner,
   17699               0 :                     evtinfo->dobj.catId, 0, evtinfo->dobj.dumpId);
   17700 ECB             : 
   17701 CBC          35 :     destroyPQExpBuffer(query);
   17702              35 :     destroyPQExpBuffer(delqry);
   17703 GIC          35 :     free(qevtname);
   17704                 : }
   17705                 : 
   17706                 : /*
   17707                 :  * dumpRule
   17708                 :  *      Dump a rule
   17709                 :  */
   17710                 : static void
   17711 CBC         821 : dumpRule(Archive *fout, const RuleInfo *rinfo)
   17712                 : {
   17713             821 :     DumpOptions *dopt = fout->dopt;
   17714             821 :     TableInfo  *tbinfo = rinfo->ruletable;
   17715                 :     bool        is_view;
   17716                 :     PQExpBuffer query;
   17717                 :     PQExpBuffer cmd;
   17718                 :     PQExpBuffer delcmd;
   17719                 :     PQExpBuffer ruleprefix;
   17720                 :     char       *qtabname;
   17721 ECB             :     PGresult   *res;
   17722                 :     char       *tag;
   17723                 : 
   17724                 :     /* Do nothing in data-only dump */
   17725 GIC         821 :     if (dopt->dataOnly)
   17726              27 :         return;
   17727                 : 
   17728                 :     /*
   17729                 :      * If it is an ON SELECT rule that is created implicitly by CREATE VIEW,
   17730                 :      * we do not want to dump it as a separate object.
   17731                 :      */
   17732             794 :     if (!rinfo->separate)
   17733             589 :         return;
   17734                 : 
   17735                 :     /*
   17736                 :      * If it's an ON SELECT rule, we want to print it as a view definition,
   17737 ECB             :      * instead of a rule.
   17738                 :      */
   17739 GIC         205 :     is_view = (rinfo->ev_type == '1' && rinfo->is_instead);
   17740 ECB             : 
   17741 CBC         205 :     query = createPQExpBuffer();
   17742             205 :     cmd = createPQExpBuffer();
   17743             205 :     delcmd = createPQExpBuffer();
   17744 GIC         205 :     ruleprefix = createPQExpBuffer();
   17745 ECB             : 
   17746 GIC         205 :     qtabname = pg_strdup(fmtId(tbinfo->dobj.name));
   17747 ECB             : 
   17748 CBC         205 :     if (is_view)
   17749                 :     {
   17750 ECB             :         PQExpBuffer result;
   17751                 : 
   17752                 :         /*
   17753                 :          * We need OR REPLACE here because we'll be replacing a dummy view.
   17754                 :          * Otherwise this should look largely like the regular view dump code.
   17755                 :          */
   17756 GIC          10 :         appendPQExpBuffer(cmd, "CREATE OR REPLACE VIEW %s",
   17757              10 :                           fmtQualifiedDumpable(tbinfo));
   17758 GBC          10 :         if (nonemptyReloptions(tbinfo->reloptions))
   17759                 :         {
   17760 UBC           0 :             appendPQExpBufferStr(cmd, " WITH (");
   17761               0 :             appendReloptionsArrayAH(cmd, tbinfo->reloptions, "", fout);
   17762 UIC           0 :             appendPQExpBufferChar(cmd, ')');
   17763                 :         }
   17764 GIC          10 :         result = createViewAsClause(fout, tbinfo);
   17765 GBC          10 :         appendPQExpBuffer(cmd, " AS\n%s", result->data);
   17766              10 :         destroyPQExpBuffer(result);
   17767 GIC          10 :         if (tbinfo->checkoption != NULL)
   17768 UBC           0 :             appendPQExpBuffer(cmd, "\n  WITH %s CHECK OPTION",
   17769                 :                               tbinfo->checkoption);
   17770 GIC          10 :         appendPQExpBufferStr(cmd, ";\n");
   17771 EUB             :     }
   17772                 :     else
   17773                 :     {
   17774                 :         /* In the rule case, just print pg_get_ruledef's result verbatim */
   17775 GBC         195 :         appendPQExpBuffer(query,
   17776 EUB             :                           "SELECT pg_catalog.pg_get_ruledef('%u'::pg_catalog.oid)",
   17777 GIC         195 :                           rinfo->dobj.catId.oid);
   17778 EUB             : 
   17779 GIC         195 :         res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   17780 EUB             : 
   17781 GBC         195 :         if (PQntuples(res) != 1)
   17782 UIC           0 :             pg_fatal("query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned",
   17783 EUB             :                      rinfo->dobj.name, tbinfo->dobj.name);
   17784                 : 
   17785 GIC         195 :         printfPQExpBuffer(cmd, "%s\n", PQgetvalue(res, 0, 0));
   17786 EUB             : 
   17787 GIC         195 :         PQclear(res);
   17788 EUB             :     }
   17789                 : 
   17790                 :     /*
   17791                 :      * Add the command to alter the rules replication firing semantics if it
   17792                 :      * differs from the default.
   17793                 :      */
   17794 GBC         205 :     if (rinfo->ev_enabled != 'O')
   17795                 :     {
   17796 UBC           0 :         appendPQExpBuffer(cmd, "ALTER TABLE %s ", fmtQualifiedDumpable(tbinfo));
   17797               0 :         switch (rinfo->ev_enabled)
   17798                 :         {
   17799               0 :             case 'A':
   17800               0 :                 appendPQExpBuffer(cmd, "ENABLE ALWAYS RULE %s;\n",
   17801 UIC           0 :                                   fmtId(rinfo->dobj.name));
   17802 UBC           0 :                 break;
   17803 UIC           0 :             case 'R':
   17804 UBC           0 :                 appendPQExpBuffer(cmd, "ENABLE REPLICA RULE %s;\n",
   17805               0 :                                   fmtId(rinfo->dobj.name));
   17806 UIC           0 :                 break;
   17807 UBC           0 :             case 'D':
   17808               0 :                 appendPQExpBuffer(cmd, "DISABLE RULE %s;\n",
   17809 UIC           0 :                                   fmtId(rinfo->dobj.name));
   17810 UBC           0 :                 break;
   17811 EUB             :         }
   17812                 :     }
   17813                 : 
   17814 GIC         205 :     if (is_view)
   17815 EUB             :     {
   17816                 :         /*
   17817                 :          * We can't DROP a view's ON SELECT rule.  Instead, use CREATE OR
   17818                 :          * REPLACE VIEW to replace the rule with something with minimal
   17819                 :          * dependencies.
   17820                 :          */
   17821                 :         PQExpBuffer result;
   17822                 : 
   17823 GBC          10 :         appendPQExpBuffer(delcmd, "CREATE OR REPLACE VIEW %s",
   17824              10 :                           fmtQualifiedDumpable(tbinfo));
   17825              10 :         result = createDummyViewAsClause(fout, tbinfo);
   17826 GIC          10 :         appendPQExpBuffer(delcmd, " AS\n%s;\n", result->data);
   17827 GBC          10 :         destroyPQExpBuffer(result);
   17828                 :     }
   17829                 :     else
   17830 EUB             :     {
   17831 GBC         195 :         appendPQExpBuffer(delcmd, "DROP RULE %s ",
   17832 GIC         195 :                           fmtId(rinfo->dobj.name));
   17833 GBC         195 :         appendPQExpBuffer(delcmd, "ON %s;\n",
   17834 GIC         195 :                           fmtQualifiedDumpable(tbinfo));
   17835                 :     }
   17836 EUB             : 
   17837 GBC         205 :     appendPQExpBuffer(ruleprefix, "RULE %s ON",
   17838 GIC         205 :                       fmtId(rinfo->dobj.name));
   17839 EUB             : 
   17840 GIC         205 :     tag = psprintf("%s %s", tbinfo->dobj.name, rinfo->dobj.name);
   17841 EUB             : 
   17842 GBC         205 :     if (rinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
   17843 GIC         205 :         ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId,
   17844             205 :                      ARCHIVE_OPTS(.tag = tag,
   17845 EUB             :                                   .namespace = tbinfo->dobj.namespace->dobj.name,
   17846                 :                                   .owner = tbinfo->rolname,
   17847                 :                                   .description = "RULE",
   17848                 :                                   .section = SECTION_POST_DATA,
   17849                 :                                   .createStmt = cmd->data,
   17850                 :                                   .dropStmt = delcmd->data));
   17851                 : 
   17852                 :     /* Dump rule comments */
   17853 GIC         205 :     if (rinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
   17854 UIC           0 :         dumpComment(fout, ruleprefix->data, qtabname,
   17855               0 :                     tbinfo->dobj.namespace->dobj.name,
   17856 EUB             :                     tbinfo->rolname,
   17857 UBC           0 :                     rinfo->dobj.catId, 0, rinfo->dobj.dumpId);
   17858 EUB             : 
   17859 GBC         205 :     free(tag);
   17860 GIC         205 :     destroyPQExpBuffer(query);
   17861 GBC         205 :     destroyPQExpBuffer(cmd);
   17862             205 :     destroyPQExpBuffer(delcmd);
   17863 GIC         205 :     destroyPQExpBuffer(ruleprefix);
   17864             205 :     free(qtabname);
   17865                 : }
   17866 ECB             : 
   17867                 : /*
   17868                 :  * getExtensionMembership --- obtain extension membership data
   17869                 :  *
   17870                 :  * We need to identify objects that are extension members as soon as they're
   17871                 :  * loaded, so that we can correctly determine whether they need to be dumped.
   17872                 :  * Generally speaking, extension member objects will get marked as *not* to
   17873                 :  * be dumped, as they will be recreated by the single CREATE EXTENSION
   17874                 :  * command.  However, in binary upgrade mode we still need to dump the members
   17875                 :  * individually.
   17876                 :  */
   17877                 : void
   17878 GIC         119 : getExtensionMembership(Archive *fout, ExtensionInfo extinfo[],
   17879                 :                        int numExtensions)
   17880 ECB             : {
   17881                 :     PQExpBuffer query;
   17882                 :     PGresult   *res;
   17883                 :     int         ntups,
   17884                 :                 i;
   17885                 :     int         i_classid,
   17886                 :                 i_objid,
   17887                 :                 i_refobjid;
   17888                 :     ExtensionInfo *ext;
   17889                 : 
   17890                 :     /* Nothing to do if no extensions */
   17891 GBC         119 :     if (numExtensions == 0)
   17892 UIC           0 :         return;
   17893 EUB             : 
   17894 GBC         119 :     query = createPQExpBuffer();
   17895 ECB             : 
   17896                 :     /* refclassid constraint is redundant but may speed the search */
   17897 CBC         119 :     appendPQExpBufferStr(query, "SELECT "
   17898 ECB             :                          "classid, objid, refobjid "
   17899                 :                          "FROM pg_depend "
   17900                 :                          "WHERE refclassid = 'pg_extension'::regclass "
   17901                 :                          "AND deptype = 'e' "
   17902                 :                          "ORDER BY 3");
   17903                 : 
   17904 GIC         119 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   17905 ECB             : 
   17906 GIC         119 :     ntups = PQntuples(res);
   17907 EUB             : 
   17908 GBC         119 :     i_classid = PQfnumber(res, "classid");
   17909             119 :     i_objid = PQfnumber(res, "objid");
   17910             119 :     i_refobjid = PQfnumber(res, "refobjid");
   17911                 : 
   17912 EUB             :     /*
   17913                 :      * Since we ordered the SELECT by referenced ID, we can expect that
   17914                 :      * multiple entries for the same extension will appear together; this
   17915                 :      * saves on searches.
   17916                 :      */
   17917 GBC         119 :     ext = NULL;
   17918 EUB             : 
   17919 GBC         925 :     for (i = 0; i < ntups; i++)
   17920 EUB             :     {
   17921                 :         CatalogId   objId;
   17922                 :         Oid         extId;
   17923                 : 
   17924 GBC         806 :         objId.tableoid = atooid(PQgetvalue(res, i, i_classid));
   17925 GIC         806 :         objId.oid = atooid(PQgetvalue(res, i, i_objid));
   17926 GBC         806 :         extId = atooid(PQgetvalue(res, i, i_refobjid));
   17927 EUB             : 
   17928 GIC         806 :         if (ext == NULL ||
   17929             687 :             ext->dobj.catId.oid != extId)
   17930 CBC         141 :             ext = findExtensionByOid(extId);
   17931 ECB             : 
   17932 GIC         806 :         if (ext == NULL)
   17933 ECB             :         {
   17934                 :             /* shouldn't happen */
   17935 LBC           0 :             pg_log_warning("could not find referenced extension %u", extId);
   17936               0 :             continue;
   17937 ECB             :         }
   17938                 : 
   17939 GIC         806 :         recordExtensionMembership(objId, ext);
   17940                 :     }
   17941                 : 
   17942             119 :     PQclear(res);
   17943                 : 
   17944             119 :     destroyPQExpBuffer(query);
   17945 ECB             : }
   17946 EUB             : 
   17947                 : /*
   17948                 :  * processExtensionTables --- deal with extension configuration tables
   17949                 :  *
   17950 ECB             :  * There are two parts to this process:
   17951                 :  *
   17952                 :  * 1. Identify and create dump records for extension configuration tables.
   17953                 :  *
   17954                 :  *    Extensions can mark tables as "configuration", which means that the user
   17955                 :  *    is able and expected to modify those tables after the extension has been
   17956                 :  *    loaded.  For these tables, we dump out only the data- the structure is
   17957                 :  *    expected to be handled at CREATE EXTENSION time, including any indexes or
   17958                 :  *    foreign keys, which brings us to-
   17959                 :  *
   17960                 :  * 2. Record FK dependencies between configuration tables.
   17961                 :  *
   17962                 :  *    Due to the FKs being created at CREATE EXTENSION time and therefore before
   17963                 :  *    the data is loaded, we have to work out what the best order for reloading
   17964                 :  *    the data is, to avoid FK violations when the tables are restored.  This is
   17965                 :  *    not perfect- we can't handle circular dependencies and if any exist they
   17966                 :  *    will cause an invalid dump to be produced (though at least all of the data
   17967                 :  *    is included for a user to manually restore).  This is currently documented
   17968                 :  *    but perhaps we can provide a better solution in the future.
   17969                 :  */
   17970                 : void
   17971 CBC         118 : processExtensionTables(Archive *fout, ExtensionInfo extinfo[],
   17972 ECB             :                        int numExtensions)
   17973                 : {
   17974 CBC         118 :     DumpOptions *dopt = fout->dopt;
   17975 ECB             :     PQExpBuffer query;
   17976                 :     PGresult   *res;
   17977                 :     int         ntups,
   17978                 :                 i;
   17979                 :     int         i_conrelid,
   17980                 :                 i_confrelid;
   17981                 : 
   17982                 :     /* Nothing to do if no extensions */
   17983 GIC         118 :     if (numExtensions == 0)
   17984 LBC           0 :         return;
   17985                 : 
   17986 EUB             :     /*
   17987                 :      * Identify extension configuration tables and create TableDataInfo
   17988                 :      * objects for them, ensuring their data will be dumped even though the
   17989                 :      * tables themselves won't be.
   17990                 :      *
   17991 ECB             :      * Note that we create TableDataInfo objects even in schemaOnly mode, ie,
   17992                 :      * user data in a configuration table is treated like schema data. This
   17993                 :      * seems appropriate since system data in a config table would get
   17994                 :      * reloaded by CREATE EXTENSION.  If the extension is not listed in the
   17995                 :      * list of extensions to be included, none of its data is dumped.
   17996                 :      */
   17997 GBC         258 :     for (i = 0; i < numExtensions; i++)
   17998                 :     {
   17999             140 :         ExtensionInfo *curext = &(extinfo[i]);
   18000 GIC         140 :         char       *extconfig = curext->extconfig;
   18001 GBC         140 :         char       *extcondition = curext->extcondition;
   18002             140 :         char      **extconfigarray = NULL;
   18003             140 :         char      **extconditionarray = NULL;
   18004             140 :         int         nconfigitems = 0;
   18005             140 :         int         nconditionitems = 0;
   18006 EUB             : 
   18007                 :         /*
   18008                 :          * Check if this extension is listed as to include in the dump.  If
   18009                 :          * not, any table data associated with it is discarded.
   18010                 :          */
   18011 GBC         140 :         if (extension_include_oids.head != NULL &&
   18012               8 :             !simple_oid_list_member(&extension_include_oids,
   18013                 :                                     curext->dobj.catId.oid))
   18014               4 :             continue;
   18015                 : 
   18016 GIC         136 :         if (strlen(extconfig) != 0 || strlen(extcondition) != 0)
   18017 ECB             :         {
   18018                 :             int         j;
   18019                 : 
   18020 CBC          19 :             if (!parsePGArray(extconfig, &extconfigarray, &nconfigitems))
   18021 LBC           0 :                 pg_fatal("could not parse %s array", "extconfig");
   18022 GIC          19 :             if (!parsePGArray(extcondition, &extconditionarray, &nconditionitems))
   18023 UIC           0 :                 pg_fatal("could not parse %s array", "extcondition");
   18024 CBC          19 :             if (nconfigitems != nconditionitems)
   18025 LBC           0 :                 pg_fatal("mismatched number of configurations and conditions for extension");
   18026 ECB             : 
   18027 GIC          57 :             for (j = 0; j < nconfigitems; j++)
   18028                 :             {
   18029                 :                 TableInfo  *configtbl;
   18030              38 :                 Oid         configtbloid = atooid(extconfigarray[j]);
   18031              38 :                 bool        dumpobj =
   18032              38 :                 curext->dobj.dump & DUMP_COMPONENT_DEFINITION;
   18033 ECB             : 
   18034 GBC          38 :                 configtbl = findTableByOid(configtbloid);
   18035              38 :                 if (configtbl == NULL)
   18036 UBC           0 :                     continue;
   18037                 : 
   18038 ECB             :                 /*
   18039                 :                  * Tables of not-to-be-dumped extensions shouldn't be dumped
   18040                 :                  * unless the table or its schema is explicitly included
   18041                 :                  */
   18042 GIC          38 :                 if (!(curext->dobj.dump & DUMP_COMPONENT_DEFINITION))
   18043                 :                 {
   18044                 :                     /* check table explicitly requested */
   18045               2 :                     if (table_include_oids.head != NULL &&
   18046 UIC           0 :                         simple_oid_list_member(&table_include_oids,
   18047                 :                                                configtbloid))
   18048 LBC           0 :                         dumpobj = true;
   18049                 : 
   18050 ECB             :                     /* check table's schema explicitly requested */
   18051 CBC           2 :                     if (configtbl->dobj.namespace->dobj.dump &
   18052                 :                         DUMP_COMPONENT_DATA)
   18053 GIC           2 :                         dumpobj = true;
   18054                 :                 }
   18055                 : 
   18056                 :                 /* check table excluded by an exclusion switch */
   18057              40 :                 if (table_exclude_oids.head != NULL &&
   18058               2 :                     simple_oid_list_member(&table_exclude_oids,
   18059                 :                                            configtbloid))
   18060               1 :                     dumpobj = false;
   18061                 : 
   18062 ECB             :                 /* check schema excluded by an exclusion switch */
   18063 CBC          38 :                 if (simple_oid_list_member(&schema_exclude_oids,
   18064 GIC          38 :                                            configtbl->dobj.namespace->dobj.catId.oid))
   18065 UIC           0 :                     dumpobj = false;
   18066                 : 
   18067 GIC          38 :                 if (dumpobj)
   18068                 :                 {
   18069 CBC          37 :                     makeTableDataInfo(dopt, configtbl);
   18070              37 :                     if (configtbl->dataObj != NULL)
   18071                 :                     {
   18072 GIC          37 :                         if (strlen(extconditionarray[j]) > 0)
   18073 UIC           0 :                             configtbl->dataObj->filtercond = pg_strdup(extconditionarray[j]);
   18074                 :                     }
   18075                 :                 }
   18076 ECB             :             }
   18077                 :         }
   18078 CBC         136 :         if (extconfigarray)
   18079              19 :             free(extconfigarray);
   18080             136 :         if (extconditionarray)
   18081              19 :             free(extconditionarray);
   18082                 :     }
   18083 ECB             : 
   18084                 :     /*
   18085                 :      * Now that all the TableDataInfo objects have been created for all the
   18086                 :      * extensions, check their FK dependencies and register them to try and
   18087                 :      * dump the data out in an order that they can be restored in.
   18088                 :      *
   18089                 :      * Note that this is not a problem for user tables as their FKs are
   18090                 :      * recreated after the data has been loaded.
   18091                 :      */
   18092                 : 
   18093 CBC         118 :     query = createPQExpBuffer();
   18094 ECB             : 
   18095 CBC         118 :     printfPQExpBuffer(query,
   18096                 :                       "SELECT conrelid, confrelid "
   18097 EUB             :                       "FROM pg_constraint "
   18098                 :                       "JOIN pg_depend ON (objid = confrelid) "
   18099                 :                       "WHERE contype = 'f' "
   18100                 :                       "AND refclassid = 'pg_extension'::regclass "
   18101 ECB             :                       "AND classid = 'pg_class'::regclass;");
   18102                 : 
   18103 CBC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   18104             118 :     ntups = PQntuples(res);
   18105 EUB             : 
   18106 GIC         118 :     i_conrelid = PQfnumber(res, "conrelid");
   18107 CBC         118 :     i_confrelid = PQfnumber(res, "confrelid");
   18108                 : 
   18109                 :     /* Now get the dependencies and register them */
   18110 GIC         118 :     for (i = 0; i < ntups; i++)
   18111                 :     {
   18112 ECB             :         Oid         conrelid,
   18113                 :                     confrelid;
   18114                 :         TableInfo  *reftable,
   18115                 :                    *contable;
   18116                 : 
   18117 UIC           0 :         conrelid = atooid(PQgetvalue(res, i, i_conrelid));
   18118 LBC           0 :         confrelid = atooid(PQgetvalue(res, i, i_confrelid));
   18119 UBC           0 :         contable = findTableByOid(conrelid);
   18120 UIC           0 :         reftable = findTableByOid(confrelid);
   18121                 : 
   18122 LBC           0 :         if (reftable == NULL ||
   18123 UIC           0 :             reftable->dataObj == NULL ||
   18124 LBC           0 :             contable == NULL ||
   18125 UIC           0 :             contable->dataObj == NULL)
   18126               0 :             continue;
   18127                 : 
   18128                 :         /*
   18129                 :          * Make referencing TABLE_DATA object depend on the referenced table's
   18130                 :          * TABLE_DATA object.
   18131 ECB             :          */
   18132 UIC           0 :         addObjectDependency(&contable->dataObj->dobj,
   18133 UBC           0 :                             reftable->dataObj->dobj.dumpId);
   18134 EUB             :     }
   18135 GIC         118 :     PQclear(res);
   18136 GBC         118 :     destroyPQExpBuffer(query);
   18137 EUB             : }
   18138                 : 
   18139                 : /*
   18140                 :  * getDependencies --- obtain available dependency data
   18141                 :  */
   18142                 : static void
   18143 GBC         118 : getDependencies(Archive *fout)
   18144 EUB             : {
   18145                 :     PQExpBuffer query;
   18146                 :     PGresult   *res;
   18147                 :     int         ntups,
   18148                 :                 i;
   18149                 :     int         i_classid,
   18150                 :                 i_objid,
   18151 ECB             :                 i_refclassid,
   18152                 :                 i_refobjid,
   18153                 :                 i_deptype;
   18154                 :     DumpableObject *dobj,
   18155                 :                *refdobj;
   18156                 : 
   18157 GIC         118 :     pg_log_info("reading dependency data");
   18158                 : 
   18159             118 :     query = createPQExpBuffer();
   18160 ECB             : 
   18161                 :     /*
   18162                 :      * Messy query to collect the dependency data we need.  Note that we
   18163                 :      * ignore the sub-object column, so that dependencies of or on a column
   18164                 :      * look the same as dependencies of or on a whole table.
   18165                 :      *
   18166                 :      * PIN dependencies aren't interesting, and EXTENSION dependencies were
   18167                 :      * already processed by getExtensionMembership.
   18168                 :      */
   18169 CBC         118 :     appendPQExpBufferStr(query, "SELECT "
   18170 ECB             :                          "classid, objid, refclassid, refobjid, deptype "
   18171                 :                          "FROM pg_depend "
   18172                 :                          "WHERE deptype != 'p' AND deptype != 'e'\n");
   18173                 : 
   18174                 :     /*
   18175                 :      * Since we don't treat pg_amop entries as separate DumpableObjects, we
   18176                 :      * have to translate their dependencies into dependencies of their parent
   18177                 :      * opfamily.  Ignore internal dependencies though, as those will point to
   18178                 :      * their parent opclass, which we needn't consider here (and if we did,
   18179                 :      * it'd just result in circular dependencies).  Also, "loose" opfamily
   18180                 :      * entries will have dependencies on their parent opfamily, which we
   18181                 :      * should drop since they'd likewise become useless self-dependencies.
   18182                 :      * (But be sure to keep deps on *other* opfamilies; see amopsortfamily.)
   18183                 :      */
   18184 GIC         118 :     appendPQExpBufferStr(query, "UNION ALL\n"
   18185                 :                          "SELECT 'pg_opfamily'::regclass AS classid, amopfamily AS objid, refclassid, refobjid, deptype "
   18186                 :                          "FROM pg_depend d, pg_amop o "
   18187                 :                          "WHERE deptype NOT IN ('p', 'e', 'i') AND "
   18188                 :                          "classid = 'pg_amop'::regclass AND objid = o.oid "
   18189                 :                          "AND NOT (refclassid = 'pg_opfamily'::regclass AND amopfamily = refobjid)\n");
   18190 ECB             : 
   18191 EUB             :     /* Likewise for pg_amproc entries */
   18192 GBC         118 :     appendPQExpBufferStr(query, "UNION ALL\n"
   18193                 :                          "SELECT 'pg_opfamily'::regclass AS classid, amprocfamily AS objid, refclassid, refobjid, deptype "
   18194 EUB             :                          "FROM pg_depend d, pg_amproc p "
   18195                 :                          "WHERE deptype NOT IN ('p', 'e', 'i') AND "
   18196 ECB             :                          "classid = 'pg_amproc'::regclass AND objid = p.oid "
   18197                 :                          "AND NOT (refclassid = 'pg_opfamily'::regclass AND amprocfamily = refobjid)\n");
   18198                 : 
   18199                 :     /* Sort the output for efficiency below */
   18200 CBC         118 :     appendPQExpBufferStr(query, "ORDER BY 1,2");
   18201 ECB             : 
   18202 GIC         118 :     res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
   18203                 : 
   18204             118 :     ntups = PQntuples(res);
   18205                 : 
   18206             118 :     i_classid = PQfnumber(res, "classid");
   18207             118 :     i_objid = PQfnumber(res, "objid");
   18208             118 :     i_refclassid = PQfnumber(res, "refclassid");
   18209             118 :     i_refobjid = PQfnumber(res, "refobjid");
   18210             118 :     i_deptype = PQfnumber(res, "deptype");
   18211                 : 
   18212                 :     /*
   18213                 :      * Since we ordered the SELECT by referencing ID, we can expect that
   18214                 :      * multiple entries for the same object will appear together; this saves
   18215 ECB             :      * on searches.
   18216                 :      */
   18217 GIC         118 :     dobj = NULL;
   18218                 : 
   18219          253999 :     for (i = 0; i < ntups; i++)
   18220                 :     {
   18221                 :         CatalogId   objId;
   18222                 :         CatalogId   refobjId;
   18223                 :         char        deptype;
   18224                 : 
   18225          253881 :         objId.tableoid = atooid(PQgetvalue(res, i, i_classid));
   18226          253881 :         objId.oid = atooid(PQgetvalue(res, i, i_objid));
   18227          253881 :         refobjId.tableoid = atooid(PQgetvalue(res, i, i_refclassid));
   18228 CBC      253881 :         refobjId.oid = atooid(PQgetvalue(res, i, i_refobjid));
   18229 GBC      253881 :         deptype = *(PQgetvalue(res, i, i_deptype));
   18230                 : 
   18231 CBC      253881 :         if (dobj == NULL ||
   18232 GIC      239304 :             dobj->catId.tableoid != objId.tableoid ||
   18233          237783 :             dobj->catId.oid != objId.oid)
   18234 CBC      109875 :             dobj = findObjectByCatalogId(objId);
   18235                 : 
   18236                 :         /*
   18237                 :          * Failure to find objects mentioned in pg_depend is not unexpected,
   18238                 :          * since for example we don't collect info about TOAST tables.
   18239                 :          */
   18240 GIC      253881 :         if (dobj == NULL)
   18241 ECB             :         {
   18242                 : #ifdef NOT_USED
   18243                 :             pg_log_warning("no referencing object %u %u",
   18244                 :                            objId.tableoid, objId.oid);
   18245                 : #endif
   18246 CBC       15043 :             continue;
   18247 ECB             :         }
   18248                 : 
   18249 GIC      239415 :         refdobj = findObjectByCatalogId(refobjId);
   18250                 : 
   18251          239415 :         if (refdobj == NULL)
   18252                 :         {
   18253                 : #ifdef NOT_USED
   18254 ECB             :             pg_log_warning("no referenced object %u %u",
   18255                 :                            refobjId.tableoid, refobjId.oid);
   18256                 : #endif
   18257 GIC         577 :             continue;
   18258                 :         }
   18259                 : 
   18260                 :         /*
   18261 ECB             :          * For 'x' dependencies, mark the object for later; we still add the
   18262                 :          * normal dependency, for possible ordering purposes.  Currently
   18263                 :          * pg_dump_sort.c knows to put extensions ahead of all object types
   18264                 :          * that could possibly depend on them, but this is safer.
   18265                 :          */
   18266 CBC      238838 :         if (deptype == 'x')
   18267              40 :             dobj->depends_on_ext = true;
   18268                 : 
   18269 ECB             :         /*
   18270                 :          * Ordinarily, table rowtypes have implicit dependencies on their
   18271                 :          * tables.  However, for a composite type the implicit dependency goes
   18272 EUB             :          * the other way in pg_depend; which is the right thing for DROP but
   18273                 :          * it doesn't produce the dependency ordering we need. So in that one
   18274                 :          * case, we reverse the direction of the dependency.
   18275                 :          */
   18276 CBC      238838 :         if (deptype == 'i' &&
   18277 GIC       65124 :             dobj->objType == DO_TABLE &&
   18278             786 :             refdobj->objType == DO_TYPE)
   18279 CBC         137 :             addObjectDependency(refdobj, dobj->dumpId);
   18280                 :         else
   18281 ECB             :             /* normal case */
   18282 GIC      238701 :             addObjectDependency(dobj, refdobj->dumpId);
   18283                 :     }
   18284                 : 
   18285             118 :     PQclear(res);
   18286                 : 
   18287             118 :     destroyPQExpBuffer(query);
   18288             118 : }
   18289                 : 
   18290                 : 
   18291                 : /*
   18292                 :  * createBoundaryObjects - create dummy DumpableObjects to represent
   18293                 :  * dump section boundaries.
   18294                 :  */
   18295                 : static DumpableObject *
   18296             118 : createBoundaryObjects(void)
   18297                 : {
   18298                 :     DumpableObject *dobjs;
   18299                 : 
   18300             118 :     dobjs = (DumpableObject *) pg_malloc(2 * sizeof(DumpableObject));
   18301                 : 
   18302             118 :     dobjs[0].objType = DO_PRE_DATA_BOUNDARY;
   18303             118 :     dobjs[0].catId = nilCatalogId;
   18304             118 :     AssignDumpId(dobjs + 0);
   18305             118 :     dobjs[0].name = pg_strdup("PRE-DATA BOUNDARY");
   18306                 : 
   18307             118 :     dobjs[1].objType = DO_POST_DATA_BOUNDARY;
   18308 CBC         118 :     dobjs[1].catId = nilCatalogId;
   18309 GIC         118 :     AssignDumpId(dobjs + 1);
   18310             118 :     dobjs[1].name = pg_strdup("POST-DATA BOUNDARY");
   18311 ECB             : 
   18312 GIC         118 :     return dobjs;
   18313                 : }
   18314                 : 
   18315                 : /*
   18316                 :  * addBoundaryDependencies - add dependencies as needed to enforce the dump
   18317                 :  * section boundaries.
   18318                 :  */
   18319                 : static void
   18320 CBC         118 : addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
   18321 EUB             :                         DumpableObject *boundaryObjs)
   18322                 : {
   18323 GIC         118 :     DumpableObject *preDataBound = boundaryObjs + 0;
   18324             118 :     DumpableObject *postDataBound = boundaryObjs + 1;
   18325                 :     int         i;
   18326                 : 
   18327          510138 :     for (i = 0; i < numObjs; i++)
   18328                 :     {
   18329          510020 :         DumpableObject *dobj = dobjs[i];
   18330                 : 
   18331                 :         /*
   18332                 :          * The classification of object types here must match the SECTION_xxx
   18333                 :          * values assigned during subsequent ArchiveEntry calls!
   18334 ECB             :          */
   18335 GIC      510020 :         switch (dobj->objType)
   18336 ECB             :         {
   18337 CBC      482225 :             case DO_NAMESPACE:
   18338 ECB             :             case DO_EXTENSION:
   18339                 :             case DO_TYPE:
   18340                 :             case DO_SHELL_TYPE:
   18341                 :             case DO_FUNC:
   18342                 :             case DO_AGG:
   18343                 :             case DO_OPERATOR:
   18344                 :             case DO_ACCESS_METHOD:
   18345                 :             case DO_OPCLASS:
   18346                 :             case DO_OPFAMILY:
   18347                 :             case DO_COLLATION:
   18348                 :             case DO_CONVERSION:
   18349                 :             case DO_TABLE:
   18350                 :             case DO_TABLE_ATTACH:
   18351                 :             case DO_ATTRDEF:
   18352                 :             case DO_PROCLANG:
   18353                 :             case DO_CAST:
   18354                 :             case DO_DUMMY_TYPE:
   18355                 :             case DO_TSPARSER:
   18356                 :             case DO_TSDICT:
   18357                 :             case DO_TSTEMPLATE:
   18358 EUB             :             case DO_TSCONFIG:
   18359 ECB             :             case DO_FDW:
   18360 EUB             :             case DO_FOREIGN_SERVER:
   18361 ECB             :             case DO_TRANSFORM:
   18362                 :             case DO_LARGE_OBJECT:
   18363                 :                 /* Pre-data objects: must come before the pre-data boundary */
   18364 CBC      482225 :                 addObjectDependency(preDataBound, dobj->dumpId);
   18365 GIC      482225 :                 break;
   18366            3475 :             case DO_TABLE_DATA:
   18367 ECB             :             case DO_SEQUENCE_SET:
   18368                 :             case DO_LARGE_OBJECT_DATA:
   18369                 :                 /* Data objects: must come between the boundaries */
   18370 GIC        3475 :                 addObjectDependency(dobj, preDataBound->dumpId);
   18371 CBC        3475 :                 addObjectDependency(postDataBound, dobj->dumpId);
   18372            3475 :                 break;
   18373 GBC        4629 :             case DO_INDEX:
   18374                 :             case DO_INDEX_ATTACH:
   18375                 :             case DO_STATSEXT:
   18376                 :             case DO_REFRESH_MATVIEW:
   18377                 :             case DO_TRIGGER:
   18378                 :             case DO_EVENT_TRIGGER:
   18379 ECB             :             case DO_DEFAULT_ACL:
   18380                 :             case DO_POLICY:
   18381                 :             case DO_PUBLICATION:
   18382                 :             case DO_PUBLICATION_REL:
   18383 EUB             :             case DO_PUBLICATION_TABLE_IN_SCHEMA:
   18384                 :             case DO_SUBSCRIPTION:
   18385                 :                 /* Post-data objects: must come after the post-data boundary */
   18386 GIC        4629 :                 addObjectDependency(dobj, postDataBound->dumpId);
   18387            4629 :                 break;
   18388 CBC       17749 :             case DO_RULE:
   18389                 :                 /* Rules are post-data, but only if dumped separately */
   18390           17749 :                 if (((RuleInfo *) dobj)->separate)
   18391 GIC         431 :                     addObjectDependency(dobj, postDataBound->dumpId);
   18392           17749 :                 break;
   18393            1706 :             case DO_CONSTRAINT:
   18394 ECB             :             case DO_FK_CONSTRAINT:
   18395                 :                 /* Constraints are post-data, but only if dumped separately */
   18396 GIC        1706 :                 if (((ConstraintInfo *) dobj)->separate)
   18397 CBC        1080 :                     addObjectDependency(dobj, postDataBound->dumpId);
   18398 GIC        1706 :                 break;
   18399             118 :             case DO_PRE_DATA_BOUNDARY:
   18400 ECB             :                 /* nothing to do */
   18401 CBC         118 :                 break;
   18402 GBC         118 :             case DO_POST_DATA_BOUNDARY:
   18403                 :                 /* must come after the pre-data boundary */
   18404 CBC         118 :                 addObjectDependency(dobj, preDataBound->dumpId);
   18405 GIC         118 :                 break;
   18406 ECB             :         }
   18407                 :     }
   18408 GIC         118 : }
   18409 ECB             : 
   18410 EUB             : 
   18411                 : /*
   18412                 :  * BuildArchiveDependencies - create dependency data for archive TOC entries
   18413                 :  *
   18414                 :  * The raw dependency data obtained by getDependencies() is not terribly
   18415 ECB             :  * useful in an archive dump, because in many cases there are dependency
   18416                 :  * chains linking through objects that don't appear explicitly in the dump.
   18417                 :  * For example, a view will depend on its _RETURN rule while the _RETURN rule
   18418                 :  * will depend on other objects --- but the rule will not appear as a separate
   18419                 :  * object in the dump.  We need to adjust the view's dependencies to include
   18420                 :  * whatever the rule depends on that is included in the dump.
   18421                 :  *
   18422                 :  * Just to make things more complicated, there are also "special" dependencies
   18423                 :  * such as the dependency of a TABLE DATA item on its TABLE, which we must
   18424                 :  * not rearrange because pg_restore knows that TABLE DATA only depends on
   18425                 :  * its table.  In these cases we must leave the dependencies strictly as-is
   18426                 :  * even if they refer to not-to-be-dumped objects.
   18427                 :  *
   18428                 :  * To handle this, the convention is that "special" dependencies are created
   18429                 :  * during ArchiveEntry calls, and an archive TOC item that has any such
   18430                 :  * entries will not be touched here.  Otherwise, we recursively search the
   18431                 :  * DumpableObject data structures to build the correct dependencies for each
   18432                 :  * archive TOC item.
   18433                 :  */
   18434                 : static void
   18435 GIC          25 : BuildArchiveDependencies(Archive *fout)
   18436                 : {
   18437              25 :     ArchiveHandle *AH = (ArchiveHandle *) fout;
   18438                 :     TocEntry   *te;
   18439                 : 
   18440 ECB             :     /* Scan all TOC entries in the archive */
   18441 CBC        4956 :     for (te = AH->toc->next; te != AH->toc; te = te->next)
   18442                 :     {
   18443 ECB             :         DumpableObject *dobj;
   18444                 :         DumpId     *dependencies;
   18445                 :         int         nDeps;
   18446                 :         int         allocDeps;
   18447                 : 
   18448                 :         /* No need to process entries that will not be dumped */
   18449 GIC        4931 :         if (te->reqs == 0)
   18450            1576 :             continue;
   18451                 :         /* Ignore entries that already have "special" dependencies */
   18452            4929 :         if (te->nDeps > 0)
   18453            1305 :             continue;
   18454 EUB             :         /* Otherwise, look up the item's original DumpableObject, if any */
   18455 GBC        3624 :         dobj = findObjectByDumpId(te->dumpId);
   18456            3624 :         if (dobj == NULL)
   18457             125 :             continue;
   18458                 :         /* No work if it has no dependencies */
   18459            3499 :         if (dobj->nDeps <= 0)
   18460             144 :             continue;
   18461 EUB             :         /* Set up work array */
   18462 GBC        3355 :         allocDeps = 64;
   18463            3355 :         dependencies = (DumpId *) pg_malloc(allocDeps * sizeof(DumpId));
   18464 GIC        3355 :         nDeps = 0;
   18465                 :         /* Recursively find all dumpable dependencies */
   18466            3355 :         findDumpableDependencies(AH, dobj,
   18467                 :                                  &dependencies, &nDeps, &allocDeps);
   18468                 :         /* And save 'em ... */
   18469 GBC        3355 :         if (nDeps > 0)
   18470 EUB             :         {
   18471 GIC        2586 :             dependencies = (DumpId *) pg_realloc(dependencies,
   18472 ECB             :                                                  nDeps * sizeof(DumpId));
   18473 CBC        2586 :             te->dependencies = dependencies;
   18474 GIC        2586 :             te->nDeps = nDeps;
   18475                 :         }
   18476                 :         else
   18477             769 :             free(dependencies);
   18478                 :     }
   18479              25 : }
   18480 ECB             : 
   18481                 : /* Recursive search subroutine for BuildArchiveDependencies */
   18482                 : static void
   18483 GIC        8271 : findDumpableDependencies(ArchiveHandle *AH, const DumpableObject *dobj,
   18484                 :                          DumpId **dependencies, int *nDeps, int *allocDeps)
   18485                 : {
   18486                 :     int         i;
   18487                 : 
   18488                 :     /*
   18489                 :      * Ignore section boundary objects: if we search through them, we'll
   18490                 :      * report lots of bogus dependencies.
   18491                 :      */
   18492            8271 :     if (dobj->objType == DO_PRE_DATA_BOUNDARY ||
   18493            8261 :         dobj->objType == DO_POST_DATA_BOUNDARY)
   18494 CBC        1525 :         return;
   18495                 : 
   18496           17284 :     for (i = 0; i < dobj->nDeps; i++)
   18497                 :     {
   18498 GIC       10538 :         DumpId      depid = dobj->dependencies[i];
   18499                 : 
   18500           10538 :         if (TocIDRequired(AH, depid) != 0)
   18501                 :         {
   18502                 :             /* Object will be dumped, so just reference it as a dependency */
   18503            5622 :             if (*nDeps >= *allocDeps)
   18504                 :             {
   18505 UIC           0 :                 *allocDeps *= 2;
   18506 LBC           0 :                 *dependencies = (DumpId *) pg_realloc(*dependencies,
   18507 UIC           0 :                                                       *allocDeps * sizeof(DumpId));
   18508                 :             }
   18509 GIC        5622 :             (*dependencies)[*nDeps] = depid;
   18510            5622 :             (*nDeps)++;
   18511                 :         }
   18512                 :         else
   18513                 :         {
   18514                 :             /*
   18515                 :              * Object will not be dumped, so recursively consider its deps. We
   18516                 :              * rely on the assumption that sortDumpableObjects already broke
   18517                 :              * any dependency loops, else we might recurse infinitely.
   18518                 :              */
   18519            4916 :             DumpableObject *otherdobj = findObjectByDumpId(depid);
   18520                 : 
   18521 CBC        4916 :             if (otherdobj)
   18522 GIC        4916 :                 findDumpableDependencies(AH, otherdobj,
   18523                 :                                          dependencies, nDeps, allocDeps);
   18524                 :         }
   18525                 :     }
   18526                 : }
   18527                 : 
   18528                 : 
   18529 ECB             : /*
   18530                 :  * getFormattedTypeName - retrieve a nicely-formatted type name for the
   18531                 :  * given type OID.
   18532                 :  *
   18533                 :  * This does not guarantee to schema-qualify the output, so it should not
   18534                 :  * be used to create the target object name for CREATE or ALTER commands.
   18535                 :  *
   18536                 :  * Note that the result is cached and must not be freed by the caller.
   18537                 :  */
   18538                 : static const char *
   18539 CBC        2294 : getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts)
   18540                 : {
   18541 ECB             :     TypeInfo   *typeInfo;
   18542                 :     char       *result;
   18543                 :     PQExpBuffer query;
   18544                 :     PGresult   *res;
   18545                 : 
   18546 CBC        2294 :     if (oid == 0)
   18547 ECB             :     {
   18548 UIC           0 :         if ((opts & zeroAsStar) != 0)
   18549               0 :             return "*";
   18550               0 :         else if ((opts & zeroAsNone) != 0)
   18551               0 :             return "NONE";
   18552                 :     }
   18553                 : 
   18554 ECB             :     /* see if we have the result cached in the type's TypeInfo record */
   18555 GIC        2294 :     typeInfo = findTypeByOid(oid);
   18556 CBC        2294 :     if (typeInfo && typeInfo->ftypname)
   18557 GIC        1818 :         return typeInfo->ftypname;
   18558                 : 
   18559             476 :     query = createPQExpBuffer();
   18560             476 :     appendPQExpBuffer(query, "SELECT pg_catalog.format_type('%u'::pg_catalog.oid, NULL)",
   18561                 :                       oid);
   18562 ECB             : 
   18563 CBC         476 :     res = ExecuteSqlQueryForSingleRow(fout, query->data);
   18564 ECB             : 
   18565                 :     /* result of format_type is already quoted */
   18566 CBC         476 :     result = pg_strdup(PQgetvalue(res, 0, 0));
   18567                 : 
   18568             476 :     PQclear(res);
   18569             476 :     destroyPQExpBuffer(query);
   18570 ECB             : 
   18571                 :     /*
   18572                 :      * Cache the result for re-use in later requests, if possible.  If we
   18573                 :      * don't have a TypeInfo for the type, the string will be leaked once the
   18574                 :      * caller is done with it ... but that case really should not happen, so
   18575                 :      * leaking if it does seems acceptable.
   18576                 :      */
   18577 CBC         476 :     if (typeInfo)
   18578 GIC         476 :         typeInfo->ftypname = result;
   18579                 : 
   18580             476 :     return result;
   18581                 : }
   18582                 : 
   18583 ECB             : /*
   18584                 :  * Return a column list clause for the given relation.
   18585                 :  *
   18586                 :  * Special case: if there are no undropped columns in the relation, return
   18587                 :  * "", not an invalid "()" column list.
   18588                 :  */
   18589                 : static const char *
   18590 GIC        6020 : fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer)
   18591                 : {
   18592            6020 :     int         numatts = ti->numatts;
   18593            6020 :     char      **attnames = ti->attnames;
   18594 CBC        6020 :     bool       *attisdropped = ti->attisdropped;
   18595 GIC        6020 :     char       *attgenerated = ti->attgenerated;
   18596                 :     bool        needComma;
   18597                 :     int         i;
   18598                 : 
   18599            6020 :     appendPQExpBufferChar(buffer, '(');
   18600            6020 :     needComma = false;
   18601           30584 :     for (i = 0; i < numatts; i++)
   18602                 :     {
   18603 CBC       24564 :         if (attisdropped[i])
   18604             564 :             continue;
   18605 GIC       24000 :         if (attgenerated[i])
   18606             620 :             continue;
   18607           23380 :         if (needComma)
   18608           17594 :             appendPQExpBufferStr(buffer, ", ");
   18609           23380 :         appendPQExpBufferStr(buffer, fmtId(attnames[i]));
   18610           23380 :         needComma = true;
   18611                 :     }
   18612                 : 
   18613 CBC        6020 :     if (!needComma)
   18614             234 :         return "";                /* no undropped columns */
   18615 ECB             : 
   18616 CBC        5786 :     appendPQExpBufferChar(buffer, ')');
   18617 GIC        5786 :     return buffer->data;
   18618                 : }
   18619 ECB             : 
   18620                 : /*
   18621                 :  * Check if a reloptions array is nonempty.
   18622                 :  */
   18623                 : static bool
   18624 CBC       10120 : nonemptyReloptions(const char *reloptions)
   18625 ECB             : {
   18626                 :     /* Don't want to print it if it's just "{}" */
   18627 GIC       10120 :     return (reloptions != NULL && strlen(reloptions) > 2);
   18628                 : }
   18629                 : 
   18630                 : /*
   18631                 :  * Format a reloptions array and append it to the given buffer.
   18632                 :  *
   18633 ECB             :  * "prefix" is prepended to the option names; typically it's "" or "toast.".
   18634                 :  */
   18635                 : static void
   18636 GIC         207 : appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
   18637 ECB             :                         const char *prefix, Archive *fout)
   18638                 : {
   18639                 :     bool        res;
   18640                 : 
   18641 CBC         207 :     res = appendReloptionsArray(buffer, reloptions, prefix, fout->encoding,
   18642             207 :                                 fout->std_strings);
   18643 GIC         207 :     if (!res)
   18644 LBC           0 :         pg_log_warning("could not parse %s array", "reloptions");
   18645 CBC         207 : }
        

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