LCOV - code coverage report
Current view: top level - src/bin/pg_upgrade - version.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 29.5 % 78 23
Test Date: 2026-03-16 22:14:56 Functions: 80.0 % 5 4
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*
       2              :  *  version.c
       3              :  *
       4              :  *  Postgres-version-specific routines
       5              :  *
       6              :  *  Copyright (c) 2010-2026, PostgreSQL Global Development Group
       7              :  *  src/bin/pg_upgrade/version.c
       8              :  */
       9              : 
      10              : #include "postgres_fe.h"
      11              : 
      12              : #include "fe_utils/string_utils.h"
      13              : #include "pg_upgrade.h"
      14              : 
      15              : /*
      16              :  * version_hook functions for check_for_data_types_usage in order to determine
      17              :  * whether a data type check should be executed for the cluster in question or
      18              :  * not.
      19              :  */
      20              : bool
      21           15 : jsonb_9_4_check_applicable(ClusterInfo *cluster)
      22              : {
      23              :     /* JSONB changed its storage format during 9.4 beta */
      24           15 :     if (GET_MAJOR_VERSION(cluster->major_version) == 904 &&
      25            0 :         cluster->controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER)
      26            0 :         return true;
      27              : 
      28           15 :     return false;
      29              : }
      30              : 
      31              : /*
      32              :  * Older servers can't support newer protocol versions, so their connection
      33              :  * strings will need to lock max_protocol_version to 3.0.
      34              :  */
      35              : bool
      36          712 : protocol_negotiation_supported(const ClusterInfo *cluster)
      37              : {
      38              :     /*
      39              :      * The February 2018 patch release (9.3.21, 9.4.16, 9.5.11, 9.6.7, and
      40              :      * 10.2) added support for NegotiateProtocolVersion. But ClusterInfo only
      41              :      * has information about the major version number. To ensure we can still
      42              :      * upgrade older unpatched servers, just assume anything prior to PG11
      43              :      * can't negotiate. It's not possible for those servers to make use of
      44              :      * newer protocols anyway, so nothing is lost.
      45              :      */
      46          712 :     return (GET_MAJOR_VERSION(cluster->major_version) >= 1100);
      47              : }
      48              : 
      49              : /*
      50              :  * old_9_6_invalidate_hash_indexes()
      51              :  *  9.6 -> 10
      52              :  *  Hash index binary format has changed from 9.6->10.0
      53              :  */
      54              : void
      55            0 : old_9_6_invalidate_hash_indexes(ClusterInfo *cluster, bool check_mode)
      56              : {
      57              :     int         dbnum;
      58            0 :     FILE       *script = NULL;
      59            0 :     bool        found = false;
      60            0 :     char       *output_path = "reindex_hash.sql";
      61              : 
      62            0 :     prep_status("Checking for hash indexes");
      63              : 
      64            0 :     for (dbnum = 0; dbnum < cluster->dbarr.ndbs; dbnum++)
      65              :     {
      66              :         PGresult   *res;
      67            0 :         bool        db_used = false;
      68              :         int         ntups;
      69              :         int         rowno;
      70              :         int         i_nspname,
      71              :                     i_relname;
      72            0 :         DbInfo     *active_db = &cluster->dbarr.dbs[dbnum];
      73            0 :         PGconn     *conn = connectToServer(cluster, active_db->db_name);
      74              : 
      75              :         /* find hash indexes */
      76            0 :         res = executeQueryOrDie(conn,
      77              :                                 "SELECT n.nspname, c.relname "
      78              :                                 "FROM  pg_catalog.pg_class c, "
      79              :                                 "      pg_catalog.pg_index i, "
      80              :                                 "      pg_catalog.pg_am a, "
      81              :                                 "      pg_catalog.pg_namespace n "
      82              :                                 "WHERE i.indexrelid = c.oid AND "
      83              :                                 "      c.relam = a.oid AND "
      84              :                                 "      c.relnamespace = n.oid AND "
      85              :                                 "      a.amname = 'hash'"
      86              :             );
      87              : 
      88            0 :         ntups = PQntuples(res);
      89            0 :         i_nspname = PQfnumber(res, "nspname");
      90            0 :         i_relname = PQfnumber(res, "relname");
      91            0 :         for (rowno = 0; rowno < ntups; rowno++)
      92              :         {
      93            0 :             found = true;
      94            0 :             if (!check_mode)
      95              :             {
      96            0 :                 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
      97            0 :                     pg_fatal("could not open file \"%s\": %m", output_path);
      98            0 :                 if (!db_used)
      99              :                 {
     100              :                     PQExpBufferData connectbuf;
     101              : 
     102            0 :                     initPQExpBuffer(&connectbuf);
     103            0 :                     appendPsqlMetaConnect(&connectbuf, active_db->db_name);
     104            0 :                     fputs(connectbuf.data, script);
     105            0 :                     termPQExpBuffer(&connectbuf);
     106            0 :                     db_used = true;
     107              :                 }
     108            0 :                 fprintf(script, "REINDEX INDEX %s.%s;\n",
     109            0 :                         quote_identifier(PQgetvalue(res, rowno, i_nspname)),
     110            0 :                         quote_identifier(PQgetvalue(res, rowno, i_relname)));
     111              :             }
     112              :         }
     113              : 
     114            0 :         PQclear(res);
     115              : 
     116            0 :         if (!check_mode && db_used)
     117              :         {
     118              :             /* mark hash indexes as invalid */
     119            0 :             PQclear(executeQueryOrDie(conn,
     120              :                                       "UPDATE pg_catalog.pg_index i "
     121              :                                       "SET indisvalid = false "
     122              :                                       "FROM    pg_catalog.pg_class c, "
     123              :                                       "        pg_catalog.pg_am a, "
     124              :                                       "        pg_catalog.pg_namespace n "
     125              :                                       "WHERE   i.indexrelid = c.oid AND "
     126              :                                       "        c.relam = a.oid AND "
     127              :                                       "        c.relnamespace = n.oid AND "
     128              :                                       "        a.amname = 'hash'"));
     129              :         }
     130              : 
     131            0 :         PQfinish(conn);
     132              :     }
     133              : 
     134            0 :     if (script)
     135            0 :         fclose(script);
     136              : 
     137            0 :     if (found)
     138              :     {
     139            0 :         report_status(PG_WARNING, "warning");
     140            0 :         if (check_mode)
     141            0 :             pg_log(PG_WARNING, "\n"
     142              :                    "Your installation contains hash indexes.  These indexes have different\n"
     143              :                    "internal formats between your old and new clusters, so they must be\n"
     144              :                    "reindexed with the REINDEX command.  After upgrading, you will be given\n"
     145              :                    "REINDEX instructions.");
     146              :         else
     147            0 :             pg_log(PG_WARNING, "\n"
     148              :                    "Your installation contains hash indexes.  These indexes have different\n"
     149              :                    "internal formats between your old and new clusters, so they must be\n"
     150              :                    "reindexed with the REINDEX command.  The file\n"
     151              :                    "    %s\n"
     152              :                    "when executed by psql by the database superuser will recreate all invalid\n"
     153              :                    "indexes; until then, none of these indexes will be used.",
     154              :                    output_path);
     155              :     }
     156              :     else
     157            0 :         check_ok();
     158            0 : }
     159              : 
     160              : /*
     161              :  * Callback function for processing results of query for
     162              :  * report_extension_updates()'s UpgradeTask.  If the query returned any rows,
     163              :  * write the details to the report file.
     164              :  */
     165              : static void
     166           32 : process_extension_updates(DbInfo *dbinfo, PGresult *res, void *arg)
     167              : {
     168           32 :     int         ntups = PQntuples(res);
     169           32 :     int         i_name = PQfnumber(res, "name");
     170           32 :     UpgradeTaskReport *report = (UpgradeTaskReport *) arg;
     171              :     PQExpBufferData connectbuf;
     172              : 
     173           32 :     if (ntups == 0)
     174           32 :         return;
     175              : 
     176            0 :     if (report->file == NULL &&
     177            0 :         (report->file = fopen_priv(report->path, "w")) == NULL)
     178            0 :         pg_fatal("could not open file \"%s\": %m", report->path);
     179              : 
     180            0 :     initPQExpBuffer(&connectbuf);
     181            0 :     appendPsqlMetaConnect(&connectbuf, dbinfo->db_name);
     182            0 :     fputs(connectbuf.data, report->file);
     183            0 :     termPQExpBuffer(&connectbuf);
     184              : 
     185            0 :     for (int rowno = 0; rowno < ntups; rowno++)
     186            0 :         fprintf(report->file, "ALTER EXTENSION %s UPDATE;\n",
     187            0 :                 quote_identifier(PQgetvalue(res, rowno, i_name)));
     188              : }
     189              : 
     190              : /*
     191              :  * report_extension_updates()
     192              :  *  Report extensions that should be updated.
     193              :  */
     194              : void
     195           10 : report_extension_updates(ClusterInfo *cluster)
     196              : {
     197              :     UpgradeTaskReport report;
     198           10 :     UpgradeTask *task = upgrade_task_create();
     199           10 :     const char *query = "SELECT name "
     200              :         "FROM pg_available_extensions "
     201              :         "WHERE installed_version != default_version";
     202              : 
     203           10 :     prep_status("Checking for extension updates");
     204              : 
     205           10 :     report.file = NULL;
     206           10 :     strcpy(report.path, "update_extensions.sql");
     207              : 
     208           10 :     upgrade_task_add_step(task, query, process_extension_updates,
     209              :                           true, &report);
     210              : 
     211           10 :     upgrade_task_run(task, cluster);
     212           10 :     upgrade_task_free(task);
     213              : 
     214           10 :     if (report.file)
     215              :     {
     216            0 :         fclose(report.file);
     217            0 :         report_status(PG_REPORT, "notice");
     218            0 :         pg_log(PG_REPORT, "\n"
     219              :                "Your installation contains extensions that should be updated\n"
     220              :                "with the ALTER EXTENSION command.  The file\n"
     221              :                "    %s\n"
     222              :                "when executed by psql by the database superuser will update\n"
     223              :                "these extensions.",
     224              :                report.path);
     225              :     }
     226              :     else
     227           10 :         check_ok();
     228           10 : }
        

Generated by: LCOV version 2.0-1