LCOV - differential code coverage report
Current view: top level - src/bin/pg_upgrade - function.c (source / functions) Coverage Total Hit UBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 85.0 % 80 68 12 68
Current Date: 2025-09-06 07:49:51 +0900 Functions: 100.0 % 4 4 4
Baseline: lcov-20250906-005545-baseline Branches: 60.7 % 28 17 11 17
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 100.0 % 16 16 16
(360..) days: 81.2 % 64 52 12 52
Function coverage date bins:
(30,360] days: 100.0 % 1 1 1
(360..) days: 100.0 % 3 3 3
Branch coverage date bins:
(360..) days: 60.7 % 28 17 11 17

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*
                                  2                 :                :  *  function.c
                                  3                 :                :  *
                                  4                 :                :  *  server-side function support
                                  5                 :                :  *
                                  6                 :                :  *  Copyright (c) 2010-2025, PostgreSQL Global Development Group
                                  7                 :                :  *  src/bin/pg_upgrade/function.c
                                  8                 :                :  */
                                  9                 :                : 
                                 10                 :                : #include "postgres_fe.h"
                                 11                 :                : 
                                 12                 :                : #include "access/transam.h"
                                 13                 :                : #include "catalog/pg_language_d.h"
                                 14                 :                : #include "common/int.h"
                                 15                 :                : #include "pg_upgrade.h"
                                 16                 :                : 
                                 17                 :                : /*
                                 18                 :                :  * qsort comparator for pointers to library names
                                 19                 :                :  *
                                 20                 :                :  * We sort first by name length, then alphabetically for names of the
                                 21                 :                :  * same length, then database array index.  This is to ensure that, eg,
                                 22                 :                :  * "hstore_plpython" sorts after both "hstore" and "plpython"; otherwise
                                 23                 :                :  * transform modules will probably fail their LOAD tests.  (The backend
                                 24                 :                :  * ought to cope with that consideration, but it doesn't yet, and even
                                 25                 :                :  * when it does it'll still be a good idea to have a predictable order of
                                 26                 :                :  * probing here.)
                                 27                 :                :  */
                                 28                 :                : static int
 3260 tgl@sss.pgh.pa.us          29                 :CBC           1 : library_name_compare(const void *p1, const void *p2)
                                 30                 :                : {
 2597 bruce@momjian.us           31                 :              1 :     const char *str1 = ((const LibraryInfo *) p1)->name;
                                 32                 :              1 :     const char *str2 = ((const LibraryInfo *) p2)->name;
  568 nathan@postgresql.or       33                 :              1 :     size_t      slen1 = strlen(str1);
                                 34                 :              1 :     size_t      slen2 = strlen(str2);
 2597 bruce@momjian.us           35                 :              1 :     int         cmp = strcmp(str1, str2);
                                 36                 :                : 
 3260 tgl@sss.pgh.pa.us          37         [ -  + ]:              1 :     if (slen1 != slen2)
  568 nathan@postgresql.or       38                 :UBC           0 :         return pg_cmp_size(slen1, slen2);
 2597 bruce@momjian.us           39         [ -  + ]:CBC           1 :     if (cmp != 0)
 2597 bruce@momjian.us           40                 :UBC           0 :         return cmp;
  568 nathan@postgresql.or       41                 :CBC           1 :     return pg_cmp_s32(((const LibraryInfo *) p1)->dbnum,
                                 42                 :              1 :                       ((const LibraryInfo *) p2)->dbnum);
                                 43                 :                : }
                                 44                 :                : 
                                 45                 :                : /*
                                 46                 :                :  * Private state for get_loadable_libraries()'s UpgradeTask.
                                 47                 :                :  */
                                 48                 :                : struct loadable_libraries_state
                                 49                 :                : {
                                 50                 :                :     PGresult  **ress;           /* results for each database */
                                 51                 :                :     int         totaltups;      /* number of tuples in all results */
                                 52                 :                : };
                                 53                 :                : 
                                 54                 :                : /*
                                 55                 :                :  * Callback function for processing results of query for
                                 56                 :                :  * get_loadable_libraries()'s UpgradeTask.  This function stores the results
                                 57                 :                :  * for later use within get_loadable_libraries().
                                 58                 :                :  */
                                 59                 :                : static void
  355                            60                 :             48 : process_loadable_libraries(DbInfo *dbinfo, PGresult *res, void *arg)
                                 61                 :                : {
                                 62                 :             48 :     struct loadable_libraries_state *state = (struct loadable_libraries_state *) arg;
                                 63                 :                : 
                                 64                 :                :     AssertVariableIsOfType(&process_loadable_libraries, UpgradeTaskProcessCB);
                                 65                 :                : 
                                 66                 :             48 :     state->ress[dbinfo - old_cluster.dbarr.dbs] = res;
                                 67                 :             48 :     state->totaltups += PQntuples(res);
                                 68                 :             48 : }
                                 69                 :                : 
                                 70                 :                : /*
                                 71                 :                :  * get_loadable_libraries()
                                 72                 :                :  *
                                 73                 :                :  *  Fetch the names of all old libraries containing either C-language functions
                                 74                 :                :  *  or are corresponding to logical replication output plugins.
                                 75                 :                :  *
                                 76                 :                :  *  We will later check that they all exist in the new installation.
                                 77                 :                :  */
                                 78                 :                : void
 5436 bruce@momjian.us           79                 :             15 : get_loadable_libraries(void)
                                 80                 :                : {
                                 81                 :                :     int         totaltups;
                                 82                 :                :     int         dbnum;
                                 83                 :                :     int         n_libinfos;
  355 nathan@postgresql.or       84                 :             15 :     UpgradeTask *task = upgrade_task_create();
                                 85                 :                :     struct loadable_libraries_state state;
                                 86                 :                :     char       *query;
                                 87                 :                : 
                                 88                 :             15 :     state.ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
                                 89                 :             15 :     state.totaltups = 0;
                                 90                 :                : 
                                 91                 :             15 :     query = psprintf("SELECT DISTINCT probin "
                                 92                 :                :                      "FROM pg_catalog.pg_proc "
                                 93                 :                :                      "WHERE prolang = %u AND "
                                 94                 :                :                      "probin IS NOT NULL AND "
                                 95                 :                :                      "oid >= %u",
                                 96                 :                :                      ClanguageId,
                                 97                 :                :                      FirstNormalObjectId);
                                 98                 :                : 
                                 99                 :             15 :     upgrade_task_add_step(task, query, process_loadable_libraries,
                                100                 :                :                           false, &state);
                                101                 :                : 
                                102                 :             15 :     upgrade_task_run(task, &old_cluster);
                                103                 :             15 :     upgrade_task_free(task);
                                104                 :                : 
                                105                 :                :     /*
                                106                 :                :      * Allocate memory for required libraries and logical replication output
                                107                 :                :      * plugins.
                                108                 :                :      */
                                109                 :             15 :     n_libinfos = state.totaltups + count_old_cluster_logical_slots();
  681 akapila@postgresql.o      110                 :             15 :     os_info.libraries = (LibraryInfo *) pg_malloc(sizeof(LibraryInfo) * n_libinfos);
 5596 bruce@momjian.us          111                 :             15 :     totaltups = 0;
                                112                 :                : 
 5362                           113         [ +  + ]:             63 :     for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
                                114                 :                :     {
  355 nathan@postgresql.or      115                 :             48 :         PGresult   *res = state.ress[dbnum];
                                116                 :                :         int         ntups;
                                117                 :                :         int         rowno;
  681 akapila@postgresql.o      118                 :             48 :         LogicalSlotInfoArr *slot_arr = &old_cluster.dbarr.dbs[dbnum].slot_arr;
                                119                 :                : 
 5596 bruce@momjian.us          120                 :             48 :         ntups = PQntuples(res);
                                121         [ +  + ]:             50 :         for (rowno = 0; rowno < ntups; rowno++)
                                122                 :                :         {
                                123                 :              2 :             char       *lib = PQgetvalue(res, rowno, 0);
                                124                 :                : 
 2597                           125                 :              2 :             os_info.libraries[totaltups].name = pg_strdup(lib);
                                126                 :              2 :             os_info.libraries[totaltups].dbnum = dbnum;
                                127                 :                : 
                                128                 :              2 :             totaltups++;
                                129                 :                :         }
 5596                           130                 :             48 :         PQclear(res);
                                131                 :                : 
                                132                 :                :         /*
                                133                 :                :          * Store the names of output plugins as well. There is a possibility
                                134                 :                :          * that duplicated plugins are set, but the consumer function
                                135                 :                :          * check_loadable_libraries() will avoid checking the same library, so
                                136                 :                :          * we do not have to consider their uniqueness here.
                                137                 :                :          */
  681 akapila@postgresql.o      138         [ +  + ]:             53 :         for (int slotno = 0; slotno < slot_arr->nslots; slotno++)
                                139                 :                :         {
                                140         [ -  + ]:              5 :             if (slot_arr->slots[slotno].invalid)
  681 akapila@postgresql.o      141                 :UBC           0 :                 continue;
                                142                 :                : 
  681 akapila@postgresql.o      143                 :CBC           5 :             os_info.libraries[totaltups].name = pg_strdup(slot_arr->slots[slotno].plugin);
                                144                 :              5 :             os_info.libraries[totaltups].dbnum = dbnum;
                                145                 :                : 
                                146                 :              5 :             totaltups++;
                                147                 :                :         }
                                148                 :                :     }
                                149                 :                : 
  355 nathan@postgresql.or      150                 :             15 :     pg_free(state.ress);
                                151                 :             15 :     pg_free(query);
                                152                 :                : 
 3260 tgl@sss.pgh.pa.us         153                 :             15 :     os_info.num_libraries = totaltups;
 5596 bruce@momjian.us          154                 :             15 : }
                                155                 :                : 
                                156                 :                : 
                                157                 :                : /*
                                158                 :                :  * check_loadable_libraries()
                                159                 :                :  *
                                160                 :                :  *  Check that the new cluster contains all required libraries.
                                161                 :                :  *  We do this by actually trying to LOAD each one, thereby testing
                                162                 :                :  *  compatibility as well as presence.
                                163                 :                :  */
                                164                 :                : void
 5436                           165                 :             13 : check_loadable_libraries(void)
                                166                 :                : {
 5362                           167                 :             13 :     PGconn     *conn = connectToServer(&new_cluster, "template1");
                                168                 :                :     int         libnum;
 2597                           169                 :             13 :     int         was_load_failure = false;
 5596                           170                 :             13 :     FILE       *script = NULL;
                                171                 :                :     char        output_path[MAXPGPATH];
                                172                 :                : 
 5436                           173                 :             13 :     prep_status("Checking for presence of required libraries");
                                174                 :                : 
 1308 michael@paquier.xyz       175                 :             13 :     snprintf(output_path, sizeof(output_path), "%s/%s",
                                176                 :                :              log_opts.basedir, "loadable_libraries.txt");
                                177                 :                : 
                                178                 :                :     /*
                                179                 :                :      * Now we want to sort the library names into order.  This avoids multiple
                                180                 :                :      * probes of the same library, and ensures that libraries are probed in a
                                181                 :                :      * consistent order, which is important for reproducible behavior if one
                                182                 :                :      * library depends on another.
                                183                 :                :      */
  942 peter@eisentraut.org      184                 :             13 :     qsort(os_info.libraries, os_info.num_libraries,
                                185                 :                :           sizeof(LibraryInfo), library_name_compare);
                                186                 :                : 
 5436 bruce@momjian.us          187         [ +  + ]:             18 :     for (libnum = 0; libnum < os_info.num_libraries; libnum++)
                                188                 :                :     {
 2597                           189                 :              5 :         char       *lib = os_info.libraries[libnum].name;
 5596                           190                 :              5 :         int         llen = strlen(lib);
                                191                 :                :         char        cmd[7 + 2 * MAXPGPATH + 1];
                                192                 :                :         PGresult   *res;
                                193                 :                : 
                                194                 :                :         /* Did the library name change?  Probe it. */
 2597                           195   [ +  +  -  + ]:              5 :         if (libnum == 0 || strcmp(lib, os_info.libraries[libnum - 1].name) != 0)
                                196                 :                :         {
                                197                 :              4 :             strcpy(cmd, "LOAD '");
                                198                 :              4 :             PQescapeStringConn(conn, cmd + strlen(cmd), lib, llen, NULL);
                                199                 :              4 :             strcat(cmd, "'");
                                200                 :                : 
                                201                 :              4 :             res = PQexec(conn, cmd);
                                202                 :                : 
                                203         [ -  + ]:              4 :             if (PQresultStatus(res) != PGRES_COMMAND_OK)
                                204                 :                :             {
 2597 bruce@momjian.us          205                 :UBC           0 :                 was_load_failure = true;
                                206                 :                : 
                                207   [ #  #  #  # ]:              0 :                 if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
  543 michael@paquier.xyz       208                 :              0 :                     pg_fatal("could not open file \"%s\": %m", output_path);
 2597 bruce@momjian.us          209                 :              0 :                 fprintf(script, _("could not load library \"%s\": %s"),
                                210                 :                :                         lib,
                                211                 :                :                         PQerrorMessage(conn));
                                212                 :                :             }
                                213                 :                :             else
 2597 bruce@momjian.us          214                 :CBC           4 :                 was_load_failure = false;
                                215                 :                : 
                                216                 :              4 :             PQclear(res);
                                217                 :                :         }
                                218                 :                : 
                                219         [ -  + ]:              5 :         if (was_load_failure)
 2160 bruce@momjian.us          220                 :UBC           0 :             fprintf(script, _("In database: %s\n"),
 2299 tgl@sss.pgh.pa.us         221                 :              0 :                     old_cluster.dbarr.dbs[os_info.libraries[libnum].dbnum].db_name);
                                222                 :                :     }
                                223                 :                : 
 5596 bruce@momjian.us          224                 :CBC          13 :     PQfinish(conn);
                                225                 :                : 
 1102 dgustafsson@postgres      226         [ -  + ]:             13 :     if (script)
                                227                 :                :     {
 5596 bruce@momjian.us          228                 :UBC           0 :         fclose(script);
 1152 tgl@sss.pgh.pa.us         229                 :              0 :         pg_log(PG_REPORT, "fatal");
 4358 peter_e@gmx.net           230                 :              0 :         pg_fatal("Your installation references loadable libraries that are missing from the\n"
                                231                 :                :                  "new installation.  You can add these libraries to the new installation,\n"
                                232                 :                :                  "or remove the functions using them from the old installation.  A list of\n"
                                233                 :                :                  "problem libraries is in the file:\n"
                                234                 :                :                  "    %s", output_path);
                                235                 :                :     }
                                236                 :                :     else
 5436 bruce@momjian.us          237                 :CBC          13 :         check_ok();
 5596                           238                 :             13 : }
        

Generated by: LCOV version 2.4-beta