dump_extension_script.patch
text/x-patch
Filename: dump_extension_script.patch
Type: text/x-patch
Part: 0
Message:
Dumping an Extension's Script
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
| File | + | − |
|---|---|---|
| src/backend/commands/extension.c | 107 | 0 |
| src/backend/parser/gram.y | 51 | 0 |
| src/bin/pg_dump/pg_dump.c | 187 | 0 |
| src/bin/pg_dump/pg_dump.h | 2 | 0 |
*** a/src/backend/commands/extension.c
--- b/src/backend/commands/extension.c
***************
*** 75,80 **** typedef struct ExtensionControlFile
--- 75,81 ----
bool superuser; /* must be superuser to install? */
int encoding; /* encoding of the script file, or -1 */
List *requires; /* names of prerequisite extensions */
+ char *script;
} ExtensionControlFile;
/*
***************
*** 577,586 **** parse_extension_control_file(ExtensionControlFile *control,
}
/*
! * Read the primary control file for the specified extension.
*/
static ExtensionControlFile *
! read_extension_control_file(const char *extname)
{
ExtensionControlFile *control;
--- 578,587 ----
}
/*
! * Create an ExtensionControlFile with default values.
*/
static ExtensionControlFile *
! default_extension_control_file(const char *extname)
{
ExtensionControlFile *control;
***************
*** 593,598 **** read_extension_control_file(const char *extname)
--- 594,610 ----
control->superuser = true;
control->encoding = -1;
+ return control;
+ }
+
+ /*
+ * Read the primary control file for the specified extension.
+ */
+ static ExtensionControlFile *
+ read_extension_control_file(const char *extname)
+ {
+ ExtensionControlFile *control = default_extension_control_file(extname);
+
/*
* Parse the primary control file.
*/
***************
*** 858,866 **** execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
CurrentExtensionObject = extensionOid;
PG_TRY();
{
! char *c_sql = read_extension_script_file(control, filename);
Datum t_sql;
/* We use various functions that want to operate on text datums */
t_sql = CStringGetTextDatum(c_sql);
--- 870,883 ----
CurrentExtensionObject = extensionOid;
PG_TRY();
{
! char *c_sql;
Datum t_sql;
+ if (control->script)
+ c_sql = control->script;
+ else
+ c_sql = read_extension_script_file(control, filename);
+
/* We use various functions that want to operate on text datums */
t_sql = CStringGetTextDatum(c_sql);
***************
*** 1178,1183 **** void
--- 1195,1203 ----
CreateExtension(CreateExtensionStmt *stmt)
{
DefElem *d_schema = NULL;
+ DefElem *d_script = NULL;
+ DefElem *d_requires = NULL;
+ DefElem *d_relocatable = NULL;
DefElem *d_new_version = NULL;
DefElem *d_old_version = NULL;
char *schemaName;
***************
*** 1229,1248 **** CreateExtension(CreateExtensionStmt *stmt)
errmsg("nested CREATE EXTENSION is not supported")));
/*
! * Read the primary control file. Note we assume that it does not contain
! * any non-ASCII data, so there is no need to worry about encoding at this
! * point.
! */
! pcontrol = read_extension_control_file(stmt->extname);
!
! /*
! * Read the statement option list
*/
foreach(lc, stmt->options)
{
DefElem *defel = (DefElem *) lfirst(lc);
! if (strcmp(defel->defname, "schema") == 0)
{
if (d_schema)
ereport(ERROR,
--- 1249,1288 ----
errmsg("nested CREATE EXTENSION is not supported")));
/*
! * Read the statement option list.
! *
! * We need to read some of the options to know what to do next: if the
! * "script" one is in use, we don't want to read any control file.
*/
foreach(lc, stmt->options)
{
DefElem *defel = (DefElem *) lfirst(lc);
! if (strcmp(defel->defname, "script") == 0)
! {
! if (d_script)
! ereport(ERROR,
! (errcode(ERRCODE_SYNTAX_ERROR),
! errmsg("conflicting or redundant options")));
! d_script = defel;
! }
! else if (strcmp(defel->defname, "relocatable") == 0)
! {
! if (d_relocatable)
! ereport(ERROR,
! (errcode(ERRCODE_SYNTAX_ERROR),
! errmsg("conflicting or redundant options")));
! d_relocatable = defel;
! }
! else if (strcmp(defel->defname, "requires") == 0)
! {
! if (d_requires)
! ereport(ERROR,
! (errcode(ERRCODE_SYNTAX_ERROR),
! errmsg("conflicting or redundant options")));
! d_requires = defel;
! }
! else if (strcmp(defel->defname, "schema") == 0)
{
if (d_schema)
ereport(ERROR,
***************
*** 1270,1275 **** CreateExtension(CreateExtensionStmt *stmt)
--- 1310,1364 ----
elog(ERROR, "unrecognized option: %s", defel->defname);
}
+ if (d_script)
+ {
+ /*
+ * We are given the extension's script in the SQL command, so create a
+ * control file structure in memory, we won't have a control file on
+ * disk to use.
+ */
+ pcontrol = default_extension_control_file(stmt->extname);
+ pcontrol->script = strVal(d_script->arg);
+
+ if (d_relocatable)
+ pcontrol->relocatable = intVal(d_relocatable->arg) != 0;
+
+ if (d_requires)
+ {
+ /* Need a modifiable copy of string */
+ char *rawnames = pstrdup(strVal(d_requires->arg));
+
+ /* Parse string into list of identifiers */
+ if (!SplitIdentifierString(rawnames, ',', &pcontrol->requires))
+ {
+ /* syntax error in name list */
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("parameter \"requires\" must be a list of extension names")));
+ }
+ }
+ }
+ else
+ {
+ /*
+ * If the extension script is not in the command, then the user is not
+ * the extension packager and we want to read about relocatable and
+ * requires in the control file, not in the SQL command.
+ */
+ if (d_relocatable || d_requires)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("parameter \"%s\" is only expected when using CREATE EXTENSION AS",
+ d_relocatable ? "relocatable" : "requires")));
+
+ /*
+ * Read the primary control file. Note we assume that it does not
+ * contain any non-ASCII data, so there is no need to worry about
+ * encoding at this point.
+ */
+ pcontrol = read_extension_control_file(stmt->extname);
+ }
+
/*
* Determine the version to install
*/
***************
*** 1332,1340 **** CreateExtension(CreateExtensionStmt *stmt)
}
/*
! * Fetch control parameters for installation target version
*/
! control = read_extension_aux_control_file(pcontrol, versionName);
/*
* Determine the target schema to install the extension into
--- 1421,1433 ----
}
/*
! * Fetch control parameters for installation target version. When the
! * script is given in the command string, no auxiliary file is expected.
*/
! if (pcontrol->script == NULL)
! control = read_extension_aux_control_file(pcontrol, versionName);
! else
! control = pcontrol;
/*
* Determine the target schema to install the extension into
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 3439,3444 **** DropTableSpaceStmt: DROP TABLESPACE name
--- 3439,3446 ----
* CREATE EXTENSION extension
* [ WITH ] [ SCHEMA schema ] [ VERSION version ] [ FROM oldversion ]
*
+ * CREATE EXTENSION extension ... AS $$ ... $$
+ *
*****************************************************************************/
CreateExtensionStmt: CREATE EXTENSION name opt_with create_extension_opt_list
***************
*** 3457,3462 **** CreateExtensionStmt: CREATE EXTENSION name opt_with create_extension_opt_list
--- 3459,3486 ----
n->options = $8;
$$ = (Node *) n;
}
+ | CREATE EXTENSION name opt_with create_extension_opt_list
+ AS Sconst
+ {
+ CreateExtensionStmt *n = makeNode(CreateExtensionStmt);
+ n->extname = $3;
+ n->if_not_exists = false;
+ n->options = lappend($5,
+ makeDefElem("script",
+ (Node *)makeString($7)));
+ $$ = (Node *) n;
+ }
+ | CREATE EXTENSION IF_P NOT EXISTS name
+ opt_with create_extension_opt_list AS Sconst
+ {
+ CreateExtensionStmt *n = makeNode(CreateExtensionStmt);
+ n->extname = $6;
+ n->if_not_exists = false;
+ n->options = lappend($8,
+ makeDefElem("script",
+ (Node *)makeString($10)));
+ $$ = (Node *) n;
+ }
;
create_extension_opt_list:
***************
*** 3479,3484 **** create_extension_opt_item:
--- 3503,3535 ----
{
$$ = makeDefElem("old_version", (Node *)makeString($2));
}
+ | IDENT Sconst
+ /*
+ * We handle identifiers that aren't parser keywords with
+ * the following special-case codes, to avoid bloating the
+ * size of the main parser.
+ */
+ {
+ if (strcmp($1, "requires") == 0)
+ $$ = makeDefElem("requires", (Node *)makeString($2));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unrecognized extension option \"%s\"", $1),
+ parser_errposition(@1)));
+ }
+ | IDENT
+ {
+ if (strcmp($1, "relocatable") == 0)
+ $$ = makeDefElem("relocatable", (Node *)makeInteger(TRUE));
+ else if (strcmp($1, "norelocatable") == 0)
+ $$ = makeDefElem("relocatable", (Node *)makeInteger(FALSE));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unrecognized extension option \"%s\"", $1),
+ parser_errposition(@1)));
+ }
;
/*****************************************************************************
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
***************
*** 119,124 **** static SimpleOidList table_exclude_oids = {NULL, NULL};
--- 119,127 ----
static SimpleStringList tabledata_exclude_patterns = {NULL, NULL};
static SimpleOidList tabledata_exclude_oids = {NULL, NULL};
+ static SimpleStringList extension_include_patterns = {NULL, NULL};
+ static SimpleOidList extension_include_oids = {NULL, NULL};
+
/* default, if no "inclusion" switches appear, is to dump everything */
static bool include_everything = true;
***************
*** 150,155 **** static void expand_schema_name_patterns(Archive *fout,
--- 153,161 ----
static void expand_table_name_patterns(Archive *fout,
SimpleStringList *patterns,
SimpleOidList *oids);
+ static void expand_extension_name_patterns(Archive *fout,
+ SimpleStringList *patterns,
+ SimpleOidList *oids);
static NamespaceInfo *findNamespace(Archive *fout, Oid nsoid, Oid objoid);
static void dumpTableData(Archive *fout, TableDataInfo *tdinfo);
static void guessConstraintInheritance(TableInfo *tblinfo, int numTables);
***************
*** 165,173 **** static void dumpSecLabel(Archive *fout, const char *target,
static int findSecLabels(Archive *fout, Oid classoid, Oid objoid,
SecLabelItem **items);
static int collectSecLabels(Archive *fout, SecLabelItem **items);
! static void dumpDumpableObject(Archive *fout, DumpableObject *dobj);
static void dumpNamespace(Archive *fout, NamespaceInfo *nspinfo);
! static void dumpExtension(Archive *fout, ExtensionInfo *extinfo);
static void dumpType(Archive *fout, TypeInfo *tyinfo);
static void dumpBaseType(Archive *fout, TypeInfo *tyinfo);
static void dumpEnumType(Archive *fout, TypeInfo *tyinfo);
--- 171,181 ----
static int findSecLabels(Archive *fout, Oid classoid, Oid objoid,
SecLabelItem **items);
static int collectSecLabels(Archive *fout, SecLabelItem **items);
! static void dumpDumpableObject(Archive *fout, DumpableObject *dobj,
! DumpableObject **dobjs, int numObjs);
static void dumpNamespace(Archive *fout, NamespaceInfo *nspinfo);
! static void dumpExtension(Archive *fout, ExtensionInfo *extinfo,
! DumpableObject **dobjs, int numObjs);
static void dumpType(Archive *fout, TypeInfo *tyinfo);
static void dumpBaseType(Archive *fout, TypeInfo *tyinfo);
static void dumpEnumType(Archive *fout, TypeInfo *tyinfo);
***************
*** 322,327 **** main(int argc, char **argv)
--- 330,336 ----
{"superuser", required_argument, NULL, 'S'},
{"table", required_argument, NULL, 't'},
{"exclude-table", required_argument, NULL, 'T'},
+ {"extension-script", required_argument, NULL, 'X'},
{"no-password", no_argument, NULL, 'w'},
{"password", no_argument, NULL, 'W'},
{"username", required_argument, NULL, 'U'},
***************
*** 388,394 **** main(int argc, char **argv)
}
}
! while ((c = getopt_long(argc, argv, "abcCE:f:F:h:in:N:oOp:RsS:t:T:U:vwWxZ:",
long_options, &optindex)) != -1)
{
switch (c)
--- 397,403 ----
}
}
! while ((c = getopt_long(argc, argv, "abcCE:f:F:h:in:N:oOp:RsS:t:T:U:vwWxX:Z:",
long_options, &optindex)) != -1)
{
switch (c)
***************
*** 471,476 **** main(int argc, char **argv)
--- 480,489 ----
simple_string_list_append(&table_exclude_patterns, optarg);
break;
+ case 'X': /* include extension(s) script */
+ simple_string_list_append(&extension_include_patterns, optarg);
+ break;
+
case 'U':
username = pg_strdup(optarg);
break;
***************
*** 670,675 **** main(int argc, char **argv)
--- 683,692 ----
expand_table_name_patterns(fout, &tabledata_exclude_patterns,
&tabledata_exclude_oids);
+ /* Expand extension selection patterns into OID lists */
+ expand_extension_name_patterns(fout, &extension_include_patterns,
+ &extension_include_oids);
+
/* non-matching exclusion patterns aren't an error */
/*
***************
*** 746,752 **** main(int argc, char **argv)
/* Now the rearrangeable objects. */
for (i = 0; i < numObjs; i++)
! dumpDumpableObject(fout, dobjs[i]);
/*
* Set up options info to ensure we dump what we want.
--- 763,769 ----
/* Now the rearrangeable objects. */
for (i = 0; i < numObjs; i++)
! dumpDumpableObject(fout, dobjs[i], dobjs, numObjs);
/*
* Set up options info to ensure we dump what we want.
***************
*** 830,835 **** help(const char *progname)
--- 847,853 ----
printf(_(" -S, --superuser=NAME superuser user name to use in plain-text format\n"));
printf(_(" -t, --table=TABLE dump the named table(s) only\n"));
printf(_(" -T, --exclude-table=TABLE do NOT dump the named table(s)\n"));
+ printf(_(" -X, --extension-script dunp named extension(s) scripts\n"));
printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
***************
*** 1062,1067 **** expand_table_name_patterns(Archive *fout,
--- 1080,1132 ----
}
/*
+ * Find the OIDs of all extensions matching the given list of patterns,
+ * and append them to the given ExtensionMembers list.
+ */
+ static void
+ expand_extension_name_patterns(Archive *fout,
+ SimpleStringList *patterns,
+ SimpleOidList *oids)
+ {
+ PQExpBuffer query;
+ PGresult *res;
+ SimpleStringListCell *cell;
+ int i;
+
+ if (patterns->head == NULL)
+ return; /* nothing to do */
+
+ query = createPQExpBuffer();
+
+ /*
+ * We use UNION ALL rather than UNION; this might sometimes result in
+ * duplicate entries in the OID list, but we don't care.
+ */
+
+ for (cell = patterns->head; cell; cell = cell->next)
+ {
+ if (cell != patterns->head)
+ appendPQExpBuffer(query, "UNION ALL\n");
+ appendPQExpBuffer(query,
+ "SELECT e.oid"
+ "\nFROM pg_catalog.pg_extension e\n");
+ processSQLNamePattern(GetConnection(fout), query,
+ cell->val, false, false,
+ NULL, "e.extname", NULL, NULL);
+ }
+
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+
+ for (i = 0; i < PQntuples(res); i++)
+ {
+ simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
+ }
+
+ PQclear(res);
+ destroyPQExpBuffer(query);
+ }
+
+ /*
* selectDumpableNamespace: policy-setting subroutine
* Mark a namespace as to be dumped or not
*/
***************
*** 1208,1213 **** selectDumpableExtension(ExtensionInfo *extinfo)
--- 1273,1286 ----
extinfo->dobj.dump = false;
else
extinfo->dobj.dump = include_everything;
+
+ /*
+ * In any case, an extension can be included an inclusion switch
+ */
+ if (extension_include_oids.head &&
+ simple_oid_list_member(&extension_include_oids,
+ extinfo->dobj.catId.oid))
+ extinfo->dobj.dump = true;
}
/*
***************
*** 2737,2742 **** getExtensions(Archive *fout, int *numExtensions)
--- 2810,2816 ----
int i_extversion;
int i_extconfig;
int i_extcondition;
+ int i_extrequires;
/*
* Before 9.1, there are no extensions.
***************
*** 2752,2761 **** getExtensions(Archive *fout, int *numExtensions)
/* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog");
! appendPQExpBuffer(query, "SELECT x.tableoid, x.oid, "
! "x.extname, n.nspname, x.extrelocatable, x.extversion, x.extconfig, x.extcondition "
! "FROM pg_extension x "
! "JOIN pg_namespace n ON n.oid = x.extnamespace");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
--- 2826,2842 ----
/* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog");
! /* Get the extension and its requirements: extensions it depends on */
! appendPQExpBuffer(query,
! "SELECT x.tableoid, x.oid, x.extname, n.nspname, "
! "x.extrelocatable, x.extversion, x.extconfig, "
! "x.extcondition, "
! "array_to_string(array_agg(e.extname), ',') as extrequires "
! "FROM pg_extension x JOIN pg_namespace n ON n.oid = x.extnamespace "
! "LEFT JOIN pg_depend d on d.objid = x.oid "
! "and d.refclassid = 'pg_extension'::regclass "
! "LEFT JOIN pg_extension e ON e.oid = d.refobjid "
! "group by 1, 2, 3, 4, 5, 6, 7, 8");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
***************
*** 2771,2776 **** getExtensions(Archive *fout, int *numExtensions)
--- 2852,2858 ----
i_extversion = PQfnumber(res, "extversion");
i_extconfig = PQfnumber(res, "extconfig");
i_extcondition = PQfnumber(res, "extcondition");
+ i_extrequires = PQfnumber(res, "extrequires");
for (i = 0; i < ntups; i++)
{
***************
*** 2784,2789 **** getExtensions(Archive *fout, int *numExtensions)
--- 2866,2872 ----
extinfo[i].extversion = pg_strdup(PQgetvalue(res, i, i_extversion));
extinfo[i].extconfig = pg_strdup(PQgetvalue(res, i, i_extconfig));
extinfo[i].extcondition = pg_strdup(PQgetvalue(res, i, i_extcondition));
+ extinfo[i].extrequires = pg_strdup(PQgetvalue(res, i, i_extrequires));
/* Decide whether we want to dump it */
selectDumpableExtension(&(extinfo[i]));
***************
*** 7248,7254 **** collectComments(Archive *fout, CommentItem **items)
* ArchiveEntries (TOC objects) for each object to be dumped.
*/
static void
! dumpDumpableObject(Archive *fout, DumpableObject *dobj)
{
switch (dobj->objType)
{
--- 7331,7338 ----
* ArchiveEntries (TOC objects) for each object to be dumped.
*/
static void
! dumpDumpableObject(Archive *fout, DumpableObject *dobj,
! DumpableObject **dobjs, int numObjs)
{
switch (dobj->objType)
{
***************
*** 7256,7262 **** dumpDumpableObject(Archive *fout, DumpableObject *dobj)
dumpNamespace(fout, (NamespaceInfo *) dobj);
break;
case DO_EXTENSION:
! dumpExtension(fout, (ExtensionInfo *) dobj);
break;
case DO_TYPE:
dumpType(fout, (TypeInfo *) dobj);
--- 7340,7346 ----
dumpNamespace(fout, (NamespaceInfo *) dobj);
break;
case DO_EXTENSION:
! dumpExtension(fout, (ExtensionInfo *) dobj, dobjs, numObjs);
break;
case DO_TYPE:
dumpType(fout, (TypeInfo *) dobj);
***************
*** 7431,7444 **** dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
* writes out to fout the queries to recreate an extension
*/
static void
! dumpExtension(Archive *fout, ExtensionInfo *extinfo)
{
PQExpBuffer q;
PQExpBuffer delq;
PQExpBuffer labelq;
char *qextname;
- /* Skip if not to be dumped */
if (!extinfo->dobj.dump || dataOnly)
return;
--- 7515,7528 ----
* writes out to fout the queries to recreate an extension
*/
static void
! dumpExtension(Archive *fout, ExtensionInfo *extinfo,
! DumpableObject **dobjs, int numObjs)
{
PQExpBuffer q;
PQExpBuffer delq;
PQExpBuffer labelq;
char *qextname;
if (!extinfo->dobj.dump || dataOnly)
return;
***************
*** 7450,7456 **** dumpExtension(Archive *fout, ExtensionInfo *extinfo)
appendPQExpBuffer(delq, "DROP EXTENSION %s;\n", qextname);
! if (!binary_upgrade)
{
/*
* In a regular dump, we use IF NOT EXISTS so that there isn't a
--- 7534,7611 ----
appendPQExpBuffer(delq, "DROP EXTENSION %s;\n", qextname);
! /* dump this extension's content */
! if (extension_include_oids.head
! && simple_oid_list_member(&extension_include_oids,
! extinfo->dobj.catId.oid))
! {
! Archive *eout; /* the extension's script file */
! ArchiveHandle *EH;
! TocEntry *te;
! int i;
!
! /* See comment for !binary_upgrade case for IF NOT EXISTS. */
! appendPQExpBuffer(q,
! "CREATE EXTENSION IF NOT EXISTS %s\n"
! " WITH SCHEMA %s\n"
! " VERSION '%s'\n"
! " %s\n"
! " REQUIRES '%s'\n"
! "AS $%s$\n",
! qextname,
! fmtId(extinfo->namespace),
! extinfo->extversion,
! extinfo->relocatable ? "relocatable":"norelocatable",
! extinfo->extrequires,
! qextname);
!
! /*
! * Have another archive for this extension: this allows us to simply
! * walk the extension's dependencies and use the existing pg_dump code
! * to get the object create statement to be added in the script.
! *
! */
! eout = CreateArchive(NULL, archNull, 0, archModeAppend);
!
! EH = (ArchiveHandle *) eout;
!
! /* grab existing connection and remote version information */
! EH->connection = ((ArchiveHandle *)fout)->connection;
! eout->remoteVersion = fout->remoteVersion;
!
! /* dump all objects for this extension, that have been sorted out in
! * the right order following dependencies etc */
! for (i = 0; i < numObjs; i++)
! {
! DumpableObject *dobj = dobjs[i];
!
! if (dobj->ext_member
! && dobj->extension_oid == extinfo->dobj.catId.oid)
! {
! bool dump = dobj->dump;
!
! /* force the DumpableObject here to be dumped */
! dobj->dump = true;
!
! /* Dump the Object */
! dumpDumpableObject(eout, dobj, dobjs, numObjs);
!
! /* now restore its old dump flag value */
! dobj->dump = dump;
! }
! }
!
! /* restore the eout Archive into the local buffer */
! for (te = EH->toc->next; te != EH->toc; te = te->next)
! {
! if (strlen(te->defn) > 0)
! appendPQExpBuffer(q, "%s", te->defn);
! }
! CloseArchive(eout);
!
! appendPQExpBuffer(q, "$%s$;\n", qextname);
! }
! else if (!binary_upgrade)
{
/*
* In a regular dump, we use IF NOT EXISTS so that there isn't a
***************
*** 14101,14106 **** getExtensionMembership(Archive *fout, ExtensionInfo extinfo[],
--- 14256,14280 ----
dobj->ext_member = true;
+ /* track the extension Oid in the object for later processing */
+ if (extension_include_oids.head
+ && simple_oid_list_member(&extension_include_oids, refobjId.oid))
+ {
+ dobj->extension_oid = refobjId.oid;
+ }
+
+ /* The Shell Type needs to be in the --extension-script */
+ if (dobj->objType == DO_TYPE)
+ {
+ TypeInfo *typeInfo = (TypeInfo *) dobj;
+
+ if (typeInfo->shellType)
+ {
+ typeInfo->shellType->dobj.ext_member = true;
+ typeInfo->shellType->dobj.extension_oid = dobj->extension_oid;
+ }
+ }
+
/*
* Normally, mark the member object as not to be dumped. But in
* binary upgrades, we still dump the members individually, since the
*** a/src/bin/pg_dump/pg_dump.h
--- b/src/bin/pg_dump/pg_dump.h
***************
*** 133,138 **** typedef struct _dumpableObject
--- 133,139 ----
struct _namespaceInfo *namespace; /* containing namespace, or NULL */
bool dump; /* true if we want to dump this object */
bool ext_member; /* true if object is member of extension */
+ Oid extension_oid; /* Oid of the extension woning this object */
DumpId *dependencies; /* dumpIds of objects this one depends on */
int nDeps; /* number of valid dependencies */
int allocDeps; /* allocated size of dependencies[] */
***************
*** 151,156 **** typedef struct _extensionInfo
--- 152,158 ----
char *namespace; /* schema containing extension's objects */
bool relocatable;
char *extversion;
+ char *extrequires;
char *extconfig; /* info about configuration tables */
char *extcondition;
} ExtensionInfo;