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

Generated by: LCOV version 1.14