PostgreSQL Source Code git master
pg_upgrade_support.c
Go to the documentation of this file.
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-2025, 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"
17#include "catalog/heap.h"
18#include "catalog/namespace.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"
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 \
34do { \
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
43{
44 Oid tbspoid = PG_GETARG_OID(0);
45
48
50}
51
54{
55 Oid typoid = PG_GETARG_OID(0);
56
59
61}
62
65{
66 Oid typoid = PG_GETARG_OID(0);
67
70
72}
73
76{
77 Oid typoid = PG_GETARG_OID(0);
78
81
83}
84
87{
88 Oid typoid = PG_GETARG_OID(0);
89
92
94}
95
98{
99 Oid reloid = PG_GETARG_OID(0);
100
103
105}
106
107Datum
109{
110 RelFileNumber relfilenumber = PG_GETARG_OID(0);
111
114
116}
117
118Datum
120{
121 Oid reloid = PG_GETARG_OID(0);
122
125
127}
128
129Datum
131{
132 RelFileNumber relfilenumber = PG_GETARG_OID(0);
133
136
138}
139
140Datum
142{
143 Oid reloid = PG_GETARG_OID(0);
144
147
149}
150
151Datum
153{
154 RelFileNumber relfilenumber = PG_GETARG_OID(0);
155
158
160}
161
162Datum
164{
165 Oid enumoid = PG_GETARG_OID(0);
166
169
171}
172
173Datum
175{
176 Oid authoid = PG_GETARG_OID(0);
177
181}
182
183Datum
185{
186 text *extName;
187 text *schemaName;
188 bool relocatable;
189 text *extVersion;
190 Datum extConfig;
191 Datum extCondition;
192 List *requiredExtensions;
193
195
196 /* We must check these things before dereferencing the arguments */
197 if (PG_ARGISNULL(0) ||
198 PG_ARGISNULL(1) ||
199 PG_ARGISNULL(2) ||
200 PG_ARGISNULL(3))
201 elog(ERROR, "null argument to binary_upgrade_create_empty_extension is not allowed");
202
203 extName = PG_GETARG_TEXT_PP(0);
204 schemaName = PG_GETARG_TEXT_PP(1);
205 relocatable = PG_GETARG_BOOL(2);
206 extVersion = PG_GETARG_TEXT_PP(3);
207
208 if (PG_ARGISNULL(4))
209 extConfig = PointerGetDatum(NULL);
210 else
211 extConfig = PG_GETARG_DATUM(4);
212
213 if (PG_ARGISNULL(5))
214 extCondition = PointerGetDatum(NULL);
215 else
216 extCondition = PG_GETARG_DATUM(5);
217
218 requiredExtensions = NIL;
219 if (!PG_ARGISNULL(6))
220 {
221 ArrayType *textArray = PG_GETARG_ARRAYTYPE_P(6);
222 Datum *textDatums;
223 int ndatums;
224 int i;
225
226 deconstruct_array_builtin(textArray, TEXTOID, &textDatums, NULL, &ndatums);
227 for (i = 0; i < ndatums; i++)
228 {
229 char *extName = TextDatumGetCString(textDatums[i]);
230 Oid extOid = get_extension_oid(extName, false);
231
232 requiredExtensions = lappend_oid(requiredExtensions, extOid);
233 }
234 }
235
237 GetUserId(),
238 get_namespace_oid(text_to_cstring(schemaName), false),
239 relocatable,
240 text_to_cstring(extVersion),
241 extConfig,
242 extCondition,
243 requiredExtensions);
244
246}
247
248Datum
250{
251 bool record_init_privs = PG_GETARG_BOOL(0);
252
254 binary_upgrade_record_init_privs = record_init_privs;
255
257}
258
259Datum
261{
262 Oid table_id = PG_GETARG_OID(0);
265 char *cattname = text_to_cstring(attname);
266 char *cvalue = text_to_cstring(value);
267
269 SetAttrMissing(table_id, cattname, cvalue);
270
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 */
283Datum
285{
286 Name slot_name;
287 XLogRecPtr end_of_wal;
288 bool found_pending_wal;
289
291
292 /*
293 * Binary upgrades only allowed super-user connections so we must have
294 * permission to use replication slots.
295 */
297
298 slot_name = PG_GETARG_NAME(0);
299
300 /* Acquire the given slot */
301 ReplicationSlotAcquire(NameStr(*slot_name), true, true);
302
304
305 /* Slots must be valid as otherwise we won't be able to scan the WAL */
307
308 end_of_wal = GetFlushRecPtr(NULL);
309 found_pending_wal = LogicalReplicationSlotHasPendingWal(end_of_wal);
310
311 /* Clean up */
313
314 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 */
323Datum
325{
326 Relation subrel;
327 Relation rel;
328 Oid subid;
329 char *subname;
330 Oid relid;
331 char relstate;
332 XLogRecPtr sublsn;
333
335
336 /* We must check these things before dereferencing the arguments */
337 if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2))
338 elog(ERROR, "null argument to binary_upgrade_add_sub_rel_state is not allowed");
339
341 relid = PG_GETARG_OID(1);
342 relstate = PG_GETARG_CHAR(2);
344
345 subrel = table_open(SubscriptionRelationId, RowExclusiveLock);
346 subid = get_subscription_oid(subname, false);
347 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 AddSubscriptionRelState(subid, relid, relstate, sublsn, false);
358
360}
361
362/*
363 * binary_upgrade_replorigin_advance
364 *
365 * Update the remote_lsn for the subscriber's replication origin.
366 */
367Datum
369{
370 Relation rel;
371 Oid subid;
372 char *subname;
373 char originname[NAMEDATALEN];
374 RepOriginId node;
375 XLogRecPtr remote_commit;
376
378
379 /*
380 * We must ensure a non-NULL subscription name before dereferencing the
381 * arguments.
382 */
383 if (PG_ARGISNULL(0))
384 elog(ERROR, "null argument to binary_upgrade_replorigin_advance is not allowed");
385
387 remote_commit = PG_ARGISNULL(1) ? InvalidXLogRecPtr : PG_GETARG_LSN(1);
388
389 rel = table_open(SubscriptionRelationId, RowExclusiveLock);
390 subid = get_subscription_oid(subname, false);
391
392 ReplicationOriginNameForLogicalRep(subid, InvalidOid, originname, sizeof(originname));
393
394 /* Lock to prevent the replication origin from vanishing */
395 LockRelationOid(ReplicationOriginRelationId, RowExclusiveLock);
396 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 replorigin_advance(node, remote_commit, InvalidXLogRecPtr,
405 false /* backward */ ,
406 false /* WAL log */ );
407
408 UnlockRelationOid(ReplicationOriginRelationId, RowExclusiveLock);
410
412}
bool binary_upgrade_record_init_privs
Definition: aclchk.c:110
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3697
Oid binary_upgrade_next_pg_tablespace_oid
Definition: tablespace.c:87
void ReplicationOriginNameForLogicalRep(Oid suboid, Oid relid, char *originname, Size szoriginname)
Definition: worker.c:426
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:703
#define Assert(condition)
Definition: c.h:815
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
ObjectAddress InsertExtensionTuple(const char *extName, Oid extOwner, Oid schemaOid, bool relocatable, const char *extVersion, Datum extConfig, Datum extCondition, List *requiredExtensions)
Definition: extension.c:1977
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition: extension.c:158
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_GETARG_CHAR(n)
Definition: fmgr.h:273
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_GETARG_NAME(n)
Definition: fmgr.h:278
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
#define PG_GETARG_TEXT_P(n)
Definition: fmgr.h:336
void SetAttrMissing(Oid relid, char *attname, char *value)
Definition: heap.c:2019
RelFileNumber binary_upgrade_next_heap_pg_class_relfilenumber
Definition: heap.c:82
RelFileNumber binary_upgrade_next_toast_pg_class_relfilenumber
Definition: heap.c:83
Oid binary_upgrade_next_toast_pg_class_oid
Definition: heap.c:81
Oid binary_upgrade_next_heap_pg_class_oid
Definition: heap.c:80
RelFileNumber binary_upgrade_next_index_pg_class_relfilenumber
Definition: index.c:85
Oid binary_upgrade_next_index_pg_class_oid
Definition: index.c:84
static struct @162 value
int i
Definition: isn.c:72
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:226
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:107
#define AccessShareLock
Definition: lockdefs.h:36
#define RowExclusiveLock
Definition: lockdefs.h:38
bool LogicalReplicationSlotHasPendingWal(XLogRecPtr end_of_wal)
Definition: logical.c:1962
Oid get_subscription_oid(const char *subname, bool missing_ok)
Definition: lsyscache.c:3702
Oid GetUserId(void)
Definition: miscinit.c:517
bool has_rolreplication(Oid roleid)
Definition: miscinit.c:736
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition: namespace.c:3535
RepOriginId replorigin_by_name(const char *roname, bool missing_ok)
Definition: origin.c:225
void replorigin_advance(RepOriginId node, XLogRecPtr remote_commit, XLogRecPtr local_commit, bool go_backward, bool wal_log)
Definition: origin.c:892
NameData attname
Definition: pg_attribute.h:41
#define NAMEDATALEN
Oid binary_upgrade_next_pg_enum_oid
Definition: pg_enum.c:36
#define NIL
Definition: pg_list.h:68
#define PG_GETARG_LSN(n)
Definition: pg_lsn.h:33
void AddSubscriptionRelState(Oid subid, Oid relid, char state, XLogRecPtr sublsn, bool retain_lock)
NameData subname
Oid binary_upgrade_next_pg_type_oid
Definition: pg_type.c:41
Datum binary_upgrade_set_next_heap_pg_class_oid(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_next_multirange_pg_type_oid(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_next_pg_enum_oid(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_next_index_pg_class_oid(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_next_array_pg_type_oid(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_next_toast_relfilenode(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_next_pg_authid_oid(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_record_init_privs(PG_FUNCTION_ARGS)
#define CHECK_IS_BINARY_UPGRADE
Datum binary_upgrade_add_sub_rel_state(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_next_multirange_array_pg_type_oid(PG_FUNCTION_ARGS)
Datum binary_upgrade_logical_slot_has_caught_up(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_next_pg_tablespace_oid(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_next_heap_relfilenode(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_next_index_relfilenode(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_missing_value(PG_FUNCTION_ARGS)
Datum binary_upgrade_create_empty_extension(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_next_pg_type_oid(PG_FUNCTION_ARGS)
Datum binary_upgrade_replorigin_advance(PG_FUNCTION_ARGS)
Datum binary_upgrade_set_next_toast_pg_class_oid(PG_FUNCTION_ARGS)
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
Oid RelFileNumber
Definition: relpath.h:25
void ReplicationSlotAcquire(const char *name, bool nowait, bool error_if_invalid)
Definition: slot.c:544
ReplicationSlot * MyReplicationSlot
Definition: slot.c:138
void ReplicationSlotRelease(void)
Definition: slot.c:667
@ RS_INVAL_NONE
Definition: slot.h:52
#define SlotIsLogical(slot)
Definition: slot.h:217
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:47
Definition: pg_list.h:54
ReplicationSlotInvalidationCause invalidated
Definition: slot.h:99
ReplicationSlotPersistentData data
Definition: slot.h:181
Definition: c.h:698
Definition: c.h:644
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
Oid binary_upgrade_next_mrng_array_pg_type_oid
Definition: typecmds.c:111
Oid binary_upgrade_next_mrng_pg_type_oid
Definition: typecmds.c:110
Oid binary_upgrade_next_array_pg_type_oid
Definition: typecmds.c:109
Oid binary_upgrade_next_pg_authid_oid
Definition: user.c:70
char * text_to_cstring(const text *t)
Definition: varlena.c:217
XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI)
Definition: xlog.c:6520
uint16 RepOriginId
Definition: xlogdefs.h:65
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28