Skip to content

Commit caddcb8

Browse files
committed
Fix pg_upgrade to handle extensions.
This follows my proposal of yesterday, namely that we try to recreate the previous state of the extension exactly, instead of allowing CREATE EXTENSION to run a SQL script that might create some entirely-incompatible on-disk state. In --binary-upgrade mode, pg_dump won't issue CREATE EXTENSION at all, but instead uses a kluge function provided by pg_upgrade_support to recreate the pg_extension row (and extension-level pg_depend entries) without creating any member objects. The member objects are then restored in the same way as if they weren't members, in particular using pg_upgrade's normal hacks to preserve OIDs that need to be preserved. Then, for each member object, ALTER EXTENSION ADD is issued to recreate the pg_depend entry that marks it as an extension member. In passing, fix breakage in pg_upgrade's enum-type support: somebody didn't fix it when the noise word VALUE got added to ALTER TYPE ADD. Also, rationalize parsetree representation of COMMENT ON DOMAIN and fix get_object_address() to allow OBJECT_DOMAIN.
1 parent 2e2d56f commit caddcb8

File tree

10 files changed

+544
-183
lines changed

10 files changed

+544
-183
lines changed

contrib/pg_upgrade/function.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,52 +36,58 @@ install_support_functions_in_new_db(const char *db_name)
3636

3737
PQclear(executeQueryOrDie(conn,
3838
"CREATE OR REPLACE FUNCTION "
39-
" binary_upgrade.set_next_pg_type_oid(OID) "
39+
"binary_upgrade.set_next_pg_type_oid(OID) "
4040
"RETURNS VOID "
4141
"AS '$libdir/pg_upgrade_support' "
4242
"LANGUAGE C STRICT;"));
4343
PQclear(executeQueryOrDie(conn,
4444
"CREATE OR REPLACE FUNCTION "
45-
" binary_upgrade.set_next_array_pg_type_oid(OID) "
45+
"binary_upgrade.set_next_array_pg_type_oid(OID) "
4646
"RETURNS VOID "
4747
"AS '$libdir/pg_upgrade_support' "
4848
"LANGUAGE C STRICT;"));
4949
PQclear(executeQueryOrDie(conn,
5050
"CREATE OR REPLACE FUNCTION "
51-
" binary_upgrade.set_next_toast_pg_type_oid(OID) "
51+
"binary_upgrade.set_next_toast_pg_type_oid(OID) "
5252
"RETURNS VOID "
5353
"AS '$libdir/pg_upgrade_support' "
5454
"LANGUAGE C STRICT;"));
5555
PQclear(executeQueryOrDie(conn,
5656
"CREATE OR REPLACE FUNCTION "
57-
" binary_upgrade.set_next_heap_pg_class_oid(OID) "
57+
"binary_upgrade.set_next_heap_pg_class_oid(OID) "
5858
"RETURNS VOID "
5959
"AS '$libdir/pg_upgrade_support' "
6060
"LANGUAGE C STRICT;"));
6161
PQclear(executeQueryOrDie(conn,
6262
"CREATE OR REPLACE FUNCTION "
63-
" binary_upgrade.set_next_index_pg_class_oid(OID) "
63+
"binary_upgrade.set_next_index_pg_class_oid(OID) "
6464
"RETURNS VOID "
6565
"AS '$libdir/pg_upgrade_support' "
6666
"LANGUAGE C STRICT;"));
6767
PQclear(executeQueryOrDie(conn,
6868
"CREATE OR REPLACE FUNCTION "
69-
" binary_upgrade.set_next_toast_pg_class_oid(OID) "
69+
"binary_upgrade.set_next_toast_pg_class_oid(OID) "
7070
"RETURNS VOID "
7171
"AS '$libdir/pg_upgrade_support' "
7272
"LANGUAGE C STRICT;"));
7373
PQclear(executeQueryOrDie(conn,
7474
"CREATE OR REPLACE FUNCTION "
75-
" binary_upgrade.set_next_pg_enum_oid(OID) "
75+
"binary_upgrade.set_next_pg_enum_oid(OID) "
7676
"RETURNS VOID "
7777
"AS '$libdir/pg_upgrade_support' "
7878
"LANGUAGE C STRICT;"));
7979
PQclear(executeQueryOrDie(conn,
8080
"CREATE OR REPLACE FUNCTION "
81-
" binary_upgrade.set_next_pg_authid_oid(OID) "
81+
"binary_upgrade.set_next_pg_authid_oid(OID) "
8282
"RETURNS VOID "
8383
"AS '$libdir/pg_upgrade_support' "
8484
"LANGUAGE C STRICT;"));
85+
PQclear(executeQueryOrDie(conn,
86+
"CREATE OR REPLACE FUNCTION "
87+
"binary_upgrade.create_empty_extension(text, text, bool, text, oid[], text[], text[]) "
88+
"RETURNS VOID "
89+
"AS '$libdir/pg_upgrade_support' "
90+
"LANGUAGE C;"));
8591
PQfinish(conn);
8692
}
8793

