From 8005cffd08c57b77564bb0294d8ebd4600bc1dcf Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Tue, 17 Feb 2015 07:39:23 +0000
Subject: [PATCH 1/3] Fix ordering of tables part of extensions linked with
 constraints

The same mechanism as data-only dumps ensuring that data is loaded
respecting foreign key constains is used if it at least one dumped
object is found as being part of an extension. This commit reinforces
as well a couple of code paths to not dump objects that are directly
part of an extension.

Patch by Gilles Darold.
---
 src/bin/pg_dump/pg_dump.c | 99 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 83 insertions(+), 16 deletions(-)

diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 7e92b74..c95ae3d 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -208,7 +208,8 @@ static void addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
 						DumpableObject *boundaryObjs);
 
 static void getDomainConstraints(Archive *fout, TypeInfo *tyinfo);
-static void getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, bool oids);
+static void getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables,
+						 bool oids, bool *has_ext_member);
 static void makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo, bool oids);
 static void buildMatViewRefreshDependencies(Archive *fout);
 static void getTableDataFKConstraints(void);
@@ -730,9 +731,12 @@ main(int argc, char **argv)
 
 	if (!dopt.schemaOnly)
 	{
-		getTableData(&dopt, tblinfo, numTables, dopt.oids);
+		bool has_ext_member = false;
+
+		getTableData(&dopt, tblinfo, numTables, dopt.oids, &has_ext_member);
 		buildMatViewRefreshDependencies(fout);
-		if (dopt.dataOnly)
+
+		if (dopt.dataOnly || has_ext_member)
 			getTableDataFKConstraints();
 	}
 
@@ -1866,7 +1870,8 @@ refreshMatViewData(Archive *fout, TableDataInfo *tdinfo)
  *	  set up dumpable objects representing the contents of tables
  */
 static void
-getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, bool oids)
+getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables,
+			 bool oids, bool *has_ext_member)
 {
 	int			i;
 
@@ -1874,6 +1879,8 @@ getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, bool oids)
 	{
 		if (tblinfo[i].dobj.dump)
 			makeTableDataInfo(dopt, &(tblinfo[i]), oids);
+		if (!(*has_ext_member) && tblinfo[i].dobj.ext_member)
+			*has_ext_member = true;
 	}
 }
 
@@ -2052,13 +2059,15 @@ buildMatViewRefreshDependencies(Archive *fout)
  * getTableDataFKConstraints -
  *	  add dump-order dependencies reflecting foreign key constraints
  *
- * This code is executed only in a data-only dump --- in schema+data dumps
- * we handle foreign key issues by not creating the FK constraints until
- * after the data is loaded.  In a data-only dump, however, we want to
- * order the table data objects in such a way that a table's referenced
- * tables are restored first.  (In the presence of circular references or
- * self-references this may be impossible; we'll detect and complain about
- * that during the dependency sorting step.)
+ * This code is executed only in a data-only dump or when an object dumped
+ * is part of an extension -- in schema+data dumps we handle foreign key
+ * issues by not creating the FK constraints until after the data is loaded.
+ * In a data-only dump or when there is an extension member to dump (schema
+ * dumps do not include extension objects, they are created with CREATE
+ * EXTENSION), we want to order the table data objects in such a way that
+ * a table's referenced tables are restored first.  (In the presence of
+ * circular references or self-references this may be impossible; we'll
+ * detect and complain about that during the dependency sorting step.)
  */
 static void
 getTableDataFKConstraints(void)
@@ -2951,9 +2960,14 @@ dumpPolicy(Archive *fout, DumpOptions *dopt, PolicyInfo *polinfo)
 	PQExpBuffer delqry;
 	const char *cmd;
 
+	/* Policies are SCHEMA not data */
 	if (dopt->dataOnly)
 		return;
 
