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