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-2023, PostgreSQL Global Development Group 9 : * src/backend/utils/adt/pg_upgrade_support.c 10 : */ 11 : 12 : #include "postgres.h" 13 : 14 : #include "catalog/binary_upgrade.h" 15 : #include "catalog/heap.h" 16 : #include "catalog/namespace.h" 17 : #include "catalog/pg_type.h" 18 : #include "commands/extension.h" 19 : #include "miscadmin.h" 20 : #include "replication/logical.h" 21 : #include "utils/array.h" 22 : #include "utils/builtins.h" 23 : 24 : 25 : #define CHECK_IS_BINARY_UPGRADE \ 26 : do { \ 27 : if (!IsBinaryUpgrade) \ 28 : ereport(ERROR, \ 29 : (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), \ 30 : errmsg("function can only be called when server is in binary upgrade mode"))); \ 31 : } while (0) 32 : 33 : Datum 34 0 : binary_upgrade_set_next_pg_tablespace_oid(PG_FUNCTION_ARGS) 35 : { 36 0 : Oid tbspoid = PG_GETARG_OID(0); 37 : 38 0 : CHECK_IS_BINARY_UPGRADE; 39 0 : binary_upgrade_next_pg_tablespace_oid = tbspoid; 40 : 41 0 : PG_RETURN_VOID(); 42 : } 43 : 44 : Datum 45 1476 : binary_upgrade_set_next_pg_type_oid(PG_FUNCTION_ARGS) 46 : { 47 1476 : Oid typoid = PG_GETARG_OID(0); 48 : 49 1476 : CHECK_IS_BINARY_UPGRADE; 50 1476 : binary_upgrade_next_pg_type_oid = typoid; 51 : 52 1476 : PG_RETURN_VOID(); 53 : } 54 : 55 : Datum 56 1474 : binary_upgrade_set_next_array_pg_type_oid(PG_FUNCTION_ARGS) 57 : { 58 1474 : Oid typoid = PG_GETARG_OID(0); 59 : 60 1474 : CHECK_IS_BINARY_UPGRADE; 61 1474 : binary_upgrade_next_array_pg_type_oid = typoid; 62 : 63 1474 : PG_RETURN_VOID(); 64 : } 65 : 66 : Datum 67 8 : binary_upgrade_set_next_multirange_pg_type_oid(PG_FUNCTION_ARGS) 68 : { 69 8 : Oid typoid = PG_GETARG_OID(0); 70 : 71 8 : CHECK_IS_BINARY_UPGRADE; 72 8 : binary_upgrade_next_mrng_pg_type_oid = typoid; 73 : 74 8 : PG_RETURN_VOID(); 75 : } 76 : 77 : Datum 78 8 : binary_upgrade_set_next_multirange_array_pg_type_oid(PG_FUNCTION_ARGS) 79 : { 80 8 : Oid typoid = PG_GETARG_OID(0); 81 : 82 8 : CHECK_IS_BINARY_UPGRADE; 83 8 : binary_upgrade_next_mrng_array_pg_type_oid = typoid; 84 : 85 8 : PG_RETURN_VOID(); 86 : } 87 : 88 : Datum 89 1488 : binary_upgrade_set_next_heap_pg_class_oid(PG_FUNCTION_ARGS) 90 : { 91 1488 : Oid reloid = PG_GETARG_OID(0); 92 : 93 1488 : CHECK_IS_BINARY_UPGRADE; 94 1488 : binary_upgrade_next_heap_pg_class_oid = reloid; 95 : 96 1488 : PG_RETURN_VOID(); 97 : } 98 : 99 : Datum 100 1226 : binary_upgrade_set_next_heap_relfilenode(PG_FUNCTION_ARGS) 101 : { 102 1226 : RelFileNumber relfilenumber = PG_GETARG_OID(0); 103 : 104 1226 : CHECK_IS_BINARY_UPGRADE; 105 1226 : binary_upgrade_next_heap_pg_class_relfilenumber = relfilenumber; 106 : 107 1226 : PG_RETURN_VOID(); 108 : } 109 : 110 : Datum 111 988 : binary_upgrade_set_next_index_pg_class_oid(PG_FUNCTION_ARGS) 112 : { 113 988 : Oid reloid = PG_GETARG_OID(0); 114 : 115 988 : CHECK_IS_BINARY_UPGRADE; 116 988 : binary_upgrade_next_index_pg_class_oid = reloid; 117 : 118 988 : PG_RETURN_VOID(); 119 : } 120 : 121 : Datum 122 1004 : binary_upgrade_set_next_index_relfilenode(PG_FUNCTION_ARGS) 123 : { 124 1004 : RelFileNumber relfilenumber = PG_GETARG_OID(0); 125 : 126 1004 : CHECK_IS_BINARY_UPGRADE; 127 1004 : binary_upgrade_next_index_pg_class_relfilenumber = relfilenumber; 128 : 129 1004 : PG_RETURN_VOID(); 130 : } 131 : 132 : Datum 133 490 : binary_upgrade_set_next_toast_pg_class_oid(PG_FUNCTION_ARGS) 134 : { 135 490 : Oid reloid = PG_GETARG_OID(0); 136 : 137 490 : CHECK_IS_BINARY_UPGRADE; 138 490 : binary_upgrade_next_toast_pg_class_oid = reloid; 139 : 140 490 : PG_RETURN_VOID(); 141 : } 142 : 143 : Datum 144 490 : binary_upgrade_set_next_toast_relfilenode(PG_FUNCTION_ARGS) 145 : { 146 490 : RelFileNumber relfilenumber = PG_GETARG_OID(0); 147 : 148 490 : CHECK_IS_BINARY_UPGRADE; 149 490 : binary_upgrade_next_toast_pg_class_relfilenumber = relfilenumber; 150 : 151 490 : PG_RETURN_VOID(); 152 : } 153 : 154 : Datum 155 88 : binary_upgrade_set_next_pg_enum_oid(PG_FUNCTION_ARGS) 156 : { 157 88 : Oid enumoid = PG_GETARG_OID(0); 158 : 159 88 : CHECK_IS_BINARY_UPGRADE; 160 88 : binary_upgrade_next_pg_enum_oid = enumoid; 161 : 162 88 : PG_RETURN_VOID(); 163 : } 164 : 165 : Datum 166 4 : binary_upgrade_set_next_pg_authid_oid(PG_FUNCTION_ARGS) 167 : { 168 4 : Oid authoid = PG_GETARG_OID(0); 169 : 170 4 : CHECK_IS_BINARY_UPGRADE; 171 4 : binary_upgrade_next_pg_authid_oid = authoid; 172 4 : PG_RETURN_VOID(); 173 : } 174 : 175 : Datum 176 0 : binary_upgrade_create_empty_extension(PG_FUNCTION_ARGS) 177 : { 178 : text *extName; 179 : text *schemaName; 180 : bool relocatable; 181 : text *extVersion; 182 : Datum extConfig; 183 : Datum extCondition; 184 : List *requiredExtensions; 185 : 186 0 : CHECK_IS_BINARY_UPGRADE; 187 : 188 : /* We must check these things before dereferencing the arguments */ 189 0 : if (PG_ARGISNULL(0) || 190 0 : PG_ARGISNULL(1) || 191 0 : PG_ARGISNULL(2) || 192 0 : PG_ARGISNULL(3)) 193 0 : elog(ERROR, "null argument to binary_upgrade_create_empty_extension is not allowed"); 194 : 195 0 : extName = PG_GETARG_TEXT_PP(0); 196 0 : schemaName = PG_GETARG_TEXT_PP(1); 197 0 : relocatable = PG_GETARG_BOOL(2); 198 0 : extVersion = PG_GETARG_TEXT_PP(3); 199 : 200 0 : if (PG_ARGISNULL(4)) 201 0 : extConfig = PointerGetDatum(NULL); 202 : else 203 0 : extConfig = PG_GETARG_DATUM(4); 204 : 205 0 : if (PG_ARGISNULL(5)) 206 0 : extCondition = PointerGetDatum(NULL); 207 : else 208 0 : extCondition = PG_GETARG_DATUM(5); 209 : 210 0 : requiredExtensions = NIL; 211 0 : if (!PG_ARGISNULL(6)) 212 : { 213 0 : ArrayType *textArray = PG_GETARG_ARRAYTYPE_P(6); 214 : Datum *textDatums; 215 : int ndatums; 216 : int i; 217 : 218 0 : deconstruct_array_builtin(textArray, TEXTOID, &textDatums, NULL, &ndatums); 219 0 : for (i = 0; i < ndatums; i++) 220 : { 221 0 : char *extName = TextDatumGetCString(textDatums[i]); 222 0 : Oid extOid = get_extension_oid(extName, false); 223 : 224 0 : requiredExtensions = lappend_oid(requiredExtensions, extOid); 225 : } 226 : } 227 : 228 0 : InsertExtensionTuple(text_to_cstring(extName), 229 : GetUserId(), 230 0 : get_namespace_oid(text_to_cstring(schemaName), false), 231 : relocatable, 232 0 : text_to_cstring(extVersion), 233 : extConfig, 234 : extCondition, 235 : requiredExtensions); 236 : 237 0 : PG_RETURN_VOID(); 238 : } 239 : 240 : Datum 241 0 : binary_upgrade_set_record_init_privs(PG_FUNCTION_ARGS) 242 : { 243 0 : bool record_init_privs = PG_GETARG_BOOL(0); 244 : 245 0 : CHECK_IS_BINARY_UPGRADE; 246 0 : binary_upgrade_record_init_privs = record_init_privs; 247 : 248 0 : PG_RETURN_VOID(); 249 : } 250 : 251 : Datum 252 4 : binary_upgrade_set_missing_value(PG_FUNCTION_ARGS) 253 : { 254 4 : Oid table_id = PG_GETARG_OID(0); 255 4 : text *attname = PG_GETARG_TEXT_P(1); 256 4 : text *value = PG_GETARG_TEXT_P(2); 257 4 : char *cattname = text_to_cstring(attname); 258 4 : char *cvalue = text_to_cstring(value); 259 : 260 4 : CHECK_IS_BINARY_UPGRADE; 261 4 : SetAttrMissing(table_id, cattname, cvalue); 262 : 263 4 : PG_RETURN_VOID(); 264 : } 265 : 266 : /* 267 : * Verify the given slot has already consumed all the WAL changes. 268 : * 269 : * Returns true if there are no decodable WAL records after the 270 : * confirmed_flush_lsn. Otherwise false. 271 : * 272 : * This is a special purpose function to ensure that the given slot can be 273 : * upgraded without data loss. 274 : */ 275 : Datum 276 10 : binary_upgrade_logical_slot_has_caught_up(PG_FUNCTION_ARGS) 277 : { 278 : Name slot_name; 279 : XLogRecPtr end_of_wal; 280 : bool found_pending_wal; 281 : 282 10 : CHECK_IS_BINARY_UPGRADE; 283 : 284 : /* We must check before dereferencing the argument */ 285 10 : if (PG_ARGISNULL(0)) 286 0 : elog(ERROR, "null argument to binary_upgrade_validate_wal_records is not allowed"); 287 : 288 10 : CheckSlotPermissions(); 289 : 290 10 : slot_name = PG_GETARG_NAME(0); 291 : 292 : /* Acquire the given slot */ 293 10 : ReplicationSlotAcquire(NameStr(*slot_name), true); 294 : 295 : Assert(SlotIsLogical(MyReplicationSlot)); 296 : 297 : /* Slots must be valid as otherwise we won't be able to scan the WAL */ 298 : Assert(MyReplicationSlot->data.invalidated == RS_INVAL_NONE); 299 : 300 10 : end_of_wal = GetFlushRecPtr(NULL); 301 10 : found_pending_wal = LogicalReplicationSlotHasPendingWal(end_of_wal); 302 : 303 : /* Clean up */ 304 10 : ReplicationSlotRelease(); 305 : 306 10 : PG_RETURN_BOOL(!found_pending_wal); 307 : }