@@ -139,8 +145,8 @@ get_loadable_libraries(void)
139145
"SELECT DISTINCT probin "
140146
"FROM pg_catalog.pg_proc "
141147
"WHERE prolang = 13 /* C */ AND "
142-
" probin IS NOT NULL AND "
143-
" oid >= %u;",
148+
"probin IS NOT NULL AND "
149+
"oid >= %u;",
144150
FirstNormalObjectId);
145151
totaltups += PQntuples(ress[dbnum]);
146152

contrib/pg_upgrade_support/pg_upgrade_support.c

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
/*
2-
* pg_upgrade_sysoids.c
2+
* pg_upgrade_support.c
33
*
44
* server-side functions to set backend global variables
5-
* to control oid and relfilenode assignment
5+
* to control oid and relfilenode assignment, and do other special
6+
* hacks needed for pg_upgrade.
67
*
78
* Copyright (c) 2010-2011, PostgreSQL Global Development Group
89
* contrib/pg_upgrade_support/pg_upgrade_support.c
@@ -12,7 +13,13 @@
1213

1314
#include "fmgr.h"
1415
#include "catalog/dependency.h"
16+
#include "catalog/namespace.h"
1517
#include "catalog/pg_class.h"
18+
#include "catalog/pg_type.h"
19+
#include "commands/extension.h"
20+
#include "miscadmin.h"
21+
#include "utils/array.h"
22+
#include "utils/builtins.h"
1623

1724
/* THIS IS USED ONLY FOR PG >= 9.0 */
1825

@@ -42,6 +49,8 @@ Datum set_next_toast_pg_class_oid(PG_FUNCTION_ARGS);
4249
Datum set_next_pg_enum_oid(PG_FUNCTION_ARGS);
4350
Datum set_next_pg_authid_oid(PG_FUNCTION_ARGS);
4451

52+
Datum create_empty_extension(PG_FUNCTION_ARGS);
53+
4554
PG_FUNCTION_INFO_V1(set_next_pg_type_oid);
4655
PG_FUNCTION_INFO_V1(set_next_array_pg_type_oid);
4756
PG_FUNCTION_INFO_V1(set_next_toast_pg_type_oid);
@@ -53,6 +62,8 @@ PG_FUNCTION_INFO_V1(set_next_toast_pg_class_oid);
5362
PG_FUNCTION_INFO_V1(set_next_pg_enum_oid);
5463
PG_FUNCTION_INFO_V1(set_next_pg_authid_oid);
5564

65+
PG_FUNCTION_INFO_V1(create_empty_extension);
66+
5667

5768
Datum
5869
set_next_pg_type_oid(PG_FUNCTION_ARGS)
@@ -133,3 +144,61 @@ set_next_pg_authid_oid(PG_FUNCTION_ARGS)
133144
PG_RETURN_VOID();
134145
}
135146

