LCOV - code coverage report
Current view: top level - src/backend/utils/adt - pg_upgrade_support.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 91.8 % 159 146
Test Date: 2026-09-21 15:17:02 Functions: 95.2 % 21 20
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 30.8 % 120 37

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  *  pg_upgrade_support.c
       3                 :             :  *
       4                 :             :  *  server-side functions to set backend global variables
       5                 :             :  *  to control oid and relfilenumber assignment, and do other special
       6                 :             :  *  hacks needed for pg_upgrade.
       7                 :             :  *
       8                 :             :  *  Copyright (c) 2010-2026, PostgreSQL Global Development Group
       9                 :             :  *  src/backend/utils/adt/pg_upgrade_support.c
      10                 :             :  */
      11                 :             : 
      12                 :             : #include "postgres.h"
      13                 :             : 
      14                 :             : #include "access/relation.h"
      15                 :             : #include "access/table.h"
      16                 :             : #include "catalog/binary_upgrade.h"
      17                 :             : #include "catalog/heap.h"
      18                 :             : #include "catalog/namespace.h"
      19                 :             : #include "catalog/pg_subscription_rel.h"
      20                 :             : #include "catalog/pg_type.h"
      21                 :             : #include "commands/extension.h"
      22                 :             : #include "miscadmin.h"
      23                 :             : #include "replication/logical.h"
      24                 :             : #include "replication/logicallauncher.h"
      25                 :             : #include "replication/origin.h"
      26                 :             : #include "replication/worker_internal.h"
      27                 :             : #include "storage/lmgr.h"
      28                 :             : #include "utils/array.h"
      29                 :             : #include "utils/builtins.h"
      30                 :             : #include "utils/lsyscache.h"
      31                 :             : #include "utils/pg_lsn.h"
      32                 :             : 
      33                 :             : 
      34                 :             : #define CHECK_IS_BINARY_UPGRADE                                 \
      35                 :             : do {                                                            \
      36                 :             :     if (!IsBinaryUpgrade)                                       \
      37                 :             :         ereport(ERROR,                                          \
      38                 :             :                 (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),    \
      39                 :             :                  errmsg("function can only be called when server is in binary upgrade mode"))); \
      40                 :             : } while (0)
      41                 :             : 
      42                 :             : Datum
      43                 :           4 : binary_upgrade_set_next_pg_tablespace_oid(PG_FUNCTION_ARGS)
      44                 :             : {
      45                 :           4 :     Oid         tbspoid = PG_GETARG_OID(0);
      46                 :             : 
      47   [ -  +  -  - ]:           4 :     CHECK_IS_BINARY_UPGRADE;
      48                 :           4 :     binary_upgrade_next_pg_tablespace_oid = tbspoid;
      49                 :             : 
      50                 :           4 :     PG_RETURN_VOID();
      51                 :             : }
      52                 :             : 
      53                 :             : Datum
      54                 :         896 : binary_upgrade_set_next_pg_type_oid(PG_FUNCTION_ARGS)
      55                 :             : {
      56                 :         896 :     Oid         typoid = PG_GETARG_OID(0);
      57                 :             : 
      58   [ -  +  -  - ]:         896 :     CHECK_IS_BINARY_UPGRADE;
      59                 :         896 :     binary_upgrade_next_pg_type_oid = typoid;
      60                 :             : 
      61                 :         896 :     PG_RETURN_VOID();
      62                 :             : }
      63                 :             : 
      64                 :             : Datum
      65                 :         895 : binary_upgrade_set_next_array_pg_type_oid(PG_FUNCTION_ARGS)
      66                 :             : {
      67                 :         895 :     Oid         typoid = PG_GETARG_OID(0);
      68                 :             : 
      69   [ -  +  -  - ]:         895 :     CHECK_IS_BINARY_UPGRADE;
      70                 :         895 :     binary_upgrade_next_array_pg_type_oid = typoid;
      71                 :             : 
      72                 :         895 :     PG_RETURN_VOID();
      73                 :             : }
      74                 :             : 
      75                 :             : Datum
      76                 :           7 : binary_upgrade_set_next_multirange_pg_type_oid(PG_FUNCTION_ARGS)
      77                 :             : {
      78                 :           7 :     Oid         typoid = PG_GETARG_OID(0);
      79                 :             : 
      80   [ -  +  -  - ]:           7 :     CHECK_IS_BINARY_UPGRADE;
      81                 :           7 :     binary_upgrade_next_mrng_pg_type_oid = typoid;
      82                 :             : 
      83                 :           7 :     PG_RETURN_VOID();
      84                 :             : }
      85                 :             : 
      86                 :             : Datum
      87                 :           7 : binary_upgrade_set_next_multirange_array_pg_type_oid(PG_FUNCTION_ARGS)
      88                 :             : {
      89                 :           7 :     Oid         typoid = PG_GETARG_OID(0);
      90                 :             : 
      91   [ -  +  -  - ]:           7 :     CHECK_IS_BINARY_UPGRADE;
      92                 :           7 :     binary_upgrade_next_mrng_array_pg_type_oid = typoid;
      93                 :             : 
      94                 :           7 :     PG_RETURN_VOID();
      95                 :             : }
      96                 :             : 
      97                 :             : Datum
      98                 :         901 : binary_upgrade_set_next_heap_pg_class_oid(PG_FUNCTION_ARGS)
      99                 :             : {
     100                 :         901 :     Oid         reloid = PG_GETARG_OID(0);
     101                 :             : 
     102   [ -  +  -  - ]:         901 :     CHECK_IS_BINARY_UPGRADE;
     103                 :         901 :     binary_upgrade_next_heap_pg_class_oid = reloid;
     104                 :             : 
     105                 :         901 :     PG_RETURN_VOID();
     106                 :             : }
     107                 :             : 
     108                 :             : Datum
     109                 :         805 : binary_upgrade_set_next_heap_relfilenode(PG_FUNCTION_ARGS)
     110                 :             : {
     111                 :         805 :     RelFileNumber relfilenumber = PG_GETARG_OID(0);
     112                 :             : 
     113   [ -  +  -  - ]:         805 :     CHECK_IS_BINARY_UPGRADE;
     114                 :         805 :     binary_upgrade_next_heap_pg_class_relfilenumber = relfilenumber;
     115                 :             : 
     116                 :         805 :     PG_RETURN_VOID();
     117                 :             : }
     118                 :             : 
     119                 :             : Datum
     120                 :         581 : binary_upgrade_set_next_index_pg_class_oid(PG_FUNCTION_ARGS)
     121                 :             : {
     122                 :         581 :     Oid         reloid = PG_GETARG_OID(0);
     123                 :             : 
     124   [ -  +  -  - ]:         581 :     CHECK_IS_BINARY_UPGRADE;
     125                 :         581 :     binary_upgrade_next_index_pg_class_oid = reloid;
     126                 :             : 
     127                 :         581 :     PG_RETURN_VOID();
     128                 :             : }
     129                 :             : 
     130                 :             : Datum
     131                 :         645 : binary_upgrade_set_next_index_relfilenode(PG_FUNCTION_ARGS)
     132                 :             : {
     133                 :         645 :     RelFileNumber relfilenumber = PG_GETARG_OID(0);
     134                 :             : 
     135   [ -  +  -  - ]:         645 :     CHECK_IS_BINARY_UPGRADE;
     136                 :         645 :     binary_upgrade_next_index_pg_class_relfilenumber = relfilenumber;
     137                 :             : 
     138                 :         645 :     PG_RETURN_VOID();
     139                 :             : }
     140                 :             : 
     141                 :             : Datum
     142                 :         278 : binary_upgrade_set_next_toast_pg_class_oid(PG_FUNCTION_ARGS)
     143                 :             : {
     144                 :         278 :     Oid         reloid = PG_GETARG_OID(0);
     145                 :             : 
     146   [ -  +  -  - ]:         278 :     CHECK_IS_BINARY_UPGRADE;
     147                 :         278 :     binary_upgrade_next_toast_pg_class_oid = reloid;
     148                 :             : 
     149                 :         278 :     PG_RETURN_VOID();
     150                 :             : }
     151                 :             : 
     152                 :             : Datum
     153                 :         278 : binary_upgrade_set_next_toast_chunk_id_typoid(PG_FUNCTION_ARGS)
     154                 :             : {
     155                 :         278 :     Oid         typoid = PG_GETARG_OID(0);
     156                 :             : 
     157   [ -  +  -  - ]:         278 :     CHECK_IS_BINARY_UPGRADE;
     158                 :         278 :     binary_upgrade_next_toast_chunk_id_typoid = typoid;
     159                 :             : 
     160                 :         278 :     PG_RETURN_VOID();
     161                 :             : }
     162                 :             : 
     163                 :             : Datum
     164                 :         278 : binary_upgrade_set_next_toast_relfilenode(PG_FUNCTION_ARGS)
     165                 :             : {
     166                 :         278 :     RelFileNumber relfilenumber = PG_GETARG_OID(0);
     167                 :             : 
     168   [ -  +  -  - ]:         278 :     CHECK_IS_BINARY_UPGRADE;
     169                 :         278 :     binary_upgrade_next_toast_pg_class_relfilenumber = relfilenumber;
     170                 :             : 
     171                 :         278 :     PG_RETURN_VOID();
     172                 :             : }
     173                 :             : 
     174                 :             : Datum
     175                 :          50 : binary_upgrade_set_next_pg_enum_oid(PG_FUNCTION_ARGS)
     176                 :             : {
     177                 :          50 :     Oid         enumoid = PG_GETARG_OID(0);
     178                 :             : 
     179   [ -  +  -  - ]:          50 :     CHECK_IS_BINARY_UPGRADE;
     180                 :          50 :     binary_upgrade_next_pg_enum_oid = enumoid;
     181                 :             : 
     182                 :          50 :     PG_RETURN_VOID();
     183                 :             : }
     184                 :             : 
     185                 :             : Datum
     186                 :          18 : binary_upgrade_set_next_pg_authid_oid(PG_FUNCTION_ARGS)
     187                 :             : {
     188                 :          18 :     Oid         authoid = PG_GETARG_OID(0);
     189                 :             : 
     190   [ -  +  -  - ]:          18 :     CHECK_IS_BINARY_UPGRADE;
     191                 :          18 :     binary_upgrade_next_pg_authid_oid = authoid;
     192                 :          18 :     PG_RETURN_VOID();
     193                 :             : }
     194                 :             : 
     195                 :             : Datum
     196                 :           5 : binary_upgrade_create_empty_extension(PG_FUNCTION_ARGS)
     197                 :             : {
     198                 :             :     text       *extName;
     199                 :             :     text       *schemaName;
     200                 :             :     bool        relocatable;
     201                 :             :     text       *extVersion;
     202                 :             :     Datum       extConfig;
     203                 :             :     Datum       extCondition;
     204                 :             :     List       *requiredExtensions;
     205                 :             : 
     206   [ -  +  -  - ]:           5 :     CHECK_IS_BINARY_UPGRADE;
     207                 :             : 
     208                 :             :     /* We must check these things before dereferencing the arguments */
     209         [ +  - ]:           5 :     if (PG_ARGISNULL(0) ||
     210         [ +  - ]:           5 :         PG_ARGISNULL(1) ||
     211         [ +  - ]:           5 :         PG_ARGISNULL(2) ||
     212         [ -  + ]:           5 :         PG_ARGISNULL(3))
     213         [ #  # ]:           0 :         elog(ERROR, "null argument to binary_upgrade_create_empty_extension is not allowed");
     214                 :             : 
     215                 :           5 :     extName = PG_GETARG_TEXT_PP(0);
     216                 :           5 :     schemaName = PG_GETARG_TEXT_PP(1);
     217                 :           5 :     relocatable = PG_GETARG_BOOL(2);
     218                 :           5 :     extVersion = PG_GETARG_TEXT_PP(3);
     219                 :             : 
     220         [ +  - ]:           5 :     if (PG_ARGISNULL(4))
     221                 :           5 :         extConfig = PointerGetDatum(NULL);
     222                 :             :     else
     223                 :           0 :         extConfig = PG_GETARG_DATUM(4);
     224                 :             : 
     225         [ +  - ]:           5 :     if (PG_ARGISNULL(5))
     226                 :           5 :         extCondition = PointerGetDatum(NULL);
     227                 :             :     else
     228                 :           0 :         extCondition = PG_GETARG_DATUM(5);
     229                 :             : 
     230                 :           5 :     requiredExtensions = NIL;
     231         [ +  - ]:           5 :     if (!PG_ARGISNULL(6))
     232                 :             :     {
     233                 :           5 :         ArrayType  *textArray = PG_GETARG_ARRAYTYPE_P(6);
     234                 :             :         Datum      *textDatums;
     235                 :             :         int         ndatums;
     236                 :             :         int         i;
     237                 :             : 
     238                 :           5 :         deconstruct_array_builtin(textArray, TEXTOID, &textDatums, NULL, &ndatums);
     239         [ -  + ]:           5 :         for (i = 0; i < ndatums; i++)
     240                 :             :         {
     241                 :           0 :             char       *reqExtName = TextDatumGetCString(textDatums[i]);
     242                 :           0 :             Oid         reqExtOid = get_extension_oid(reqExtName, false);
     243                 :             : 
     244                 :           0 :             requiredExtensions = lappend_oid(requiredExtensions, reqExtOid);
     245                 :             :         }
     246                 :             :     }
     247                 :             : 
     248                 :           5 :     InsertExtensionTuple(text_to_cstring(extName),
     249                 :             :                          GetUserId(),
     250                 :           5 :                          get_namespace_oid(text_to_cstring(schemaName), false),
     251                 :             :                          relocatable,
     252                 :           5 :                          text_to_cstring(extVersion),
     253                 :             :                          extConfig,
     254                 :             :                          extCondition,
     255                 :             :                          requiredExtensions);
     256                 :             : 
     257                 :           5 :     PG_RETURN_VOID();
     258                 :             : }
     259                 :             : 
     260                 :             : Datum
     261                 :           0 : binary_upgrade_set_record_init_privs(PG_FUNCTION_ARGS)
     262                 :             : {
     263                 :           0 :     bool        record_init_privs = PG_GETARG_BOOL(0);
     264                 :             : 
     265   [ #  #  #  # ]:           0 :     CHECK_IS_BINARY_UPGRADE;
     266                 :           0 :     binary_upgrade_record_init_privs = record_init_privs;
     267                 :             : 
     268                 :           0 :     PG_RETURN_VOID();
     269                 :             : }
     270                 :             : 
     271                 :             : Datum
     272                 :           3 : binary_upgrade_set_missing_value(PG_FUNCTION_ARGS)
     273                 :             : {
     274                 :           3 :     Oid         table_id = PG_GETARG_OID(0);
     275                 :           3 :     text       *attname = PG_GETARG_TEXT_P(1);
     276                 :           3 :     text       *value = PG_GETARG_TEXT_P(2);
     277                 :           3 :     char       *cattname = text_to_cstring(attname);
     278                 :           3 :     char       *cvalue = text_to_cstring(value);
     279                 :             : 
     280   [ -  +  -  - ]:           3 :     CHECK_IS_BINARY_UPGRADE;
     281                 :           3 :     SetAttrMissing(table_id, cattname, cvalue);
     282                 :             : 
     283                 :           3 :     PG_RETURN_VOID();
     284                 :             : }
     285                 :             : 
     286                 :             : /*
     287                 :             :  * Verify the given slot has already consumed all the WAL changes.
     288                 :             :  *
     289                 :             :  * Returns true if there are no decodable WAL records after the
     290                 :             :  * confirmed_flush_lsn. Otherwise false.
     291                 :             :  *
     292                 :             :  * This is a special purpose function to ensure that the given slot can be
     293                 :             :  * upgraded without data loss.
     294                 :             :  */
     295                 :             : Datum
     296                 :           4 : binary_upgrade_check_logical_slot_pending_wal(PG_FUNCTION_ARGS)
     297                 :             : {
     298                 :             :     Name        slot_name;
     299                 :             :     XLogRecPtr  end_of_wal;
     300                 :             :     XLogRecPtr  scan_cutoff_lsn;
     301                 :             :     XLogRecPtr  last_pending_wal;
     302                 :             : 
     303   [ -  +  -  - ]:           4 :     CHECK_IS_BINARY_UPGRADE;
     304                 :             : 
     305                 :             :     /*
     306                 :             :      * Binary upgrades only allowed super-user connections so we must have
     307                 :             :      * permission to use replication slots.
     308                 :             :      */
     309                 :             :     Assert(has_rolreplication(GetUserId()));
     310                 :             : 
     311                 :           4 :     slot_name = PG_GETARG_NAME(0);
     312                 :           4 :     scan_cutoff_lsn = PG_GETARG_LSN(1);
     313                 :             : 
     314                 :             :     /* Acquire the given slot */
     315                 :           4 :     ReplicationSlotAcquire(NameStr(*slot_name), true, true);
     316                 :             : 
     317                 :             :     Assert(SlotIsLogical(MyReplicationSlot));
     318                 :             : 
     319                 :             :     /* Slots must be valid as otherwise we won't be able to scan the WAL */
     320                 :             :     Assert(MyReplicationSlot->data.invalidated == RS_INVAL_NONE);
     321                 :             : 
     322                 :           4 :     end_of_wal = GetFlushRecPtr(NULL);
     323                 :           4 :     last_pending_wal = LogicalReplicationSlotCheckPendingWal(end_of_wal,
     324                 :             :                                                              scan_cutoff_lsn);
     325                 :             : 
     326                 :             :     /* Clean up */
     327                 :           4 :     ReplicationSlotRelease();
     328                 :             : 
     329         [ +  + ]:           4 :     if (XLogRecPtrIsValid(last_pending_wal))
     330                 :           1 :         PG_RETURN_LSN(last_pending_wal);
     331                 :             :     else
     332                 :           3 :         PG_RETURN_NULL();
     333                 :             : }
     334                 :             : 
     335                 :             : /*
     336                 :             :  * binary_upgrade_add_sub_rel_state
     337                 :             :  *
     338                 :             :  * Add the relation with the specified relation state to pg_subscription_rel
     339                 :             :  * catalog.
     340                 :             :  */
     341                 :             : Datum
     342                 :           3 : binary_upgrade_add_sub_rel_state(PG_FUNCTION_ARGS)
     343                 :             : {
     344                 :             :     Relation    subrel;
     345                 :             :     Relation    rel;
     346                 :             :     Oid         subid;
     347                 :             :     char       *subname;
     348                 :             :     Oid         relid;
     349                 :             :     char        relstate;
     350                 :             :     XLogRecPtr  sublsn;
     351                 :             : 
     352   [ -  +  -  - ]:           3 :     CHECK_IS_BINARY_UPGRADE;
     353                 :             : 
     354                 :             :     /* We must check these things before dereferencing the arguments */
     355   [ +  -  +  -  :           3 :     if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2))
                   -  + ]
     356         [ #  # ]:           0 :         elog(ERROR, "null argument to binary_upgrade_add_sub_rel_state is not allowed");
     357                 :             : 
     358                 :           3 :     subname = text_to_cstring(PG_GETARG_TEXT_PP(0));
     359                 :           3 :     relid = PG_GETARG_OID(1);
     360                 :           3 :     relstate = PG_GETARG_CHAR(2);
     361         [ +  + ]:           3 :     sublsn = PG_ARGISNULL(3) ? InvalidXLogRecPtr : PG_GETARG_LSN(3);
     362                 :             : 
     363                 :           3 :     subrel = table_open(SubscriptionRelationId, RowExclusiveLock);
     364                 :           3 :     subid = get_subscription_oid(subname, false);
     365                 :           3 :     rel = relation_open(relid, AccessShareLock);
     366                 :             : 
     367                 :             :     /*
     368                 :             :      * Since there are no concurrent ALTER/DROP SUBSCRIPTION commands during
     369                 :             :      * the upgrade process, and the apply worker (which builds cache based on
     370                 :             :      * the subscription catalog) is not running, the locks can be released
     371                 :             :      * immediately.
     372                 :             :      */
     373                 :           3 :     AddSubscriptionRelState(subid, relid, relstate, sublsn, false);
     374                 :           3 :     relation_close(rel, AccessShareLock);
     375                 :           3 :     table_close(subrel, RowExclusiveLock);
     376                 :             : 
     377                 :           3 :     PG_RETURN_VOID();
     378                 :             : }
     379                 :             : 
     380                 :             : /*
     381                 :             :  * binary_upgrade_replorigin_advance
     382                 :             :  *
     383                 :             :  * Update the remote_lsn for the subscriber's replication origin.
     384                 :             :  */
     385                 :             : Datum
     386                 :           1 : binary_upgrade_replorigin_advance(PG_FUNCTION_ARGS)
     387                 :             : {
     388                 :             :     Relation    rel;
     389                 :             :     Oid         subid;
     390                 :             :     char       *subname;
     391                 :             :     char        originname[NAMEDATALEN];
     392                 :             :     ReplOriginId node;
     393                 :             :     XLogRecPtr  remote_commit;
     394                 :             : 
     395   [ -  +  -  - ]:           1 :     CHECK_IS_BINARY_UPGRADE;
     396                 :             : 
     397                 :             :     /*
     398                 :             :      * We must ensure a non-NULL subscription name before dereferencing the
     399                 :             :      * arguments.
     400                 :             :      */
     401         [ -  + ]:           1 :     if (PG_ARGISNULL(0))
     402         [ #  # ]:           0 :         elog(ERROR, "null argument to binary_upgrade_replorigin_advance is not allowed");
     403                 :             : 
     404                 :           1 :     subname = text_to_cstring(PG_GETARG_TEXT_PP(0));
     405         [ +  - ]:           1 :     remote_commit = PG_ARGISNULL(1) ? InvalidXLogRecPtr : PG_GETARG_LSN(1);
     406                 :             : 
     407                 :           1 :     rel = table_open(SubscriptionRelationId, RowExclusiveLock);
     408                 :           1 :     subid = get_subscription_oid(subname, false);
     409                 :             : 
     410                 :           1 :     ReplicationOriginNameForLogicalRep(subid, InvalidOid, originname, sizeof(originname));
     411                 :             : 
     412                 :             :     /* Lock to prevent the replication origin from vanishing */
     413                 :           1 :     LockRelationOid(ReplicationOriginRelationId, RowExclusiveLock);
     414                 :           1 :     node = replorigin_by_name(originname, false);
     415                 :             : 
     416                 :             :     /*
     417                 :             :      * The server will be stopped after setting up the objects in the new
     418                 :             :      * cluster and the origins will be flushed during the shutdown checkpoint.
     419                 :             :      * This will ensure that the latest LSN values for origin will be
     420                 :             :      * available after the upgrade.
     421                 :             :      */
     422                 :           1 :     replorigin_advance(node, remote_commit, InvalidXLogRecPtr,
     423                 :             :                        false /* backward */ ,
     424                 :             :                        false /* WAL log */ );
     425                 :             : 
     426                 :           1 :     UnlockRelationOid(ReplicationOriginRelationId, RowExclusiveLock);
     427                 :           1 :     table_close(rel, RowExclusiveLock);
     428                 :             : 
     429                 :           1 :     PG_RETURN_VOID();
     430                 :             : }
     431                 :             : 
     432                 :             : /*
     433                 :             :  * binary_upgrade_create_conflict_detection_slot
     434                 :             :  *
     435                 :             :  * Create a replication slot to retain information necessary for conflict
     436                 :             :  * detection such as dead tuples, commit timestamps, and origins.
     437                 :             :  */
     438                 :             : Datum
     439                 :           1 : binary_upgrade_create_conflict_detection_slot(PG_FUNCTION_ARGS)
     440                 :             : {
     441   [ -  +  -  - ]:           1 :     CHECK_IS_BINARY_UPGRADE;
     442                 :             : 
     443                 :           1 :     CreateConflictDetectionSlot();
     444                 :             : 
     445                 :           1 :     ReplicationSlotRelease();
     446                 :             : 
     447                 :           1 :     PG_RETURN_VOID();
     448                 :             : }
        

Generated by: LCOV version 2.0-1