Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)