147+
Datum
148+
create_empty_extension(PG_FUNCTION_ARGS)
149+
{
150+
text *extName = PG_GETARG_TEXT_PP(0);
151+
text *schemaName = PG_GETARG_TEXT_PP(1);
152+
bool relocatable = PG_GETARG_BOOL(2);
153+
char *extVersion;
154+
Datum extConfig;
155+
Datum extCondition;
156+
List *requiredExtensions;
157+
158+
if (PG_ARGISNULL(3))
159+
extVersion = NULL;
160+
else
161+
extVersion = text_to_cstring(PG_GETARG_TEXT_PP(3));
162+
163+
if (PG_ARGISNULL(4))
164+
extConfig = PointerGetDatum(NULL);
165+
else
166+
extConfig = PG_GETARG_DATUM(4);
167+
168+
if (PG_ARGISNULL(5))
169+
extCondition = PointerGetDatum(NULL);
170+
else
171+
extCondition = PG_GETARG_DATUM(5);
172+
173+
requiredExtensions = NIL;
174+
if (!PG_ARGISNULL(6))
175+
{
176+
ArrayType *textArray = PG_GETARG_ARRAYTYPE_P(6);
177+
Datum *textDatums;
178+
int ndatums;
179+
int i;
180+
181+
deconstruct_array(textArray,
182+
TEXTOID, -1, false, 'i',
183+
&textDatums, NULL, &ndatums);
184+
for (i = 0; i < ndatums; i++)
185+
{
186+
text *txtname = DatumGetTextPP(textDatums[i]);
187+
char *extName = text_to_cstring(txtname);
188+
Oid extOid = get_extension_oid(extName, false);
189+
190+
requiredExtensions = lappend_oid(requiredExtensions, extOid);
191+
}
192+
}
193+
194+
InsertExtensionTuple(text_to_cstring(extName),
195+
GetUserId(),
196+
get_namespace_oid(text_to_cstring(schemaName), false),
197+
relocatable,
198+
extVersion,
199+
extConfig,
200+
extCondition,
201+
requiredExtensions);
202+
203+
PG_RETURN_VOID();
204+
}

src/backend/catalog/objectaddress.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
139139
address = get_object_address_unqualified(objtype, objname);
140140
break;
141141
case OBJECT_TYPE:
142+
case OBJECT_DOMAIN:
142143
address.classId = TypeRelationId;
143144
address.objectId =
144145
typenameTypeId(NULL, makeTypeNameFromNameList(objname));

src/backend/commands/comment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ CommentObject(CommentStmt *stmt)
105105
strVal(linitial(stmt->objname)));
106106
break;
107107
case OBJECT_TYPE:
108+
case OBJECT_DOMAIN:
108109
if (!pg_type_ownercheck(address.objectId, GetUserId()))
109110
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
110111
format_type_be(address.objectId));

src/backend/commands/extension.c

Lines changed: 68 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -648,13 +648,7 @@ CreateExtension(CreateExtensionStmt *stmt)
648648
ExtensionControlFile *control;
649649
List *requiredExtensions;
650650
List *requiredSchemas;
651-
Relation rel;
652-
Datum values[Natts_pg_extension];
653-
bool nulls[Natts_pg_extension];
654-
HeapTuple tuple;
655651
Oid extensionOid;
656-
ObjectAddress myself;
657-
ObjectAddress nsp;
658652
ListCell *lc;
659653

660654
/* Must be super user */
@@ -801,27 +795,85 @@ CreateExtension(CreateExtensionStmt *stmt)
801795
}
802796

803797
/*
804-
* Insert new tuple into pg_extension.
798+
* Insert new tuple into pg_extension, and create dependency entries.
799+
*/
800+
extensionOid = InsertExtensionTuple(control->name, extowner,
801+
schemaOid, control->relocatable,
802+
control->version,
803+
PointerGetDatum(NULL),
804+
PointerGetDatum(NULL),
805+
requiredExtensions);
806+
807+
/*
808+
* Apply any comment on extension
809+
*/
810+
if (control->comment != NULL)
811+
CreateComments(extensionOid, ExtensionRelationId, 0, control->comment);
812+
813+
/*
814+
* Finally, execute the extension script to create the member objects
815+
*/
816+
execute_extension_script(extensionOid, control, requiredSchemas,
817+
schemaName, schemaOid);
818+
}
819+
820+
/*
821+
* InsertExtensionTuple
822+
*
823+
* Insert the new pg_extension row, and create extension's dependency entries.
824+
* Return the OID assigned to the new row.
825+
*
826+
* This is exported for the benefit of pg_upgrade, which has to create a
827+
* pg_extension entry (and the extension-level dependencies) without
828+
* actually running the extension's script.
829+
*
830+
* extConfig and extCondition should be arrays or PointerGetDatum(NULL).
831+
* We declare them as plain Datum to avoid needing array.h in extension.h.
832+
*/
833+
Oid
834+
InsertExtensionTuple(const char *extName, Oid extOwner,
835+
Oid schemaOid, bool relocatable, const char *extVersion,
836+
Datum extConfig, Datum extCondition,
837+
List *requiredExtensions)
838+
{
839+
Oid extensionOid;
840+
Relation rel;
841+
Datum values[Natts_pg_extension];
842+
bool nulls[Natts_pg_extension];
843+
HeapTuple tuple;
844+
ObjectAddress myself;
845+
ObjectAddress nsp;
846+
ListCell *lc;
847+
848+
/*
849+
* Build and insert the pg_extension tuple
805850
*/
806851
rel = heap_open(ExtensionRelationId, RowExclusiveLock);
807852

808853
memset(values, 0, sizeof(values));
809854
memset(nulls, 0, sizeof(nulls));
810855

811856
values[Anum_pg_extension_extname - 1] =
812-
DirectFunctionCall1(namein, CStringGetDatum(control->name));
813-
values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extowner);
857+
DirectFunctionCall1(namein, CStringGetDatum(extName));
858+
values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner);
814859
values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid);
815-
values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(control->relocatable);
860+
values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable);
816861

