| 1 | /* |
| 2 | * pg_upgrade_support.c |
| 3 | * |
| 4 | * server-side functions to set backend global variables |
| 5 | * to control oid and relfilenode assignment, and do other special |
| 6 | * hacks needed for pg_upgrade. |
| 7 | * |
| 8 | * Copyright (c) 2010-2019, 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 "utils/array.h" |
| 21 | #include "utils/builtins.h" |
| 22 | |
| 23 | |
| 24 | #define CHECK_IS_BINARY_UPGRADE \ |
| 25 | do { \ |
| 26 | if (!IsBinaryUpgrade) \ |
| 27 | ereport(ERROR, \ |
| 28 | (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), \ |
| 29 | (errmsg("function can only be called when server is in binary upgrade mode")))); \ |
| 30 | } while (0) |
| 31 | |
| 32 | Datum |
| 33 | binary_upgrade_set_next_pg_type_oid(PG_FUNCTION_ARGS) |
| 34 | { |
| 35 | Oid typoid = PG_GETARG_OID(0); |
| 36 | |
| 37 | CHECK_IS_BINARY_UPGRADE; |
| 38 | binary_upgrade_next_pg_type_oid = typoid; |
| 39 | |
| 40 | PG_RETURN_VOID(); |
| 41 | } |
| 42 | |
| 43 | Datum |
| 44 | binary_upgrade_set_next_array_pg_type_oid(PG_FUNCTION_ARGS) |
| 45 | { |
| 46 | Oid typoid = PG_GETARG_OID(0); |
| 47 | |
| 48 | CHECK_IS_BINARY_UPGRADE; |
| 49 | binary_upgrade_next_array_pg_type_oid = typoid; |
| 50 | |
| 51 | PG_RETURN_VOID(); |
| 52 | } |
| 53 | |
| 54 | Datum |
| 55 | binary_upgrade_set_next_toast_pg_type_oid(PG_FUNCTION_ARGS) |
| 56 | { |
| 57 | Oid typoid = PG_GETARG_OID(0); |
| 58 | |
| 59 | CHECK_IS_BINARY_UPGRADE; |
| 60 | binary_upgrade_next_toast_pg_type_oid = typoid; |
| 61 | |
| 62 | PG_RETURN_VOID(); |
| 63 | } |
| 64 | |
| 65 | Datum |
| 66 | binary_upgrade_set_next_heap_pg_class_oid(PG_FUNCTION_ARGS) |
| 67 | { |
| 68 | Oid reloid = PG_GETARG_OID(0); |
| 69 | |
| 70 | CHECK_IS_BINARY_UPGRADE; |
| 71 | binary_upgrade_next_heap_pg_class_oid = reloid; |
| 72 | |
| 73 | PG_RETURN_VOID(); |
| 74 | } |
| 75 | |
| 76 | Datum |
| 77 | binary_upgrade_set_next_index_pg_class_oid(PG_FUNCTION_ARGS) |
| 78 | { |
| 79 | Oid reloid = PG_GETARG_OID(0); |
| 80 | |
| 81 | CHECK_IS_BINARY_UPGRADE; |
| 82 | binary_upgrade_next_index_pg_class_oid = reloid; |
| 83 | |
| 84 | PG_RETURN_VOID(); |
| 85 | } |
| 86 | |
| 87 | Datum |
| 88 | binary_upgrade_set_next_toast_pg_class_oid(PG_FUNCTION_ARGS) |
| 89 | { |
| 90 | Oid reloid = PG_GETARG_OID(0); |
| 91 | |
| 92 | CHECK_IS_BINARY_UPGRADE; |
| 93 | binary_upgrade_next_toast_pg_class_oid = reloid; |
| 94 | |
| 95 | PG_RETURN_VOID(); |
| 96 | } |
| 97 | |
| 98 | Datum |
| 99 | binary_upgrade_set_next_pg_enum_oid(PG_FUNCTION_ARGS) |
| 100 | { |
| 101 | Oid enumoid = PG_GETARG_OID(0); |
| 102 | |
| 103 | CHECK_IS_BINARY_UPGRADE; |
| 104 | binary_upgrade_next_pg_enum_oid = enumoid; |
| 105 | |
| 106 | PG_RETURN_VOID(); |
| 107 | } |
| 108 | |
| 109 | Datum |
| 110 | binary_upgrade_set_next_pg_authid_oid(PG_FUNCTION_ARGS) |
| 111 | { |
| 112 | Oid authoid = PG_GETARG_OID(0); |
| 113 | |
| 114 | CHECK_IS_BINARY_UPGRADE; |
| 115 | binary_upgrade_next_pg_authid_oid = authoid; |
| 116 | PG_RETURN_VOID(); |
| 117 | } |
| 118 | |
| 119 | Datum |
| 120 | binary_upgrade_create_empty_extension(PG_FUNCTION_ARGS) |
| 121 | { |
| 122 | text *extName; |
| 123 | text *schemaName; |
| 124 | bool relocatable; |
| 125 | text *extVersion; |
| 126 | Datum extConfig; |
| 127 | Datum extCondition; |
| 128 | List *requiredExtensions; |
| 129 | |
| 130 | CHECK_IS_BINARY_UPGRADE; |
| 131 | |
| 132 | /* We must check these things before dereferencing the arguments */ |
| 133 | if (PG_ARGISNULL(0) || |
| 134 | PG_ARGISNULL(1) || |
| 135 | PG_ARGISNULL(2) || |
| 136 | PG_ARGISNULL(3)) |
| 137 | elog(ERROR, "null argument to binary_upgrade_create_empty_extension is not allowed" ); |
| 138 | |
| 139 | extName = PG_GETARG_TEXT_PP(0); |
| 140 | schemaName = PG_GETARG_TEXT_PP(1); |
| 141 | relocatable = PG_GETARG_BOOL(2); |
| 142 | extVersion = PG_GETARG_TEXT_PP(3); |
| 143 | |
| 144 | if (PG_ARGISNULL(4)) |
| 145 | extConfig = PointerGetDatum(NULL); |
| 146 | else |
| 147 | extConfig = PG_GETARG_DATUM(4); |
| 148 | |
| 149 | if (PG_ARGISNULL(5)) |
| 150 | extCondition = PointerGetDatum(NULL); |
| 151 | else |
| 152 | extCondition = PG_GETARG_DATUM(5); |
| 153 | |
| 154 | requiredExtensions = NIL; |
| 155 | if (!PG_ARGISNULL(6)) |
| 156 | { |
| 157 | ArrayType *textArray = PG_GETARG_ARRAYTYPE_P(6); |
| 158 | Datum *textDatums; |
| 159 | int ndatums; |
| 160 | int i; |
| 161 | |
| 162 | deconstruct_array(textArray, |
| 163 | TEXTOID, -1, false, 'i', |
| 164 | &textDatums, NULL, &ndatums); |
| 165 | for (i = 0; i < ndatums; i++) |
| 166 | { |
| 167 | char *extName = TextDatumGetCString(textDatums[i]); |
| 168 | Oid extOid = get_extension_oid(extName, false); |
| 169 | |
| 170 | requiredExtensions = lappend_oid(requiredExtensions, extOid); |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | InsertExtensionTuple(text_to_cstring(extName), |
| 175 | GetUserId(), |
| 176 | get_namespace_oid(text_to_cstring(schemaName), false), |
| 177 | relocatable, |
| 178 | text_to_cstring(extVersion), |
| 179 | extConfig, |
| 180 | extCondition, |
| 181 | requiredExtensions); |
| 182 | |
| 183 | PG_RETURN_VOID(); |
| 184 | } |
| 185 | |
| 186 | Datum |
| 187 | binary_upgrade_set_record_init_privs(PG_FUNCTION_ARGS) |
| 188 | { |
| 189 | bool record_init_privs = PG_GETARG_BOOL(0); |
| 190 | |
| 191 | CHECK_IS_BINARY_UPGRADE; |
| 192 | binary_upgrade_record_init_privs = record_init_privs; |
| 193 | |
| 194 | PG_RETURN_VOID(); |
| 195 | } |
| 196 | |
| 197 | Datum |
| 198 | binary_upgrade_set_missing_value(PG_FUNCTION_ARGS) |
| 199 | { |
| 200 | Oid table_id = PG_GETARG_OID(0); |
| 201 | text *attname = PG_GETARG_TEXT_P(1); |
| 202 | text *value = PG_GETARG_TEXT_P(2); |
| 203 | char *cattname = text_to_cstring(attname); |
| 204 | char *cvalue = text_to_cstring(value); |
| 205 | |
| 206 | CHECK_IS_BINARY_UPGRADE; |
| 207 | SetAttrMissing(table_id, cattname, cvalue); |
| 208 | |
| 209 | PG_RETURN_VOID(); |
| 210 | } |
| 211 | |