+	/* Ignore extension members */
+	if (tbinfo->dobj.ext_member)
+		return;
+
 	/*
 	 * If polname is NULL, then this record is just indicating that ROW
 	 * LEVEL SECURITY is enabled for the table. Dump as ALTER TABLE <table>
@@ -7910,6 +7924,10 @@ dumpTableComment(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo,
 	if (dopt->dataOnly)
 		return;
 
+	/* Ignore extension members */
+	if (tbinfo->dobj.ext_member)
+		return;
+
 	/* Search for comments associated with relation, using table */
 	ncomments = findComments(fout,
 							 tbinfo->dobj.catId.tableoid,
@@ -13118,6 +13136,10 @@ dumpTableSecLabel(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo, const cha
 	if (dopt->dataOnly)
 		return;
 
+	/* Ignore extension members */
+	if (tbinfo->dobj.ext_member)
+		return;
+
 	/* Search for comments associated with relation, using table */
 	nlabels = findSecLabels(fout,
 							tbinfo->dobj.catId.tableoid,
@@ -13325,7 +13347,7 @@ collectSecLabels(Archive *fout, SecLabelItem **items)
 static void
 dumpTable(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo)
 {
-	if (tbinfo->dobj.dump && !dopt->dataOnly)
+	if (tbinfo->dobj.dump && !dopt->dataOnly && !tbinfo->dobj.ext_member)
 	{
 		char	   *namecopy;
 
@@ -13463,6 +13485,10 @@ dumpTableSchema(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo)
 	int			j,
 				k;
 
+	/* Ignore extension members */
+	if (tbinfo->dobj.ext_member)
+		return;
+
 	/* Make sure we are in proper schema */
 	selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
 
@@ -14097,6 +14123,14 @@ dumpAttrDef(Archive *fout, DumpOptions *dopt, AttrDefInfo *adinfo)
 	if (!tbinfo->dobj.dump || dopt->dataOnly)
 		return;
 
+	/* Ignore extension members */
+	if (tbinfo->dobj.ext_member)
+		return;
+
+	/* Ignore extension members */
+	if (tbinfo->dobj.ext_member)
+		return;
+
 	/* Skip if not "separate"; it was dumped in the table's definition */
 	if (!adinfo->separate)
 		return;
@@ -14184,6 +14218,10 @@ dumpIndex(Archive *fout, DumpOptions *dopt, IndxInfo *indxinfo)
 	if (dopt->dataOnly)
 		return;
 
+	/* Ignore extension members */
+	if (tbinfo->dobj.ext_member)
+		return;
+
 	q = createPQExpBuffer();
 	delq = createPQExpBuffer();
 	labelq = createPQExpBuffer();
@@ -14273,6 +14311,10 @@ dumpConstraint(Archive *fout, DumpOptions *dopt, ConstraintInfo *coninfo)
 	if (!coninfo->dobj.dump || dopt->dataOnly)
 		return;
 
+	/* Ignore extension members */
+	if (tbinfo != NULL && tbinfo->dobj.ext_member)
+		return;
+
 	q = createPQExpBuffer();
 	delq = createPQExpBuffer();
 
@@ -14497,7 +14539,13 @@ static void
 dumpTableConstraintComment(Archive *fout, DumpOptions *dopt, ConstraintInfo *coninfo)
 {
 	TableInfo  *tbinfo = coninfo->contable;
-	PQExpBuffer labelq = createPQExpBuffer();
+	PQExpBuffer labelq;
+
+	/* Ignore extension members */
+	if (tbinfo->dobj.ext_member)
+		return;
+
+	labelq = createPQExpBuffer();
 
 	appendPQExpBuffer(labelq, "CONSTRAINT %s ",
 					  fmtId(coninfo->dobj.name));
@@ -14574,9 +14622,17 @@ dumpSequence(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo)
 	char		bufm[100],
 				bufx[100];
 	bool		cycled;
-	PQExpBuffer query = createPQExpBuffer();
-	PQExpBuffer delqry = createPQExpBuffer();
-	PQExpBuffer labelq = createPQExpBuffer();
+	PQExpBuffer query;
+	PQExpBuffer delqry;
+	PQExpBuffer labelq;
+
+	/* Ignore extension members */
+	if (tbinfo->dobj.ext_member)
+		return;
+
+	query = createPQExpBuffer();
+	delqry = createPQExpBuffer();
+	labelq = createPQExpBuffer();
 
 	/* Make sure we are in proper schema */
 	selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
@@ -14841,6 +14897,10 @@ dumpTrigger(Archive *fout, DumpOptions *dopt, TriggerInfo *tginfo)
 	if (dopt->dataOnly)
 		return;
 
+	/* Ignore extension members */
+	if (tbinfo->dobj.ext_member)
+		return;
+
 	query = createPQExpBuffer();
 	delqry = createPQExpBuffer();
 	labelq = createPQExpBuffer();
@@ -15117,6 +15177,10 @@ dumpRule(Archive *fout, DumpOptions *dopt, RuleInfo *rinfo)
 	if (!rinfo->dobj.dump || dopt->dataOnly)
 		return;
 
+	/* Ignore extension members */
+	if (tbinfo->dobj.ext_member)
+		return;
+
 	/*
 	 * If it is an ON SELECT rule that is created implicitly by CREATE VIEW,
 	 * we do not want to dump it as a separate object.
@@ -15407,6 +15471,9 @@ getExtensionMembership(Archive *fout, DumpOptions *dopt, ExtensionInfo extinfo[]
 
 				if (dumpobj)
 				{
+					/* Mark member table as dumpable */
+					configtbl->dobj.dump = true;
+
 					/*
 					 * Note: config tables are dumped without OIDs regardless
 					 * of the --oids setting.  This is because row filtering
-- 
2.3.0

