LCOV - code coverage report
Current view: top level - src/backend/utils/adt - pg_upgrade_support.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 206 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 20 0
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 0.0 % 156 0

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

Generated by: LCOV version 2.3.2-1