817-
if (control->version == NULL)
862+
if (extVersion == NULL)
818863
nulls[Anum_pg_extension_extversion - 1] = true;
819864
else
820865
values[Anum_pg_extension_extversion - 1] =
821-
CStringGetTextDatum(control->version);
866+
CStringGetTextDatum(extVersion);
867+
868+
if (extConfig == PointerGetDatum(NULL))
869+
nulls[Anum_pg_extension_extconfig - 1] = true;
870+
else
871+
values[Anum_pg_extension_extconfig - 1] = extConfig;
822872

823-
nulls[Anum_pg_extension_extconfig - 1] = true;
824-
nulls[Anum_pg_extension_extcondition - 1] = true;
873+
if (extCondition == PointerGetDatum(NULL))
874+
nulls[Anum_pg_extension_extcondition - 1] = true;
875+
else
876+
values[Anum_pg_extension_extcondition - 1] = extCondition;
825877

826878
tuple = heap_form_tuple(rel->rd_att, values, nulls);
827879

@@ -831,16 +883,10 @@ CreateExtension(CreateExtensionStmt *stmt)
831883
heap_freetuple(tuple);
832884
heap_close(rel, RowExclusiveLock);
833885

834-
/*
835-
* Apply any comment on extension
836-
*/
837-
if (control->comment != NULL)
838-
CreateComments(extensionOid, ExtensionRelationId, 0, control->comment);
839-
840886
/*
841887
* Record dependencies on owner, schema, and prerequisite extensions
842888
*/
843-
recordDependencyOnOwner(ExtensionRelationId, extensionOid, extowner);
889+
recordDependencyOnOwner(ExtensionRelationId, extensionOid, extOwner);
844890

845891
myself.classId = ExtensionRelationId;
846892
myself.objectId = extensionOid;
@@ -864,11 +910,7 @@ CreateExtension(CreateExtensionStmt *stmt)
864910
recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
865911
}
866912

867-
/*
868-
* Finally, execute the extension script to create the member objects
869-
*/
870-
execute_extension_script(extensionOid, control, requiredSchemas,
871-
schemaName, schemaOid);
913+
return extensionOid;
872914
}
873915

874916

src/backend/parser/gram.y

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4790,7 +4790,7 @@ comment_type:
47904790
| INDEX { $$ = OBJECT_INDEX; }
47914791
| SEQUENCE { $$ = OBJECT_SEQUENCE; }
47924792
| TABLE { $$ = OBJECT_TABLE; }
4793-
| DOMAIN_P { $$ = OBJECT_TYPE; }
4793+
| DOMAIN_P { $$ = OBJECT_DOMAIN; }
47944794
| TYPE_P { $$ = OBJECT_TYPE; }
47954795
| VIEW { $$ = OBJECT_VIEW; }
47964796
| CONVERSION_P { $$ = OBJECT_CONVERSION; }

src/bin/pg_dump/common.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@ AssignDumpId(DumpableObject *dobj)
463463
dobj->name = NULL; /* must be set later */
464464
dobj->namespace = NULL; /* may be set later */
465465
dobj->dump = true; /* default assumption */
466+
dobj->ext_member = false; /* default assumption */
466467
dobj->dependencies = NULL;
467468
dobj->nDeps = 0;
468469
dobj->allocDeps = 0;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy