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-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
818 rhaas@postgresql.org 43 :UBC 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
3323 peter_e@gmx.net 54 :CBC 768 : binary_upgrade_set_next_pg_type_oid(PG_FUNCTION_ARGS)
55 : : {
5086 bruce@momjian.us 56 : 768 : Oid typoid = PG_GETARG_OID(0);
57 : :
3520 58 [ - + - - ]: 768 : CHECK_IS_BINARY_UPGRADE;
5086 59 : 768 : binary_upgrade_next_pg_type_oid = typoid;
60 : :
61 : 768 : PG_RETURN_VOID();
62 : : }
63 : :
64 : : Datum
3323 peter_e@gmx.net 65 : 767 : binary_upgrade_set_next_array_pg_type_oid(PG_FUNCTION_ARGS)
66 : : {
5086 bruce@momjian.us 67 : 767 : Oid typoid = PG_GETARG_OID(0);
68 : :
3520 69 [ - + - - ]: 767 : CHECK_IS_BINARY_UPGRADE;
4846 70 : 767 : binary_upgrade_next_array_pg_type_oid = typoid;
71 : :
5086 72 : 767 : PG_RETURN_VOID();
73 : : }
74 : :
75 : : Datum
1211 akorotkov@postgresql 76 : 4 : binary_upgrade_set_next_multirange_pg_type_oid(PG_FUNCTION_ARGS)
77 : : {
78 : 4 : Oid typoid = PG_GETARG_OID(0);
79 : :
80 [ - + - - ]: 4 : CHECK_IS_BINARY_UPGRADE;
81 : 4 : binary_upgrade_next_mrng_pg_type_oid = typoid;
82 : :
83 : 4 : PG_RETURN_VOID();
84 : : }
85 : :
86 : : Datum
87 : 4 : binary_upgrade_set_next_multirange_array_pg_type_oid(PG_FUNCTION_ARGS)
88 : : {
89 : 4 : Oid typoid = PG_GETARG_OID(0);
90 : :
91 [ - + - - ]: 4 : CHECK_IS_BINARY_UPGRADE;
92 : 4 : binary_upgrade_next_mrng_array_pg_type_oid = typoid;
93 : :
94 : 4 : PG_RETURN_VOID();
95 : : }
96 : :
97 : : Datum
3323 peter_e@gmx.net 98 : 776 : binary_upgrade_set_next_heap_pg_class_oid(PG_FUNCTION_ARGS)
99 : : {
4846 bruce@momjian.us 100 : 776 : Oid reloid = PG_GETARG_OID(0);
101 : :
3520 102 [ - + - - ]: 776 : CHECK_IS_BINARY_UPGRADE;
4846 103 : 776 : binary_upgrade_next_heap_pg_class_oid = reloid;
104 : :
5086 105 : 776 : PG_RETURN_VOID();
106 : : }
107 : :
108 : : Datum
818 rhaas@postgresql.org 109 : 643 : binary_upgrade_set_next_heap_relfilenode(PG_FUNCTION_ARGS)
110 : : {
564 111 : 643 : RelFileNumber relfilenumber = PG_GETARG_OID(0);
112 : :
818 113 [ - + - - ]: 643 : CHECK_IS_BINARY_UPGRADE;
648 114 : 643 : binary_upgrade_next_heap_pg_class_relfilenumber = relfilenumber;
115 : :
818 116 : 643 : PG_RETURN_VOID();
117 : : }
118 : :
119 : : Datum
3323 peter_e@gmx.net 120 : 525 : binary_upgrade_set_next_index_pg_class_oid(PG_FUNCTION_ARGS)
121 : : {
4846 bruce@momjian.us 122 : 525 : Oid reloid = PG_GETARG_OID(0);
123 : :
3520 124 [ - + - - ]: 525 : CHECK_IS_BINARY_UPGRADE;
4846 125 : 525 : binary_upgrade_next_index_pg_class_oid = reloid;
126 : :
5086 127 : 525 : PG_RETURN_VOID();
128 : : }
129 : :
130 : : Datum
818 rhaas@postgresql.org 131 : 535 : binary_upgrade_set_next_index_relfilenode(PG_FUNCTION_ARGS)
132 : : {
564 133 : 535 : RelFileNumber relfilenumber = PG_GETARG_OID(0);
134 : :
818 135 [ - + - - ]: 535 : CHECK_IS_BINARY_UPGRADE;
648 136 : 535 : binary_upgrade_next_index_pg_class_relfilenumber = relfilenumber;
137 : :
818 138 : 535 : PG_RETURN_VOID();
139 : : }
140 : :
141 : : Datum
3323 peter_e@gmx.net 142 : 262 : binary_upgrade_set_next_toast_pg_class_oid(PG_FUNCTION_ARGS)
143 : : {
4846 bruce@momjian.us 144 : 262 : Oid reloid = PG_GETARG_OID(0);
145 : :
3520 146 [ - + - - ]: 262 : CHECK_IS_BINARY_UPGRADE;
4846 147 : 262 : binary_upgrade_next_toast_pg_class_oid = reloid;
148 : :
5086 149 : 262 : PG_RETURN_VOID();
150 : : }
151 : :
152 : : Datum
818 rhaas@postgresql.org 153 : 262 : binary_upgrade_set_next_toast_relfilenode(PG_FUNCTION_ARGS)
154 : : {
564 155 : 262 : RelFileNumber relfilenumber = PG_GETARG_OID(0);
156 : :
818 157 [ - + - - ]: 262 : CHECK_IS_BINARY_UPGRADE;
648 158 : 262 : binary_upgrade_next_toast_pg_class_relfilenumber = relfilenumber;
159 : :
818 160 : 262 : PG_RETURN_VOID();
161 : : }
162 : :
163 : : Datum
3323 peter_e@gmx.net 164 : 50 : binary_upgrade_set_next_pg_enum_oid(PG_FUNCTION_ARGS)
165 : : {
5086 bruce@momjian.us 166 : 50 : Oid enumoid = PG_GETARG_OID(0);
167 : :
3520 168 [ - + - - ]: 50 : CHECK_IS_BINARY_UPGRADE;
4921 tgl@sss.pgh.pa.us 169 : 50 : binary_upgrade_next_pg_enum_oid = enumoid;
170 : :
5086 bruce@momjian.us 171 : 50 : PG_RETURN_VOID();
172 : : }
173 : :
174 : : Datum
3323 peter_e@gmx.net 175 : 3 : binary_upgrade_set_next_pg_authid_oid(PG_FUNCTION_ARGS)
176 : : {
4846 bruce@momjian.us 177 : 3 : Oid authoid = PG_GETARG_OID(0);
178 : :
3520 179 [ - + - - ]: 3 : CHECK_IS_BINARY_UPGRADE;
4846 180 : 3 : binary_upgrade_next_pg_authid_oid = authoid;
181 : 3 : PG_RETURN_VOID();
182 : : }
183 : :
184 : : Datum
3323 peter_e@gmx.net 185 :UBC 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 : :
3520 bruce@momjian.us 195 [ # # # # ]: 0 : CHECK_IS_BINARY_UPGRADE;
196 : :
197 : : /* We must check these things before dereferencing the arguments */
3024 tgl@sss.pgh.pa.us 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 : :
4813 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 : :
653 peter@eisentraut.org 227 : 0 : deconstruct_array_builtin(textArray, TEXTOID, &textDatums, NULL, &ndatums);
4813 tgl@sss.pgh.pa.us 228 [ # # ]: 0 : for (i = 0; i < ndatums; i++)
229 : : {
2590 noah@leadboat.com 230 : 0 : char *extName = TextDatumGetCString(textDatums[i]);
4753 bruce@momjian.us 231 : 0 : Oid extOid = get_extension_oid(extName, false);
232 : :
4813 tgl@sss.pgh.pa.us 233 : 0 : requiredExtensions = lappend_oid(requiredExtensions, extOid);
234 : : }
235 : : }
236 : :
237 : 0 : InsertExtensionTuple(text_to_cstring(extName),
238 : : GetUserId(),
2489 239 : 0 : get_namespace_oid(text_to_cstring(schemaName), false),
240 : : relocatable,
4811 241 : 0 : text_to_cstring(extVersion),
242 : : extConfig,
243 : : extCondition,
244 : : requiredExtensions);
245 : :
4813 246 : 0 : PG_RETURN_VOID();
247 : : }
248 : :
249 : : Datum
2930 sfrost@snowman.net 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
2123 andrew@dunslane.net 261 :CBC 2 : binary_upgrade_set_missing_value(PG_FUNCTION_ARGS)
262 : : {
263 : 2 : Oid table_id = PG_GETARG_OID(0);
264 : 2 : text *attname = PG_GETARG_TEXT_P(1);
265 : 2 : text *value = PG_GETARG_TEXT_P(2);
266 : 2 : char *cattname = text_to_cstring(attname);
267 : 2 : char *cvalue = text_to_cstring(value);
268 : :
269 [ - + - - ]: 2 : CHECK_IS_BINARY_UPGRADE;
270 : 2 : SetAttrMissing(table_id, cattname, cvalue);
271 : :
272 : 2 : 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
171 akapila@postgresql.o 285 :GNC 5 : 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 [ - + - - ]: 5 : 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 : : */
129 297 [ - + ]: 5 : Assert(has_rolreplication(GetUserId()));
298 : :
171 299 : 5 : slot_name = PG_GETARG_NAME(0);
300 : :
301 : : /* Acquire the given slot */
302 : 5 : ReplicationSlotAcquire(NameStr(*slot_name), true);
303 : :
304 [ - + ]: 5 : Assert(SlotIsLogical(MyReplicationSlot));
305 : :
306 : : /* Slots must be valid as otherwise we won't be able to scan the WAL */
307 [ - + ]: 5 : Assert(MyReplicationSlot->data.invalidated == RS_INVAL_NONE);
308 : :
309 : 5 : end_of_wal = GetFlushRecPtr(NULL);
310 : 5 : found_pending_wal = LogicalReplicationSlotHasPendingWal(end_of_wal);
311 : :
312 : : /* Clean up */
313 : 5 : ReplicationSlotRelease();
314 : :
315 : 5 : 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
103 325 : 2 : 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 [ - + - - ]: 2 : CHECK_IS_BINARY_UPGRADE;
336 : :
337 : : /* We must check these things before dereferencing the arguments */
338 [ + - + - : 2 : if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2))
- + ]
103 akapila@postgresql.o 339 [ # # ]:UNC 0 : elog(ERROR, "null argument to binary_upgrade_add_sub_rel_state is not allowed");
340 : :
103 akapila@postgresql.o 341 :GNC 2 : subname = text_to_cstring(PG_GETARG_TEXT_PP(0));
342 : 2 : relid = PG_GETARG_OID(1);
343 : 2 : relstate = PG_GETARG_CHAR(2);
344 [ + + ]: 2 : sublsn = PG_ARGISNULL(3) ? InvalidXLogRecPtr : PG_GETARG_LSN(3);
345 : :
346 : 2 : subrel = table_open(SubscriptionRelationId, RowExclusiveLock);
347 : 2 : subid = get_subscription_oid(subname, false);
348 : 2 : 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 : 2 : AddSubscriptionRelState(subid, relid, relstate, sublsn, false);
357 : 2 : relation_close(rel, AccessShareLock);
358 : 2 : table_close(subrel, RowExclusiveLock);
359 : :
360 : 2 : 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 : 1 : 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 [ - + - - ]: 1 : CHECK_IS_BINARY_UPGRADE;
379 : :
380 : : /*
381 : : * We must ensure a non-NULL subscription name before dereferencing the
382 : : * arguments.
383 : : */
384 [ - + ]: 1 : if (PG_ARGISNULL(0))
103 akapila@postgresql.o 385 [ # # ]:UNC 0 : elog(ERROR, "null argument to binary_upgrade_replorigin_advance is not allowed");
386 : :
103 akapila@postgresql.o 387 :GNC 1 : subname = text_to_cstring(PG_GETARG_TEXT_PP(0));
388 [ + - ]: 1 : remote_commit = PG_ARGISNULL(1) ? InvalidXLogRecPtr : PG_GETARG_LSN(1);
389 : :
390 : 1 : rel = table_open(SubscriptionRelationId, RowExclusiveLock);
391 : 1 : subid = get_subscription_oid(subname, false);
392 : :
393 : 1 : ReplicationOriginNameForLogicalRep(subid, InvalidOid, originname, sizeof(originname));
394 : :
395 : : /* Lock to prevent the replication origin from vanishing */
396 : 1 : LockRelationOid(ReplicationOriginRelationId, RowExclusiveLock);
397 : 1 : 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 : 1 : replorigin_advance(node, remote_commit, InvalidXLogRecPtr,
406 : : false /* backward */ ,
407 : : false /* WAL log */ );
408 : :
409 : 1 : UnlockRelationOid(ReplicationOriginRelationId, RowExclusiveLock);
410 : 1 : table_close(rel, RowExclusiveLock);
411 : :
412 : 1 : PG_RETURN_VOID();
413 : : }
|