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 \
25do { \
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
32Datum
33binary_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
43Datum
44binary_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
54Datum
55binary_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
65Datum
66binary_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
76Datum
77binary_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
87Datum
88binary_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
98Datum
99binary_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
109Datum
110binary_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
119Datum
120binary_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
186Datum
187binary_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
197Datum
198binary_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