LCOV - code coverage report
Current view: top level - src/backend/utils/adt - pg_upgrade_support.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 105 146 71.9 %
Date: 2024-04-25 03:11:44 Functions: 16 19 84.2 %
Legend: Lines: hit not hit

          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-2024, 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/origin.h"
      25             : #include "replication/worker_internal.h"
      26             : #include "storage/lmgr.h"
      27             : #include "utils/array.h"
      28             : #include "utils/builtins.h"
      29             : #include "utils/lsyscache.h"
      30             : #include "utils/pg_lsn.h"
      31             : #include "utils/syscache.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             : }
      52             : 
      53             : Datum
      54        1536 : binary_upgrade_set_next_pg_type_oid(PG_FUNCTION_ARGS)
      55             : {
      56        1536 :     Oid         typoid = PG_GETARG_OID(0);
      57             : 
      58        1536 :     CHECK_IS_BINARY_UPGRADE;
      59        1536 :     binary_upgrade_next_pg_type_oid = typoid;
      60             : 
      61        1536 :     PG_RETURN_VOID();
      62             : }
      63             : 
      64             : Datum
      65        1534 : binary_upgrade_set_next_array_pg_type_oid(PG_FUNCTION_ARGS)
      66             : {
      67        1534 :     Oid         typoid = PG_GETARG_OID(0);
      68             : 
      69        1534 :     CHECK_IS_BINARY_UPGRADE;
      70        1534 :     binary_upgrade_next_array_pg_type_oid = typoid;
      71             : 
      72        1534 :     PG_RETURN_VOID();
      73             : }
      74             : 
      75             : Datum
      76           8 : binary_upgrade_set_next_multirange_pg_type_oid(PG_FUNCTION_ARGS)
      77             : {
      78           8 :     Oid         typoid = PG_GETARG_OID(0);
      79             : 
      80           8 :     CHECK_IS_BINARY_UPGRADE;
      81           8 :     binary_upgrade_next_mrng_pg_type_oid = typoid;
      82             : 
      83           8 :     PG_RETURN_VOID();
      84             : }
      85             : 
      86             : Datum
      87           8 : binary_upgrade_set_next_multirange_array_pg_type_oid(PG_FUNCTION_ARGS)
      88             : {
      89           8 :     Oid         typoid = PG_GETARG_OID(0);
      90             : 
      91           8 :     CHECK_IS_BINARY_UPGRADE;
      92           8 :     binary_upgrade_next_mrng_array_pg_type_oid = typoid;
      93             : 
      94           8 :     PG_RETURN_VOID();
      95             : }
      96             : 
      97             : Datum
      98        1554 : binary_upgrade_set_next_heap_pg_class_oid(PG_FUNCTION_ARGS)
      99             : {
     100        1554 :     Oid         reloid = PG_GETARG_OID(0);
     101             : 
     102        1554 :     CHECK_IS_BINARY_UPGRADE;
     103        1554 :     binary_upgrade_next_heap_pg_class_oid = reloid;
     104             : 
     105        1554 :     PG_RETURN_VOID();
     106             : }
     107             : 
     108             : Datum
     109        1288 : binary_upgrade_set_next_heap_relfilenode(PG_FUNCTION_ARGS)
     110             : {
     111        1288 :     RelFileNumber relfilenumber = PG_GETARG_OID(0);
     112             : 
     113        1288 :     CHECK_IS_BINARY_UPGRADE;
     114        1288 :     binary_upgrade_next_heap_pg_class_relfilenumber = relfilenumber;
     115             : 
     116        1288 :     PG_RETURN_VOID();
     117             : }
     118             : 
     119             : Datum
     120        1050 : binary_upgrade_set_next_index_pg_class_oid(PG_FUNCTION_ARGS)
     121             : {
     122        1050 :     Oid         reloid = PG_GETARG_OID(0);
     123             : 
     124        1050 :     CHECK_IS_BINARY_UPGRADE;
     125        1050 :     binary_upgrade_next_index_pg_class_oid = reloid;
     126             : 
     127        1050 :     PG_RETURN_VOID();
     128             : }
     129             : 
     130             : Datum
     131        1070 : binary_upgrade_set_next_index_relfilenode(PG_FUNCTION_ARGS)
     132             : {
     133        1070 :     RelFileNumber relfilenumber = PG_GETARG_OID(0);
     134             : 
     135        1070 :     CHECK_IS_BINARY_UPGRADE;
     136        1070 :     binary_upgrade_next_index_pg_class_relfilenumber = relfilenumber;
     137             : 
     138        1070 :     PG_RETURN_VOID();
     139             : }
     140             : 
     141             : Datum
     142         524 : binary_upgrade_set_next_toast_pg_class_oid(PG_FUNCTION_ARGS)
     143             : {
     144         524 :     Oid         reloid = PG_GETARG_OID(0);
     145             : 
     146         524 :     CHECK_IS_BINARY_UPGRADE;
     147         524 :     binary_upgrade_next_toast_pg_class_oid = reloid;
     148             : 
     149         524 :     PG_RETURN_VOID();
     150             : }
     151             : 
     152             : Datum
     153         524 : binary_upgrade_set_next_toast_relfilenode(PG_FUNCTION_ARGS)
     154             : {
     155         524 :     RelFileNumber relfilenumber = PG_GETARG_OID(0);
     156             : 
     157         524 :     CHECK_IS_BINARY_UPGRADE;
     158         524 :     binary_upgrade_next_toast_pg_class_relfilenumber = relfilenumber;
     159             : 
     160         524 :     PG_RETURN_VOID();
     161             : }
     162             : 
     163             : Datum
     164         100 : binary_upgrade_set_next_pg_enum_oid(PG_FUNCTION_ARGS)
     165             : {
     166         100 :     Oid         enumoid = PG_GETARG_OID(0);
     167             : 
     168         100 :     CHECK_IS_BINARY_UPGRADE;
     169         100 :     binary_upgrade_next_pg_enum_oid = enumoid;
     170             : 
     171         100 :     PG_RETURN_VOID();
     172             : }
     173             : 
     174             : Datum
     175           6 : binary_upgrade_set_next_pg_authid_oid(PG_FUNCTION_ARGS)
     176             : {
     177           6 :     Oid         authoid = PG_GETARG_OID(0);
     178             : 
     179           6 :     CHECK_IS_BINARY_UPGRADE;
     180           6 :     binary_upgrade_next_pg_authid_oid = authoid;
     181           6 :     PG_RETURN_VOID();
     182             : }
     183             : 
     184             : Datum
     185           0 : binary_upgrade_create_empty_extension(PG_FUNCTION_ARGS)
     186             : {
     187             :     text       *extName;
     188             :     text       *schemaName;
     189             :     bool        relocatable;
     190             :     text       *extVersion;
     191             :     Datum       extConfig;
     192             :     Datum       extCondition;
     193             :     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             :         Datum      *textDatums;
     224             :         int         ndatums;
     225             :         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             :         }
     235             :     }
     236             : 
     237           0 :     InsertExtensionTuple(text_to_cstring(extName),
     238             :                          GetUserId(),
     239           0 :                          get_namespace_oid(text_to_cstring(schemaName), false),
     240             :                          relocatable,
     241           0 :                          text_to_cstring(extVersion),
     242             :                          extConfig,
     243             :                          extCondition,
     244             :                          requiredExtensions);
     245             : 
     246           0 :     PG_RETURN_VOID();
     247             : }
     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             : }
     259             : 
     260             : Datum
     261           4 : binary_upgrade_set_missing_value(PG_FUNCTION_ARGS)
     262             : {
     263           4 :     Oid         table_id = PG_GETARG_OID(0);
     264           4 :     text       *attname = PG_GETARG_TEXT_P(1);
     265           4 :     text       *value = PG_GETARG_TEXT_P(2);
     266           4 :     char       *cattname = text_to_cstring(attname);
     267           4 :     char       *cvalue = text_to_cstring(value);
     268             : 
     269           4 :     CHECK_IS_BINARY_UPGRADE;
     270           4 :     SetAttrMissing(table_id, cattname, cvalue);
     271             : 
     272           4 :     PG_RETURN_VOID();
     273             : }
     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          10 : binary_upgrade_logical_slot_has_caught_up(PG_FUNCTION_ARGS)
     286             : {
     287             :     Name        slot_name;
     288             :     XLogRecPtr  end_of_wal;
     289             :     bool        found_pending_wal;
     290             : 
     291          10 :     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             :     Assert(has_rolreplication(GetUserId()));
     298             : 
     299          10 :     slot_name = PG_GETARG_NAME(0);
     300             : 
     301             :     /* Acquire the given slot */
     302          10 :     ReplicationSlotAcquire(NameStr(*slot_name), true);
     303             : 
     304             :     Assert(SlotIsLogical(MyReplicationSlot));
     305             : 
     306             :     /* Slots must be valid as otherwise we won't be able to scan the WAL */
     307             :     Assert(MyReplicationSlot->data.invalidated == RS_INVAL_NONE);
     308             : 
     309          10 :     end_of_wal = GetFlushRecPtr(NULL);
     310          10 :     found_pending_wal = LogicalReplicationSlotHasPendingWal(end_of_wal);
     311             : 
     312             :     /* Clean up */
     313          10 :     ReplicationSlotRelease();
     314             : 
     315          10 :     PG_RETURN_BOOL(!found_pending_wal);
     316             : }
     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           4 : binary_upgrade_add_sub_rel_state(PG_FUNCTION_ARGS)
     326             : {
     327             :     Relation    subrel;
     328             :     Relation    rel;
     329             :     Oid         subid;
     330             :     char       *subname;
     331             :     Oid         relid;
     332             :     char        relstate;
     333             :     XLogRecPtr  sublsn;
     334             : 
     335           4 :     CHECK_IS_BINARY_UPGRADE;
     336             : 
     337             :     /* We must check these things before dereferencing the arguments */
     338           4 :     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           4 :     subname = text_to_cstring(PG_GETARG_TEXT_PP(0));
     342           4 :     relid = PG_GETARG_OID(1);
     343           4 :     relstate = PG_GETARG_CHAR(2);
     344           4 :     sublsn = PG_ARGISNULL(3) ? InvalidXLogRecPtr : PG_GETARG_LSN(3);
     345             : 
     346           4 :     subrel = table_open(SubscriptionRelationId, RowExclusiveLock);
     347           4 :     subid = get_subscription_oid(subname, false);
     348           4 :     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           4 :     AddSubscriptionRelState(subid, relid, relstate, sublsn, false);
     357           4 :     relation_close(rel, AccessShareLock);
     358           4 :     table_close(subrel, RowExclusiveLock);
     359             : 
     360           4 :     PG_RETURN_VOID();
     361             : }
     362             : 
     363             : /*
     364             :  * binary_upgrade_replorigin_advance
     365             :  *
     366             :  * Update the remote_lsn for the subscriber's replication origin.
     367             :  */
     368             : Datum
     369           2 : binary_upgrade_replorigin_advance(PG_FUNCTION_ARGS)
     370             : {
     371             :     Relation    rel;
     372             :     Oid         subid;
     373             :     char       *subname;
     374             :     char        originname[NAMEDATALEN];
     375             :     RepOriginId node;
     376             :     XLogRecPtr  remote_commit;
     377             : 
     378           2 :     CHECK_IS_BINARY_UPGRADE;
     379             : 
     380             :     /*
     381             :      * We must ensure a non-NULL subscription name before dereferencing the
     382             :      * arguments.
     383             :      */
     384           2 :     if (PG_ARGISNULL(0))
     385           0 :         elog(ERROR, "null argument to binary_upgrade_replorigin_advance is not allowed");
     386             : 
     387           2 :     subname = text_to_cstring(PG_GETARG_TEXT_PP(0));
     388           2 :     remote_commit = PG_ARGISNULL(1) ? InvalidXLogRecPtr : PG_GETARG_LSN(1);
     389             : 
     390           2 :     rel = table_open(SubscriptionRelationId, RowExclusiveLock);
     391           2 :     subid = get_subscription_oid(subname, false);
     392             : 
     393           2 :     ReplicationOriginNameForLogicalRep(subid, InvalidOid, originname, sizeof(originname));
     394             : 
     395             :     /* Lock to prevent the replication origin from vanishing */
     396           2 :     LockRelationOid(ReplicationOriginRelationId, RowExclusiveLock);
     397           2 :     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           2 :     replorigin_advance(node, remote_commit, InvalidXLogRecPtr,
     406             :                        false /* backward */ ,
     407             :                        false /* WAL log */ );
     408             : 
     409           2 :     UnlockRelationOid(ReplicationOriginRelationId, RowExclusiveLock);
     410           2 :     table_close(rel, RowExclusiveLock);
     411             : 
     412           2 :     PG_RETURN_VOID();
     413             : }

Generated by: LCOV version 1.14