LCOV - differential code coverage report
Current view: top level - src/bin/pg_upgrade - info.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: 64.1 % 245 157 7 8 39 34 4 77 28 48 48 88 2 13
Current Date: 2023-04-08 17:13:01 Functions: 72.7 % 11 8 3 7 1 3 8
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 92.0 % 25 23 2 23
Legend: Lines: hit not hit (180,240] days: 100.0 % 2 2 1 1
(240..) days: 60.6 % 218 132 5 8 39 34 4 76 4 48 34 78
Function coverage date bins:
[..60] days: 100.0 % 1 1 1
(240..) days: 36.8 % 19 7 3 7 1 8

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*
                                  2                 :  *  info.c
                                  3                 :  *
                                  4                 :  *  information support functions
                                  5                 :  *
                                  6                 :  *  Copyright (c) 2010-2023, PostgreSQL Global Development Group
                                  7                 :  *  src/bin/pg_upgrade/info.c
                                  8                 :  */
                                  9                 : 
                                 10                 : #include "postgres_fe.h"
                                 11                 : 
                                 12                 : #include "access/transam.h"
                                 13                 : #include "catalog/pg_class_d.h"
                                 14                 : #include "pg_upgrade.h"
                                 15                 : 
                                 16                 : static void create_rel_filename_map(const char *old_data, const char *new_data,
                                 17                 :                                     const DbInfo *old_db, const DbInfo *new_db,
                                 18                 :                                     const RelInfo *old_rel, const RelInfo *new_rel,
                                 19                 :                                     FileNameMap *map);
                                 20                 : static void report_unmatched_relation(const RelInfo *rel, const DbInfo *db,
                                 21                 :                                       bool is_new_db);
                                 22                 : static void free_db_and_rel_infos(DbInfoArr *db_arr);
                                 23                 : static void get_template0_info(ClusterInfo *cluster);
                                 24                 : static void get_db_infos(ClusterInfo *cluster);
                                 25                 : static void get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo);
                                 26                 : static void free_rel_infos(RelInfoArr *rel_arr);
                                 27                 : static void print_db_infos(DbInfoArr *db_arr);
                                 28                 : static void print_rel_infos(RelInfoArr *rel_arr);
                                 29                 : 
                                 30                 : 
                                 31                 : /*
                                 32                 :  * gen_db_file_maps()
                                 33                 :  *
                                 34                 :  * generates a database mapping from "old_db" to "new_db".
                                 35                 :  *
                                 36                 :  * Returns a malloc'ed array of mappings.  The length of the array
                                 37                 :  * is returned into *nmaps.
                                 38                 :  */
                                 39                 : FileNameMap *
 4555 bruce                      40 GIC           6 : gen_db_file_maps(DbInfo *old_db, DbInfo *new_db,
 2529 tgl                        41 ECB             :                  int *nmaps,
                                 42                 :                  const char *old_pgdata, const char *new_pgdata)
                                 43                 : {
                                 44                 :     FileNameMap *maps;
                                 45                 :     int         old_relnum,
                                 46                 :                 new_relnum;
 4715 bruce                      47 GIC           6 :     int         num_maps = 0;
 2529 tgl                        48 CBC           6 :     bool        all_matched = true;
 4715 bruce                      49 ECB             : 
                                 50                 :     /* There will certainly not be more mappings than there are old rels */
 4555 bruce                      51 GIC           6 :     maps = (FileNameMap *) pg_malloc(sizeof(FileNameMap) *
 4477 bruce                      52 CBC           6 :                                      old_db->rel_arr.nrels);
 4715 bruce                      53 ECB             : 
                                 54                 :     /*
                                 55                 :      * Each of the RelInfo arrays should be sorted by OID.  Scan through them
                                 56                 :      * and match them up.  If we fail to match everything, we'll abort, but
                                 57                 :      * first print as much info as we can about mismatches.
                                 58                 :      */
 2529 tgl                        59 GIC           6 :     old_relnum = new_relnum = 0;
 2529 tgl                        60 CBC        1264 :     while (old_relnum < old_db->rel_arr.nrels ||
                                 61               6 :            new_relnum < new_db->rel_arr.nrels)
 4715 bruce                      62 ECB             :     {
 2529 tgl                        63 GIC        2516 :         RelInfo    *old_rel = (old_relnum < old_db->rel_arr.nrels) ?
 2529 tgl                        64 CBC        1258 :         &old_db->rel_arr.rels[old_relnum] : NULL;
                                 65            2516 :         RelInfo    *new_rel = (new_relnum < new_db->rel_arr.nrels) ?
                                 66            1258 :         &new_db->rel_arr.rels[new_relnum] : NULL;
 3198 bruce                      67 ECB             : 
                                 68                 :         /* handle running off one array before the other */
 2529 tgl                        69 GIC        1258 :         if (!new_rel)
 3198 bruce                      70 ECB             :         {
                                 71                 :             /*
                                 72                 :              * old_rel is unmatched.  This should never happen, because we
                                 73                 :              * force new rels to have TOAST tables if the old one did.
                                 74                 :              */
 2529 tgl                        75 UIC           0 :             report_unmatched_relation(old_rel, old_db, false);
 2529 tgl                        76 UBC           0 :             all_matched = false;
                                 77               0 :             old_relnum++;
                                 78               0 :             continue;
 2529 tgl                        79 EUB             :         }
 2529 tgl                        80 GIC        1258 :         if (!old_rel)
 2529 tgl                        81 ECB             :         {
                                 82                 :             /*
                                 83                 :              * new_rel is unmatched.  This shouldn't really happen either, but
                                 84                 :              * if it's a TOAST table, we can ignore it and continue
                                 85                 :              * processing, assuming that the new server made a TOAST table
                                 86                 :              * that wasn't needed.
                                 87                 :              */
 2529 tgl                        88 UIC           0 :             if (strcmp(new_rel->nspname, "pg_toast") != 0)
 2529 tgl                        89 EUB             :             {
 2529 tgl                        90 UIC           0 :                 report_unmatched_relation(new_rel, new_db, true);
 2529 tgl                        91 UBC           0 :                 all_matched = false;
 2529 tgl                        92 EUB             :             }
 2529 tgl                        93 UIC           0 :             new_relnum++;
 2529 tgl                        94 UBC           0 :             continue;
 3198 bruce                      95 EUB             :         }
                                 96                 : 
                                 97                 :         /* check for mismatched OID */
 2529 tgl                        98 GIC        1258 :         if (old_rel->reloid < new_rel->reloid)
 3198 bruce                      99 ECB             :         {
                                100                 :             /* old_rel is unmatched, see comment above */
 2529 tgl                       101 UIC           0 :             report_unmatched_relation(old_rel, old_db, false);
 2529 tgl                       102 UBC           0 :             all_matched = false;
                                103               0 :             old_relnum++;
                                104               0 :             continue;
 2529 tgl                       105 EUB             :         }
 2529 tgl                       106 GIC        1258 :         else if (old_rel->reloid > new_rel->reloid)
 2529 tgl                       107 ECB             :         {
                                108                 :             /* new_rel is unmatched, see comment above */
 2529 tgl                       109 UIC           0 :             if (strcmp(new_rel->nspname, "pg_toast") != 0)
 2529 tgl                       110 EUB             :             {
 2529 tgl                       111 UIC           0 :                 report_unmatched_relation(new_rel, new_db, true);
 2529 tgl                       112 UBC           0 :                 all_matched = false;
 2529 tgl                       113 EUB             :             }
 2529 tgl                       114 UIC           0 :             new_relnum++;
 2529 tgl                       115 UBC           0 :             continue;
 3198 bruce                     116 EUB             :         }
                                117                 : 
                                118                 :         /*
                                119                 :          * Verify that rels of same OID have same name.  The namespace name
                                120                 :          * should always match, but the relname might not match for TOAST
                                121                 :          * tables (and, therefore, their indexes).
                                122                 :          */
 4417 bruce                     123 GIC        1258 :         if (strcmp(old_rel->nspname, new_rel->nspname) != 0 ||
  481 tgl                       124 CBC        1258 :             strcmp(old_rel->relname, new_rel->relname) != 0)
 2529 tgl                       125 ECB             :         {
 2529 tgl                       126 UIC           0 :             pg_log(PG_WARNING, "Relation names for OID %u in database \"%s\" do not match: "
                                127                 :                    "old name \"%s.%s\", new name \"%s.%s\"",
                                128                 :                    old_rel->reloid, old_db->db_name,
                                129                 :                    old_rel->nspname, old_rel->relname,
                                130                 :                    new_rel->nspname, new_rel->relname);
                                131               0 :             all_matched = false;
 2529 tgl                       132 UBC           0 :             old_relnum++;
                                133               0 :             new_relnum++;
                                134               0 :             continue;
 2529 tgl                       135 EUB             :         }
                                136                 : 
                                137                 :         /* OK, create a mapping entry */
 4478 bruce                     138 GIC        1258 :         create_rel_filename_map(old_pgdata, new_pgdata, old_db, new_db,
 4382 bruce                     139 CBC        1258 :                                 old_rel, new_rel, maps + num_maps);
 4715                           140            1258 :         num_maps++;
 3198                           141            1258 :         old_relnum++;
 2529 tgl                       142            1258 :         new_relnum++;
 4715 bruce                     143 ECB             :     }
                                144                 : 
 2529 tgl                       145 GIC           6 :     if (!all_matched)
  271 tgl                       146 UNC           0 :         pg_fatal("Failed to match up old and new tables in database \"%s\"",
 3260 bruce                     147 EUB             :                  old_db->db_name);
                                148                 : 
 4715 bruce                     149 GIC           6 :     *nmaps = num_maps;
 4715 bruce                     150 CBC           6 :     return maps;
 4715 bruce                     151 ECB             : }
                                152                 : 
                                153                 : 
                                154                 : /*
                                155                 :  * create_rel_filename_map()
                                156                 :  *
                                157                 :  * fills a file node map structure and returns it in "map".
                                158                 :  */
                                159                 : static void
 4478 bruce                     160 GIC        1258 : create_rel_filename_map(const char *old_data, const char *new_data,
 4382 bruce                     161 ECB             :                         const DbInfo *old_db, const DbInfo *new_db,
                                162                 :                         const RelInfo *old_rel, const RelInfo *new_rel,
                                163                 :                         FileNameMap *map)
                                164                 : {
                                165                 :     /* In case old/new tablespaces don't match, do them separately. */
 4478 bruce                     166 GIC        1258 :     if (strlen(old_rel->tablespace) == 0)
 4715 bruce                     167 ECB             :     {
                                168                 :         /*
                                169                 :          * relation belongs to the default tablespace, hence relfiles should
                                170                 :          * exist in the data directories.
                                171                 :          */
 3343 bruce                     172 GIC        1258 :         map->old_tablespace = old_data;
 3343 bruce                     173 CBC        1258 :         map->old_tablespace_suffix = "/base";
 4715 bruce                     174 ECB             :     }
                                175                 :     else
                                176                 :     {
                                177                 :         /* relation belongs to a tablespace, so use the tablespace location */
 3343 bruce                     178 UIC           0 :         map->old_tablespace = old_rel->tablespace;
 3343 bruce                     179 UBC           0 :         map->old_tablespace_suffix = old_cluster.tablespace_suffix;
 2767 bruce                     180 EUB             :     }
                                181                 : 
                                182                 :     /* Do the same for new tablespaces */
 2767 bruce                     183 GIC        1258 :     if (strlen(new_rel->tablespace) == 0)
 2767 bruce                     184 ECB             :     {
 2767 bruce                     185 GIC        1258 :         map->new_tablespace = new_data;
 2767 bruce                     186 CBC        1258 :         map->new_tablespace_suffix = "/base";
 2767 bruce                     187 ECB             :     }
                                188                 :     else
                                189                 :     {
 2767 bruce                     190 UIC           0 :         map->new_tablespace = new_rel->tablespace;
 3343 bruce                     191 UBC           0 :         map->new_tablespace_suffix = new_cluster.tablespace_suffix;
 4715 bruce                     192 EUB             :     }
                                193                 : 
                                194                 :     /* DB oid and relfilenumbers are preserved between old and new cluster */
  440 rhaas                     195 GIC        1258 :     map->db_oid = old_db->db_oid;
  277 rhaas                     196 GNC        1258 :     map->relfilenumber = old_rel->relfilenumber;
 4477 bruce                     197 ECB             : 
                                198                 :     /* used only for logging and error reporting, old/new are identical */
 3762 bruce                     199 GIC        1258 :     map->nspname = old_rel->nspname;
 3762 bruce                     200 CBC        1258 :     map->relname = old_rel->relname;
 4715                           201            1258 : }
 4715 bruce                     202 ECB             : 
                                203                 : 
                                204                 : /*
                                205                 :  * Complain about a relation we couldn't match to the other database,
                                206                 :  * identifying it as best we can.
                                207                 :  */
                                208                 : static void
 2529 tgl                       209 UIC           0 : report_unmatched_relation(const RelInfo *rel, const DbInfo *db, bool is_new_db)
 2529 tgl                       210 EUB             : {
 2529 tgl                       211 UIC           0 :     Oid         reloid = rel->reloid;    /* we might change rel below */
 2529 tgl                       212 EUB             :     char        reldesc[1000];
                                213                 :     int         i;
                                214                 : 
 2529 tgl                       215 UIC           0 :     snprintf(reldesc, sizeof(reldesc), "\"%s.%s\"",
 2529 tgl                       216 UBC           0 :              rel->nspname, rel->relname);
                                217               0 :     if (rel->indtable)
 2529 tgl                       218 EUB             :     {
 2529 tgl                       219 UIC           0 :         for (i = 0; i < db->rel_arr.nrels; i++)
 2529 tgl                       220 EUB             :         {
 2529 tgl                       221 UIC           0 :             const RelInfo *hrel = &db->rel_arr.rels[i];
 2529 tgl                       222 EUB             : 
 2529 tgl                       223 UIC           0 :             if (hrel->reloid == rel->indtable)
 2529 tgl                       224 EUB             :             {
 2529 tgl                       225 UIC           0 :                 snprintf(reldesc + strlen(reldesc),
 2529 tgl                       226 UBC           0 :                          sizeof(reldesc) - strlen(reldesc),
 2368 peter_e                   227               0 :                          _(" which is an index on \"%s.%s\""),
 2529 tgl                       228               0 :                          hrel->nspname, hrel->relname);
 2529 tgl                       229 EUB             :                 /* Shift attention to index's table for toast check */
 2529 tgl                       230 UIC           0 :                 rel = hrel;
 2529 tgl                       231 UBC           0 :                 break;
 2529 tgl                       232 EUB             :             }
                                233                 :         }
 2529 tgl                       234 UIC           0 :         if (i >= db->rel_arr.nrels)
 2529 tgl                       235 UBC           0 :             snprintf(reldesc + strlen(reldesc),
                                236               0 :                      sizeof(reldesc) - strlen(reldesc),
 2368 peter_e                   237               0 :                      _(" which is an index on OID %u"), rel->indtable);
 2529 tgl                       238 EUB             :     }
 2529 tgl                       239 UIC           0 :     if (rel->toastheap)
 2529 tgl                       240 EUB             :     {
 2529 tgl                       241 UIC           0 :         for (i = 0; i < db->rel_arr.nrels; i++)
 2529 tgl                       242 EUB             :         {
 2529 tgl                       243 UIC           0 :             const RelInfo *brel = &db->rel_arr.rels[i];
 2529 tgl                       244 EUB             : 
 2529 tgl                       245 UIC           0 :             if (brel->reloid == rel->toastheap)
 2529 tgl                       246 EUB             :             {
 2529 tgl                       247 UIC           0 :                 snprintf(reldesc + strlen(reldesc),
 2529 tgl                       248 UBC           0 :                          sizeof(reldesc) - strlen(reldesc),
 2368 peter_e                   249               0 :                          _(" which is the TOAST table for \"%s.%s\""),
 2529 tgl                       250               0 :                          brel->nspname, brel->relname);
                                251               0 :                 break;
 2529 tgl                       252 EUB             :             }
                                253                 :         }
 2529 tgl                       254 UIC           0 :         if (i >= db->rel_arr.nrels)
 2529 tgl                       255 UBC           0 :             snprintf(reldesc + strlen(reldesc),
                                256               0 :                      sizeof(reldesc) - strlen(reldesc),
 2118                           257               0 :                      _(" which is the TOAST table for OID %u"), rel->toastheap);
 2529 tgl                       258 EUB             :     }
                                259                 : 
 2529 tgl                       260 UIC           0 :     if (is_new_db)
  271 tgl                       261 UNC           0 :         pg_log(PG_WARNING, "No match found in old cluster for new relation with OID %u in database \"%s\": %s",
 2529 tgl                       262 UBC           0 :                reloid, db->db_name, reldesc);
 2529 tgl                       263 EUB             :     else
  271 tgl                       264 UNC           0 :         pg_log(PG_WARNING, "No match found in new cluster for old relation with OID %u in database \"%s\": %s",
 2529 tgl                       265 UBC           0 :                reloid, db->db_name, reldesc);
                                266               0 : }
 2529 tgl                       267 EUB             : 
                                268                 : /*
                                269                 :  * get_db_and_rel_infos()
                                270                 :  *
                                271                 :  * higher level routine to generate dbinfos for the database running
                                272                 :  * on the given "port". Assumes that server is already running.
                                273                 :  */
                                274                 : void
 4472 bruce                     275 GIC           5 : get_db_and_rel_infos(ClusterInfo *cluster)
 4472 bruce                     276 ECB             : {
                                277                 :     int         dbnum;
                                278                 : 
 4436 bruce                     279 GIC           5 :     if (cluster->dbarr.dbs != NULL)
 4436 bruce                     280 CBC           1 :         free_db_and_rel_infos(&cluster->dbarr);
 4436 bruce                     281 ECB             : 
   31 jdavis                    282 GNC           5 :     get_template0_info(cluster);
 4472 bruce                     283 GIC           5 :     get_db_infos(cluster);
 4472 bruce                     284 ECB             : 
 4472 bruce                     285 CBC          27 :     for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
 4472 bruce                     286 GIC          22 :         get_rel_infos(cluster, &cluster->dbarr.dbs[dbnum]);
 4472 bruce                     287 ECB             : 
 2095 alvherre                  288 CBC           5 :     if (cluster == &old_cluster)
  271 tgl                       289 GNC           2 :         pg_log(PG_VERBOSE, "\nsource databases:");
 2095 alvherre                  290 ECB             :     else
  271 tgl                       291 GNC           3 :         pg_log(PG_VERBOSE, "\ntarget databases:");
                                292                 : 
 4045 bruce                     293 CBC           5 :     if (log_opts.verbose)
 4472 bruce                     294 UIC           0 :         print_db_infos(&cluster->dbarr);
 4472 bruce                     295 CBC           5 : }
 4472 bruce                     296 EUB             : 
 4472 bruce                     297 ECB             : 
                                298                 : /*
                                299                 :  * Get information about template0, which will be copied from the old cluster
                                300                 :  * to the new cluster.
                                301                 :  */
                                302                 : static void
   31 jdavis                    303 GNC           5 : get_template0_info(ClusterInfo *cluster)
                                304                 : {
                                305               5 :     PGconn          *conn = connectToServer(cluster, "template1");
                                306                 :     DbLocaleInfo    *locale;
                                307                 :     PGresult        *dbres;
                                308                 :     int              i_datencoding;
                                309                 :     int              i_datlocprovider;
                                310                 :     int              i_datcollate;
                                311                 :     int              i_datctype;
                                312                 :     int              i_daticulocale;
                                313                 : 
                                314               5 :     if (GET_MAJOR_VERSION(cluster->major_version) >= 1500)
                                315               5 :         dbres = executeQueryOrDie(conn,
                                316                 :                                   "SELECT encoding, datlocprovider, "
                                317                 :                                   "       datcollate, datctype, daticulocale "
                                318                 :                                   "FROM    pg_catalog.pg_database "
                                319                 :                                   "WHERE datname='template0'");
                                320                 :     else
   31 jdavis                    321 UNC           0 :         dbres = executeQueryOrDie(conn,
                                322                 :                                   "SELECT encoding, 'c' AS datlocprovider, "
                                323                 :                                   "       datcollate, datctype, NULL AS daticulocale "
                                324                 :                                   "FROM    pg_catalog.pg_database "
                                325                 :                                   "WHERE datname='template0'");
                                326                 : 
                                327                 : 
   31 jdavis                    328 GNC           5 :     if (PQntuples(dbres) != 1)
   31 jdavis                    329 UNC           0 :         pg_fatal("template0 not found");
                                330                 : 
   31 jdavis                    331 GNC           5 :     locale = pg_malloc(sizeof(DbLocaleInfo));
                                332                 : 
                                333               5 :     i_datencoding = PQfnumber(dbres, "encoding");
                                334               5 :     i_datlocprovider = PQfnumber(dbres, "datlocprovider");
                                335               5 :     i_datcollate = PQfnumber(dbres, "datcollate");
                                336               5 :     i_datctype = PQfnumber(dbres, "datctype");
                                337               5 :     i_daticulocale = PQfnumber(dbres, "daticulocale");
                                338                 : 
                                339               5 :     locale->db_encoding = atoi(PQgetvalue(dbres, 0, i_datencoding));
                                340               5 :     locale->db_collprovider = PQgetvalue(dbres, 0, i_datlocprovider)[0];
                                341               5 :     locale->db_collate = pg_strdup(PQgetvalue(dbres, 0, i_datcollate));
                                342               5 :     locale->db_ctype = pg_strdup(PQgetvalue(dbres, 0, i_datctype));
                                343               5 :     if (PQgetisnull(dbres, 0, i_daticulocale))
                                344               2 :         locale->db_iculocale = NULL;
                                345                 :     else
                                346               3 :         locale->db_iculocale = pg_strdup(PQgetvalue(dbres, 0, i_daticulocale));
                                347                 : 
                                348               5 :     cluster->template0 = locale;
                                349                 : 
                                350               5 :     PQclear(dbres);
                                351               5 :     PQfinish(conn);
                                352               5 : }
                                353                 : 
                                354                 : 
                                355                 : /*
                                356                 :  * get_db_infos()
                                357                 :  *
                                358                 :  * Scans pg_database system catalog and populates all user
                                359                 :  * databases.
                                360                 :  */
                                361                 : static void
 4481 bruce                     362 CBC           5 : get_db_infos(ClusterInfo *cluster)
                                363                 : {
                                364               5 :     PGconn     *conn = connectToServer(cluster, "template1");
                                365                 :     PGresult   *res;
                                366                 :     int         ntups;
                                367                 :     int         tupnum;
                                368                 :     DbInfo     *dbinfos;
                                369                 :     int         i_datname,
                                370                 :                 i_oid,
                                371                 :                 i_spclocation;
                                372                 :     char        query[QUERY_ALLOC];
                                373                 : 
 4141 magnus                    374 GIC           5 :     snprintf(query, sizeof(query),
  388 peter                     375 EUB             :              "SELECT d.oid, d.datname, d.encoding, d.datcollate, d.datctype, ");
  230 peter                     376 GIC           5 :     if (GET_MAJOR_VERSION(cluster->major_version) < 1500)
  388 peter                     377 UIC           0 :         snprintf(query + strlen(query), sizeof(query) - strlen(query),
                                378                 :                  "'c' AS datlocprovider, NULL AS daticulocale, ");
                                379                 :     else
  388 peter                     380 GIC           5 :         snprintf(query + strlen(query), sizeof(query) - strlen(query),
                                381                 :                  "datlocprovider, daticulocale, ");
  388 peter                     382 CBC           5 :     snprintf(query + strlen(query), sizeof(query) - strlen(query),
  481 tgl                       383 EUB             :              "pg_catalog.pg_tablespace_location(t.oid) AS spclocation "
                                384                 :              "FROM pg_catalog.pg_database d "
 3955 bruce                     385 ECB             :              " LEFT OUTER JOIN pg_catalog.pg_tablespace t "
                                386                 :              " ON d.dattablespace = t.oid "
                                387                 :              "WHERE d.datallowconn = true "
  440 rhaas                     388                 :              "ORDER BY 1");
 4141 magnus                    389                 : 
 4141 magnus                    390 CBC           5 :     res = executeQueryOrDie(conn, "%s", query);
 4660 bruce                     391 ECB             : 
 4715 bruce                     392 GIC           5 :     i_oid = PQfnumber(res, "oid");
 4418 bruce                     393 CBC           5 :     i_datname = PQfnumber(res, "datname");
 4715 bruce                     394 GIC           5 :     i_spclocation = PQfnumber(res, "spclocation");
 4715 bruce                     395 ECB             : 
 4715 bruce                     396 GIC           5 :     ntups = PQntuples(res);
 4555 bruce                     397 CBC           5 :     dbinfos = (DbInfo *) pg_malloc(sizeof(DbInfo) * ntups);
                                398                 : 
 4715                           399              27 :     for (tupnum = 0; tupnum < ntups; tupnum++)
 4715 bruce                     400 ECB             :     {
 4576 bruce                     401 CBC          22 :         dbinfos[tupnum].db_oid = atooid(PQgetvalue(res, tupnum, i_oid));
 3762 bruce                     402 GIC          22 :         dbinfos[tupnum].db_name = pg_strdup(PQgetvalue(res, tupnum, i_datname));
 3343 bruce                     403 CBC          22 :         snprintf(dbinfos[tupnum].db_tablespace, sizeof(dbinfos[tupnum].db_tablespace), "%s",
                                404                 :                  PQgetvalue(res, tupnum, i_spclocation));
 4715 bruce                     405 ECB             :     }
 4715 bruce                     406 GIC           5 :     PQclear(res);
                                407                 : 
                                408               5 :     PQfinish(conn);
                                409                 : 
 4481                           410               5 :     cluster->dbarr.dbs = dbinfos;
                                411               5 :     cluster->dbarr.ndbs = ntups;
 4715                           412               5 : }
                                413                 : 
                                414                 : 
 4715 bruce                     415 ECB             : /*
                                416                 :  * get_rel_infos()
                                417                 :  *
 2529 tgl                       418 EUB             :  * gets the relinfos for all the user tables and indexes of the database
                                419                 :  * referred to by "dbinfo".
                                420                 :  *
 2529 tgl                       421 ECB             :  * Note: the resulting RelInfo array is assumed to be sorted by OID.
                                422                 :  * This allows later processing to match up old and new databases efficiently.
 4715 bruce                     423                 :  */
                                424                 : static void
 4478 bruce                     425 GIC          22 : get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
                                426                 : {
 4481                           427              22 :     PGconn     *conn = connectToServer(cluster,
 4478                           428              22 :                                        dbinfo->db_name);
                                429                 :     PGresult   *res;
                                430                 :     RelInfo    *relinfos;
 4715 bruce                     431 ECB             :     int         ntups;
                                432                 :     int         relnum;
 4715 bruce                     433 CBC          22 :     int         num_rels = 0;
                                434              22 :     char       *nspname = NULL;
                                435              22 :     char       *relname = NULL;
 3343 bruce                     436 GIC          22 :     char       *tablespace = NULL;
 4382 bruce                     437 ECB             :     int         i_spclocation,
                                438                 :                 i_nspname,
                                439                 :                 i_relname,
 2529 tgl                       440                 :                 i_reloid,
                                441                 :                 i_indtable,
                                442                 :                 i_toastheap,
                                443                 :                 i_relfilenumber,
 1433 akapila                   444                 :                 i_reltablespace;
                                445                 :     char        query[QUERY_ALLOC];
 3260 bruce                     446 GIC          22 :     char       *last_namespace = NULL,
 3260 bruce                     447 CBC          22 :                *last_tablespace = NULL;
                                448                 : 
 2529 tgl                       449              22 :     query[0] = '\0';            /* initialize query string to empty */
                                450                 : 
 4715 bruce                     451 ECB             :     /*
   96 michael                   452                 :      * Create a CTE that collects OIDs of regular user tables and matviews,
                                453                 :      * but excluding toast tables and indexes.  We assume that relations with
                                454                 :      * OIDs >= FirstNormalObjectId belong to the user.  (That's probably
                                455                 :      * redundant with the namespace-name exclusions, but let's be safe.)
                                456                 :      *
                                457                 :      * pg_largeobject contains user data that does not appear in pg_dump
                                458                 :      * output, so we have to copy that system table.  It's easiest to do that
                                459                 :      * by treating it as a user table.
                                460                 :      */
 2529 tgl                       461 GIC          22 :     snprintf(query + strlen(query), sizeof(query) - strlen(query),
                                462                 :              "WITH regular_heap (reloid, indtable, toastheap) AS ( "
                                463                 :              "  SELECT c.oid, 0::oid, 0::oid "
                                464                 :              "  FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n "
                                465                 :              "         ON c.relnamespace = n.oid "
 2222 tgl                       466 ECB             :              "  WHERE relkind IN (" CppAsString2(RELKIND_RELATION) ", "
                                467                 :              CppAsString2(RELKIND_MATVIEW) ") AND "
 2529                           468                 :     /* exclude possible orphaned temp tables */
                                469                 :              "    ((n.nspname !~ '^pg_temp_' AND "
                                470                 :              "      n.nspname !~ '^pg_toast_temp_' AND "
                                471                 :              "      n.nspname NOT IN ('pg_catalog', 'information_schema', "
                                472                 :              "                        'binary_upgrade', 'pg_toast') AND "
                                473                 :              "      c.oid >= %u::pg_catalog.oid) OR "
                                474                 :              "     (n.nspname = 'pg_catalog' AND "
 1595 andres                    475                 :              "      relname IN ('pg_largeobject') ))), ",
                                476                 :              FirstNormalObjectId);
 4715 bruce                     477                 : 
                                478                 :     /*
                                479                 :      * Add a CTE that collects OIDs of toast tables belonging to the tables
                                480                 :      * selected by the regular_heap CTE.  (We have to do this separately
                                481                 :      * because the namespace-name rules above don't work for toast tables.)
                                482                 :      */
 2529 tgl                       483 GIC          22 :     snprintf(query + strlen(query), sizeof(query) - strlen(query),
                                484                 :              "  toast_heap (reloid, indtable, toastheap) AS ( "
                                485                 :              "  SELECT c.reltoastrelid, 0::oid, c.oid "
                                486                 :              "  FROM regular_heap JOIN pg_catalog.pg_class c "
 2529 tgl                       487 ECB             :              "      ON regular_heap.reloid = c.oid "
                                488                 :              "  WHERE c.reltoastrelid != 0), ");
                                489                 : 
 2878 bruce                     490                 :     /*
                                491                 :      * Add a CTE that collects OIDs of all valid indexes on the previously
                                492                 :      * selected tables.  We can ignore invalid indexes since pg_dump does.
                                493                 :      * Testing indisready is necessary in 9.2, and harmless in earlier/later
                                494                 :      * versions.
                                495                 :      */
 2529 tgl                       496 GIC          22 :     snprintf(query + strlen(query), sizeof(query) - strlen(query),
                                497                 :              "  all_index (reloid, indtable, toastheap) AS ( "
                                498                 :              "  SELECT indexrelid, indrelid, 0::oid "
                                499                 :              "  FROM pg_catalog.pg_index "
                                500                 :              "  WHERE indisvalid AND indisready "
                                501                 :              "    AND indrelid IN "
 2529 tgl                       502 ECB             :              "        (SELECT reloid FROM regular_heap "
                                503                 :              "         UNION ALL "
                                504                 :              "         SELECT reloid FROM toast_heap)) ");
                                505                 : 
                                506                 :     /*
                                507                 :      * And now we can write the query that retrieves the data we want for each
                                508                 :      * heap and index relation.  Make sure result is sorted by OID.
                                509                 :      */
 2529 tgl                       510 GIC          22 :     snprintf(query + strlen(query), sizeof(query) - strlen(query),
                                511                 :              "SELECT all_rels.*, n.nspname, c.relname, "
                                512                 :              "  c.relfilenode, c.reltablespace, "
                                513                 :              "  pg_catalog.pg_tablespace_location(t.oid) AS spclocation "
                                514                 :              "FROM (SELECT * FROM regular_heap "
                                515                 :              "      UNION ALL "
                                516                 :              "      SELECT * FROM toast_heap "
                                517                 :              "      UNION ALL "
                                518                 :              "      SELECT * FROM all_index) all_rels "
                                519                 :              "  JOIN pg_catalog.pg_class c "
                                520                 :              "      ON all_rels.reloid = c.oid "
                                521                 :              "  JOIN pg_catalog.pg_namespace n "
                                522                 :              "     ON c.relnamespace = n.oid "
                                523                 :              "  LEFT OUTER JOIN pg_catalog.pg_tablespace t "
 2529 tgl                       524 ECB             :              "     ON c.reltablespace = t.oid "
                                525                 :              "ORDER BY 1;");
                                526                 : 
 4229 peter_e                   527 GIC          22 :     res = executeQueryOrDie(conn, "%s", query);
                                528                 : 
 4715 bruce                     529              22 :     ntups = PQntuples(res);
                                530                 : 
 4555                           531              22 :     relinfos = (RelInfo *) pg_malloc(sizeof(RelInfo) * ntups);
                                532                 : 
 2529 tgl                       533              22 :     i_reloid = PQfnumber(res, "reloid");
                                534              22 :     i_indtable = PQfnumber(res, "indtable");
                                535              22 :     i_toastheap = PQfnumber(res, "toastheap");
 4715 bruce                     536              22 :     i_nspname = PQfnumber(res, "nspname");
 4715 bruce                     537 CBC          22 :     i_relname = PQfnumber(res, "relname");
  277 rhaas                     538 GNC          22 :     i_relfilenumber = PQfnumber(res, "relfilenode");
 4016 bruce                     539 GIC          22 :     i_reltablespace = PQfnumber(res, "reltablespace");
 4715                           540              22 :     i_spclocation = PQfnumber(res, "spclocation");
                                541                 : 
                                542            3804 :     for (relnum = 0; relnum < ntups; relnum++)
                                543                 :     {
                                544            3782 :         RelInfo    *curr = &relinfos[num_rels++];
                                545                 : 
 2529 tgl                       546            3782 :         curr->reloid = atooid(PQgetvalue(res, relnum, i_reloid));
                                547            3782 :         curr->indtable = atooid(PQgetvalue(res, relnum, i_indtable));
                                548            3782 :         curr->toastheap = atooid(PQgetvalue(res, relnum, i_toastheap));
                                549                 : 
 4715 bruce                     550            3782 :         nspname = PQgetvalue(res, relnum, i_nspname);
 3343 bruce                     551 CBC        3782 :         curr->nsp_alloc = false;
                                552                 : 
                                553                 :         /*
                                554                 :          * Many of the namespace and tablespace strings are identical, so we
                                555                 :          * try to reuse the allocated string pointers where possible to reduce
                                556                 :          * memory consumption.
                                557                 :          */
                                558                 :         /* Can we reuse the previous string allocation? */
 3343 bruce                     559 GIC        3782 :         if (last_namespace && strcmp(nspname, last_namespace) == 0)
                                560            2350 :             curr->nspname = last_namespace;
                                561                 :         else
                                562                 :         {
                                563            1432 :             last_namespace = curr->nspname = pg_strdup(nspname);
                                564            1432 :             curr->nsp_alloc = true;
                                565                 :         }
                                566                 : 
 4715                           567            3782 :         relname = PQgetvalue(res, relnum, i_relname);
 3762 bruce                     568 CBC        3782 :         curr->relname = pg_strdup(relname);
                                569                 : 
  193 rhaas                     570 GNC        3782 :         curr->relfilenumber = atooid(PQgetvalue(res, relnum, i_relfilenumber));
 3343 bruce                     571 GIC        3782 :         curr->tblsp_alloc = false;
 4715 bruce                     572 ECB             : 
                                573                 :         /* Is the tablespace oid non-default? */
 4016 bruce                     574 CBC        3782 :         if (atooid(PQgetvalue(res, relnum, i_reltablespace)) != 0)
 3343 bruce                     575 ECB             :         {
                                576                 :             /*
                                577                 :              * The tablespace location might be "", meaning the cluster
                                578                 :              * default location, i.e. pg_default or pg_global.
                                579                 :              */
 3343 bruce                     580 LBC           0 :             tablespace = PQgetvalue(res, relnum, i_spclocation);
 3343 bruce                     581 ECB             : 
                                582                 :             /* Can we reuse the previous string allocation? */
 3343 bruce                     583 LBC           0 :             if (last_tablespace && strcmp(tablespace, last_tablespace) == 0)
 3343 bruce                     584 UIC           0 :                 curr->tablespace = last_tablespace;
 3343 bruce                     585 ECB             :             else
                                586                 :             {
 3343 bruce                     587 LBC           0 :                 last_tablespace = curr->tablespace = pg_strdup(tablespace);
                                588               0 :                 curr->tblsp_alloc = true;
 3343 bruce                     589 ECB             :             }
                                590                 :         }
 4016                           591                 :         else
 3343                           592                 :             /* A zero reltablespace oid indicates the database tablespace. */
 3343 bruce                     593 GIC        3782 :             curr->tablespace = dbinfo->db_tablespace;
                                594                 :     }
 4715                           595              22 :     PQclear(res);
                                596                 : 
                                597              22 :     PQfinish(conn);
                                598                 : 
 4478                           599              22 :     dbinfo->rel_arr.rels = relinfos;
 4478 bruce                     600 CBC          22 :     dbinfo->rel_arr.nrels = num_rels;
 4715                           601              22 : }
                                602                 : 
                                603                 : 
 3799 bruce                     604 ECB             : static void
 4472 bruce                     605 CBC           1 : free_db_and_rel_infos(DbInfoArr *db_arr)
                                606                 : {
                                607                 :     int         dbnum;
 4715 bruce                     608 ECB             : 
 4715 bruce                     609 CBC           3 :     for (dbnum = 0; dbnum < db_arr->ndbs; dbnum++)
                                610                 :     {
 4472                           611               2 :         free_rel_infos(&db_arr->dbs[dbnum].rel_arr);
 3762                           612               2 :         pg_free(db_arr->dbs[dbnum].db_name);
                                613                 :     }
 4472 bruce                     614 GIC           1 :     pg_free(db_arr->dbs);
 4436 bruce                     615 CBC           1 :     db_arr->dbs = NULL;
 4715 bruce                     616 GIC           1 :     db_arr->ndbs = 0;
                                617               1 : }
                                618                 : 
                                619                 : 
                                620                 : static void
 4472 bruce                     621 GBC           2 : free_rel_infos(RelInfoArr *rel_arr)
                                622                 : {
                                623                 :     int         relnum;
 3762 bruce                     624 EUB             : 
 3762 bruce                     625 GBC           6 :     for (relnum = 0; relnum < rel_arr->nrels; relnum++)
                                626                 :     {
 3343 bruce                     627 GIC           4 :         if (rel_arr->rels[relnum].nsp_alloc)
 3343 bruce                     628 GBC           2 :             pg_free(rel_arr->rels[relnum].nspname);
 3762                           629               4 :         pg_free(rel_arr->rels[relnum].relname);
 3343 bruce                     630 GIC           4 :         if (rel_arr->rels[relnum].tblsp_alloc)
 3343 bruce                     631 UIC           0 :             pg_free(rel_arr->rels[relnum].tablespace);
                                632                 :     }
 4472 bruce                     633 GIC           2 :     pg_free(rel_arr->rels);
 4472 bruce                     634 CBC           2 :     rel_arr->nrels = 0;
 4472 bruce                     635 GIC           2 : }
 4715 bruce                     636 ECB             : 
                                637                 : 
 4472                           638                 : static void
 4472 bruce                     639 UIC           0 : print_db_infos(DbInfoArr *db_arr)
 4472 bruce                     640 ECB             : {
                                641                 :     int         dbnum;
                                642                 : 
 4472 bruce                     643 UIC           0 :     for (dbnum = 0; dbnum < db_arr->ndbs; dbnum++)
                                644                 :     {
  271 tgl                       645 UNC           0 :         pg_log(PG_VERBOSE, "Database: %s", db_arr->dbs[dbnum].db_name);
 4472 bruce                     646 LBC           0 :         print_rel_infos(&db_arr->dbs[dbnum].rel_arr);
                                647                 :     }
 4715 bruce                     648 UIC           0 : }
 4715 bruce                     649 ECB             : 
                                650                 : 
                                651                 : static void
 3762 bruce                     652 LBC           0 : print_rel_infos(RelInfoArr *rel_arr)
                                653                 : {
 4715 bruce                     654 ECB             :     int         relnum;
                                655                 : 
 3762 bruce                     656 LBC           0 :     for (relnum = 0; relnum < rel_arr->nrels; relnum++)
  271 tgl                       657 UNC           0 :         pg_log(PG_VERBOSE, "relname: %s.%s: reloid: %u reltblspace: %s",
 3599 sfrost                    658 UIC           0 :                rel_arr->rels[relnum].nspname,
                                659               0 :                rel_arr->rels[relnum].relname,
                                660               0 :                rel_arr->rels[relnum].reloid,
 3599 sfrost                    661 LBC           0 :                rel_arr->rels[relnum].tablespace);
 4715 bruce                     662 UIC           0 : }
        

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