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