Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdcb467b

Browse files
committed
Fix pg_dump handling of extension config tables
Since 9.1, we've provided extensions with a way to denote"configuration" tables- tables created by an extension which the usermay modify. By marking these as "configuration" tables, the extensionis asking for the data in these tables to be pg_dump'd (tables whichare not marked in this way are assumed to be entirely handled duringCREATE EXTENSION and are not included at all in a pg_dump).Unfortunately, pg_dump neglected to consider foreign key relationshipsbetween extension configuration tables and therefore could end uptrying to reload the data in an order which would cause FK violations.This patch teaches pg_dump about these dependencies, so that the datadumped out is done so in the best order possible. Note that there's noway to handle circular dependencies, but those have yet to be seen inthe wild.The release notes for this should include a caution to users thatexisting pg_dump-based backups may be invalid due to this issue. Thedata is all there, but restoring from it will require extracting thedata for the configuration tables and then loading them in the correctorder by hand.Discussed initially back in bug #6738, more recently brought up byGilles Darold, who provided an initial patch which was further reworkedby Michael Paquier. Further modifications and documentation updatesby me.Back-patch to 9.1 where we added the concept of extension configurationtables.
1 parent1c96685 commitdcb467b

File tree

2 files changed

+90
-1
lines changed

2 files changed

+90
-1
lines changed

‎doc/src/sgml/extend.sgml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,17 @@ SELECT pg_catalog.pg_extension_config_dump('my_config', 'WHERE NOT standard_entr
714714
a table as no longer a configuration table is to dissociate it from the
715715
extension with <command>ALTER EXTENSION ... DROP TABLE</>.
716716
</para>
717+
718+
<para>
719+
Note that foreign key relationships between these tables will dictate the
720+
order in which the tables are dumped out by pg_dump. Specifically, pg_dump
721+
will attempt to dump the referenced-by table before the referencing table.
722+
As the foreign key relationships are set up at CREATE EXTENSION time (prior
723+
to data being loaded into the tables) circular dependencies are not
724+
supported. When circular dependencies exist, the data will still be dumped
725+
out but the dump will not be able to be restored directly and user
726+
intervention will be required.
727+
</para>
717728
</sect2>
718729

719730
<sect2>

‎src/bin/pg_dump/pg_dump.c

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13739,6 +13739,33 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
1373913739

1374013740
/*
1374113741
* getExtensionMembership --- obtain extension membership data
13742+
*
13743+
* There are three main parts to this process:
13744+
*
13745+
* 1. Identify objects which are members of extensions
13746+
*
13747+
* Generally speaking, this is to mark them as *not* being dumped, as most
13748+
* extension objects are created by the single CREATE EXTENSION command.
13749+
* The one exception is binary upgrades with pg_upgrade will still dump the
13750+
* non-table objects.
13751+
*
13752+
* 2. Identify and create dump records for extension configuration tables.
13753+
*
13754+
* Extensions can mark tables as "configuration", which means that the user
13755+
* is able and expected to modify those tables after the extension has been
13756+
* loaded. For these tables, we dump out only the data- the structure is
13757+
* expected to be handled at CREATE EXTENSION time, including any indexes or
13758+
* foriegn keys, which brings us to-
13759+
*
13760+
* 3. Record FK dependencies between configuration tables.
13761+
*
13762+
* Due to the FKs being created at CREATE EXTENSION time and therefore before
13763+
* the data is loaded, we have to work out what the best order for reloading
13764+
* the data is, to avoid FK violations when the tables are restored. This is
13765+
* not perfect- we can't handle circular dependencies and if any exist they
13766+
* will cause an invalid dump to be produced (though at least all of the data
13767+
* is included for a user to manually restore). This is currently documented
13768+
* but perhaps we can provide a better solution in the future.
1374213769
*/
1374313770
void
1374413771
getExtensionMembership(ExtensionInfoextinfo[],intnumExtensions)
@@ -13750,7 +13777,9 @@ getExtensionMembership(ExtensionInfo extinfo[], int numExtensions)
1375013777
inti_classid,
1375113778
i_objid,
1375213779
i_refclassid,
13753-
i_refobjid;
13780+
i_refobjid,
13781+
i_conrelid,
13782+
i_confrelid;
1375413783
DumpableObject*dobj,
1375513784
*refdobj;
1375613785

@@ -13929,6 +13958,55 @@ getExtensionMembership(ExtensionInfo extinfo[], int numExtensions)
1392913958
free(extconditionarray);
1393013959
}
1393113960

13961+
/*
13962+
* Now that all the TableInfoData objects have been created for all
13963+
* the extensions, check their FK dependencies and register them to
13964+
* try and dump the data out in an order which they can be restored
13965+
* in.
13966+
*
13967+
* Note that this is not a problem for user tables as their FKs are
13968+
* recreated after the data has been loaded.
13969+
*/
13970+
printfPQExpBuffer(query,
13971+
"SELECT conrelid, confrelid "
13972+
"FROM pg_constraint "
13973+
"JOIN pg_depend ON (objid = confrelid) "
13974+
"WHERE contype = 'f' "
13975+
"AND refclassid = 'pg_extension'::regclass "
13976+
"AND classid = 'pg_class'::regclass;");
13977+
13978+
res=PQexec(g_conn,query->data);
13979+
check_sql_result(res,g_conn,query->data,PGRES_TUPLES_OK);
13980+
13981+
ntups=PQntuples(res);
13982+
13983+
i_conrelid=PQfnumber(res,"conrelid");
13984+
i_confrelid=PQfnumber(res,"confrelid");
13985+
13986+
/* Now get the dependencies and register them */
13987+
for (i=0;i<ntups;i++)
13988+
{
13989+
Oidconrelid,confrelid;
13990+
TableInfo*reftable,*contable;
13991+
13992+
conrelid=atooid(PQgetvalue(res,i,i_conrelid));
13993+
confrelid=atooid(PQgetvalue(res,i,i_confrelid));
13994+
contable=findTableByOid(conrelid);
13995+
reftable=findTableByOid(confrelid);
13996+
13997+
if (reftable==NULL||
13998+
reftable->dataObj==NULL||
13999+
contable==NULL||
14000+
contable->dataObj==NULL)
14001+
continue;
14002+
14003+
/*
14004+
* Make referencing TABLE_DATA object depend on the
14005+
* referenced table's TABLE_DATA object.
14006+
*/
14007+
addObjectDependency(&contable->dataObj->dobj,
14008+
reftable->dataObj->dobj.dumpId);
14009+
}
1393214010
destroyPQExpBuffer(query);
1393314011
}
1393414012

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp