Age Owner Branch data TLA 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
1707 rhaas@postgresql.org 43 :CBC 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
4212 peter_e@gmx.net 54 : 896 : binary_upgrade_set_next_pg_type_oid(PG_FUNCTION_ARGS)
55 : : {
5975 bruce@momjian.us 56 : 896 : Oid typoid = PG_GETARG_OID(0);
57 : :
4409 58 [ - + - - ]: 896 : CHECK_IS_BINARY_UPGRADE;
5975 59 : 896 : binary_upgrade_next_pg_type_oid = typoid;
60 : :
61 : 896 : PG_RETURN_VOID();
62 : : }
63 : :
64 : : Datum
4212 peter_e@gmx.net 65 : 895 : binary_upgrade_set_next_array_pg_type_oid(PG_FUNCTION_ARGS)
66 : : {
5975 bruce@momjian.us 67 : 895 : Oid typoid = PG_GETARG_OID(0);
68 : :
4409 69 [ - + - - ]: 895 : CHECK_IS_BINARY_UPGRADE;
5735 70 : 895 : binary_upgrade_next_array_pg_type_oid = typoid;
71 : :
5975 72 : 895 : PG_RETURN_VOID();
73 : : }
74 : :
75 : : Datum
2100 akorotkov@postgresql 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
4212 peter_e@gmx.net 98 : 901 : binary_upgrade_set_next_heap_pg_class_oid(PG_FUNCTION_ARGS)
99 : : {
5735 bruce@momjian.us 100 : 901 : Oid reloid = PG_GETARG_OID(0);
101 : :
4409 102 [ - + - - ]: 901 : CHECK_IS_BINARY_UPGRADE;
5735 103 : 901 : binary_upgrade_next_heap_pg_class_oid = reloid;
104 : :
5975 105 : 901 : PG_RETURN_VOID();
106 : : }
107 : :
108 : : Datum
1707 rhaas@postgresql.org 109 : 805 : binary_upgrade_set_next_heap_relfilenode(PG_FUNCTION_ARGS)
110 : : {
1453 111 : 805 : RelFileNumber relfilenumber = PG_GETARG_OID(0);
112 : :
1707 113 [ - + - - ]: 805 : CHECK_IS_BINARY_UPGRADE;
1537 114 : 805 : binary_upgrade_next_heap_pg_class_relfilenumber = relfilenumber;
115 : :
1707 116 : 805 : PG_RETURN_VOID();
117 : : }
118 : :
119 : : Datum
4212 peter_e@gmx.net 120 : 581 : binary_upgrade_set_next_index_pg_class_oid(PG_FUNCTION_ARGS)
121 : : {
5735 bruce@momjian.us 122 : 581 : Oid reloid = PG_GETARG_OID(0);
123 : :
4409 124 [ - + - - ]: 581 : CHECK_IS_BINARY_UPGRADE;
5735 125 : 581 : binary_upgrade_next_index_pg_class_oid = reloid;
126 : :
5975 127 : 581 : PG_RETURN_VOID();
128 : : }
129 : :
130 : : Datum
1707 rhaas@postgresql.org 131 : 645 : binary_upgrade_set_next_index_relfilenode(PG_FUNCTION_ARGS)
132 : : {
1453 133 : 645 : RelFileNumber relfilenumber = PG_GETARG_OID(0);
134 : :
1707 135 [ - + - - ]: 645 : CHECK_IS_BINARY_UPGRADE;
1537 136 : 645 : binary_upgrade_next_index_pg_class_relfilenumber = relfilenumber;
137 : :
1707 138 : 645 : PG_RETURN_VOID();
139 : : }
140 : :
141 : : Datum
4212 peter_e@gmx.net 142 : 278 : binary_upgrade_set_next_toast_pg_class_oid(PG_FUNCTION_ARGS)
143 : : {
5735 bruce@momjian.us 144 : 278 : Oid reloid = PG_GETARG_OID(0);
145 : :
4409 146 [ - + - - ]: 278 : CHECK_IS_BINARY_UPGRADE;
5735 147 : 278 : binary_upgrade_next_toast_pg_class_oid = reloid;
148 : :
5975 149 : 278 : PG_RETURN_VOID();
150 : : }
151 : :
152 : : Datum
9 michael@paquier.xyz 153 :GNC 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
1707 rhaas@postgresql.org 164 :CBC 278 : binary_upgrade_set_next_toast_relfilenode(PG_FUNCTION_ARGS)
165 : : {
1453 166 : 278 : RelFileNumber relfilenumber = PG_GETARG_OID(0);
167 : :
1707 168 [ - + - - ]: 278 : CHECK_IS_BINARY_UPGRADE;
1537 169 : 278 : binary_upgrade_next_toast_pg_class_relfilenumber = relfilenumber;
170 : :
1707 171 : 278 : PG_RETURN_VOID();
172 : : }
173 : :
174 : : Datum
4212 peter_e@gmx.net 175 : 50 : binary_upgrade_set_next_pg_enum_oid(PG_FUNCTION_ARGS)
176 : : {
5975 bruce@momjian.us 177 : 50 : Oid enumoid = PG_GETARG_OID(0);
178 : :
4409 179 [ - + - - ]: 50 : CHECK_IS_BINARY_UPGRADE;
5810 tgl@sss.pgh.pa.us 180 : 50 : binary_upgrade_next_pg_enum_oid = enumoid;
181 : :
5975 bruce@momjian.us 182 : 50 : PG_RETURN_VOID();
183 : : }
184 : :
185 : : Datum
4212 peter_e@gmx.net 186 : 18 : binary_upgrade_set_next_pg_authid_oid(PG_FUNCTION_ARGS)
187 : : {
5735 bruce@momjian.us 188 : 18 : Oid authoid = PG_GETARG_OID(0);
189 : :
4409 190 [ - + - - ]: 18 : CHECK_IS_BINARY_UPGRADE;
5735 191 : 18 : binary_upgrade_next_pg_authid_oid = authoid;
192 : 18 : PG_RETURN_VOID();
193 : : }
194 : :
195 : : Datum
4212 peter_e@gmx.net 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 : :
4409 bruce@momjian.us 206 [ - + - - ]: 5 : CHECK_IS_BINARY_UPGRADE;
207 : :
208 : : /* We must check these things before dereferencing the arguments */
3913 tgl@sss.pgh.pa.us 209 [ + - ]: 5 : if (PG_ARGISNULL(0) ||
210 [ + - ]: 5 : PG_ARGISNULL(1) ||
211 [ + - ]: 5 : PG_ARGISNULL(2) ||
212 [ - + ]: 5 : PG_ARGISNULL(3))
3913 tgl@sss.pgh.pa.us 213 [ # # ]:UBC 0 : elog(ERROR, "null argument to binary_upgrade_create_empty_extension is not allowed");
214 : :
3913 tgl@sss.pgh.pa.us 215 :CBC 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 : :
5702 220 [ + - ]: 5 : if (PG_ARGISNULL(4))
221 : 5 : extConfig = PointerGetDatum(NULL);
222 : : else
5702 tgl@sss.pgh.pa.us 223 :UBC 0 : extConfig = PG_GETARG_DATUM(4);
224 : :
5702 tgl@sss.pgh.pa.us 225 [ + - ]:CBC 5 : if (PG_ARGISNULL(5))
226 : 5 : extCondition = PointerGetDatum(NULL);
227 : : else
5702 tgl@sss.pgh.pa.us 228 :UBC 0 : extCondition = PG_GETARG_DATUM(5);
229 : :
5702 tgl@sss.pgh.pa.us 230 :CBC 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 : :
1542 peter@eisentraut.org 238 : 5 : deconstruct_array_builtin(textArray, TEXTOID, &textDatums, NULL, &ndatums);
5702 tgl@sss.pgh.pa.us 239 [ - + ]: 5 : for (i = 0; i < ndatums; i++)
240 : : {
12 peter@eisentraut.org 241 :UNC 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 : :
5702 tgl@sss.pgh.pa.us 248 :CBC 5 : InsertExtensionTuple(text_to_cstring(extName),
249 : : GetUserId(),
3378 250 : 5 : get_namespace_oid(text_to_cstring(schemaName), false),
251 : : relocatable,
5700 252 : 5 : text_to_cstring(extVersion),
253 : : extConfig,
254 : : extCondition,
255 : : requiredExtensions);
256 : :
5702 257 : 5 : PG_RETURN_VOID();
258 : : }
259 : :
260 : : Datum
3819 sfrost@snowman.net 261 :UBC 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
3012 andrew@dunslane.net 272 :CBC 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
228 msawada@postgresql.o 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 : :
1060 akapila@postgresql.o 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 : : */
1018 309 [ - + ]: 4 : Assert(has_rolreplication(GetUserId()));
310 : :
1060 311 : 4 : slot_name = PG_GETARG_NAME(0);
228 msawada@postgresql.o 312 : 4 : scan_cutoff_lsn = PG_GETARG_LSN(1);
313 : :
314 : : /* Acquire the given slot */
597 akapila@postgresql.o 315 : 4 : ReplicationSlotAcquire(NameStr(*slot_name), true, true);
316 : :
1060 317 [ - + ]: 4 : Assert(SlotIsLogical(MyReplicationSlot));
318 : :
319 : : /* Slots must be valid as otherwise we won't be able to scan the WAL */
320 [ - + ]: 4 : Assert(MyReplicationSlot->data.invalidated == RS_INVAL_NONE);
321 : :
322 : 4 : end_of_wal = GetFlushRecPtr(NULL);
228 msawada@postgresql.o 323 : 4 : last_pending_wal = LogicalReplicationSlotCheckPendingWal(end_of_wal,
324 : : scan_cutoff_lsn);
325 : :
326 : : /* Clean up */
1060 akapila@postgresql.o 327 : 4 : ReplicationSlotRelease();
328 : :
228 msawada@postgresql.o 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
992 akapila@postgresql.o 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))
- + ]
992 akapila@postgresql.o 356 [ # # ]:UBC 0 : elog(ERROR, "null argument to binary_upgrade_add_sub_rel_state is not allowed");
357 : :
992 akapila@postgresql.o 358 :CBC 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))
992 akapila@postgresql.o 402 [ # # ]:UBC 0 : elog(ERROR, "null argument to binary_upgrade_replorigin_advance is not allowed");
403 : :
992 akapila@postgresql.o 404 :CBC 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
424 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 : : }
|