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-2018, 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
binary_upgrade_set_next_pg_type_oid(PG_FUNCTION_ARGS)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
binary_upgrade_set_next_array_pg_type_oid(PG_FUNCTION_ARGS)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
binary_upgrade_set_next_toast_pg_type_oid(PG_FUNCTION_ARGS)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
binary_upgrade_set_next_heap_pg_class_oid(PG_FUNCTION_ARGS)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
binary_upgrade_set_next_index_pg_class_oid(PG_FUNCTION_ARGS)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
binary_upgrade_set_next_toast_pg_class_oid(PG_FUNCTION_ARGS)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
binary_upgrade_set_next_pg_enum_oid(PG_FUNCTION_ARGS)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
binary_upgrade_set_next_pg_authid_oid(PG_FUNCTION_ARGS)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
binary_upgrade_create_empty_extension(PG_FUNCTION_ARGS)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
binary_upgrade_set_record_init_privs(PG_FUNCTION_ARGS)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
binary_upgrade_set_missing_value(PG_FUNCTION_ARGS)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