From 72e369ee725301003cf065b0bf9875724455dac1 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

Additional checks on FK constraints potentially linking between them
extension objects are done and data dump ordering is ensured. Note
that this does not take into account foreign keys of tables that are
not part of an extension linking to an extension table.
---
 src/bin/pg_dump/pg_dump.c | 80 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 78 insertions(+), 2 deletions(-)

diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 2b53c72..bbcd600 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -15236,7 +15236,8 @@ dumpRule(Archive *fout, DumpOptions *dopt, RuleInfo *rinfo)
 }
 
 /*
- * getExtensionMembership --- obtain extension membership data
+ * getExtensionMembership --- obtain extension membership data and check FK
+ * dependencies among extension tables.
  */
 void
 getExtensionMembership(Archive *fout, DumpOptions *dopt, ExtensionInfo extinfo[],
@@ -15368,7 +15369,9 @@ getExtensionMembership(Archive *fout, DumpOptions *dopt, ExtensionInfo extinfo[]
 		  parsePGArray(extcondition, &extconditionarray, &nconditionitems) &&
 			nconfigitems == nconditionitems)
 		{
-			int			j;
+			int			j, i_conrelid, i_confrelid;
+			PQExpBuffer query2;
+			bool		first_elt = true;
 
 			for (j = 0; j < nconfigitems; j++)
 			{
@@ -15423,6 +15426,79 @@ getExtensionMembership(Archive *fout, DumpOptions *dopt, ExtensionInfo extinfo[]
 					}
 				}
 			}
+
+			/*
+			 * Now that all the TableInfoData objects have been created for
+			 * all the extensions, check their FK dependencies and register
+			 * them to ensure correct data ordering.  Note that this is not
+			 * a problem for user tables not included in an extension
+			 * referencing with a FK tables in extensions as their constraint
+			 * is declared after dumping their data. In --data-only mode the
+			 * table ordering is ensured as well thanks to
+			 * getTableDataFKConstraints().
+			 */
+			query2 = createPQExpBuffer();
+
+			/*
+			 * Query all the foreign key dependencies for all the extension
+			 * tables found previously. Only tables whose data need to be
+			 * have to be tracked.
+			 */
+			appendPQExpBuffer(query2,
+					  "SELECT conrelid, confrelid "
+					  "FROM pg_catalog.pg_constraint "
+					  "WHERE contype = 'f' AND conrelid IN (");
+
+			for (j = 0; j < nconfigitems; j++)
+			{
+				TableInfo  *configtbl;
+				Oid			configtbloid = atooid(extconfigarray[j]);
+
+				configtbl = findTableByOid(configtbloid);
+				if (configtbl == NULL || configtbl->dataObj == NULL)
+					continue;
+
+				if (first_elt)
+				{
+					appendPQExpBuffer(query2, "%u", configtbloid);
+					first_elt = false;
+				}
+				else
+					appendPQExpBuffer(query2, ", %u", configtbloid);
+			}
+			appendPQExpBuffer(query2, ");");
+
+			res = ExecuteSqlQuery(fout, query2->data, PGRES_TUPLES_OK);
+			ntups = PQntuples(res);
+
+			i_conrelid = PQfnumber(res, "conrelid");
+			i_confrelid = PQfnumber(res, "confrelid");
+
+			/* Now get the dependencies and register them */
+			for (j = 0; j < ntups; j++)
+			{
+				Oid			conrelid, confrelid;
+				TableInfo  *reftable, *contable;
+
+				conrelid = atooid(PQgetvalue(res, j, i_conrelid));
+				confrelid = atooid(PQgetvalue(res, j, i_confrelid));
+				contable = findTableByOid(conrelid);
+				reftable = findTableByOid(confrelid);
+
+				if (reftable == NULL ||
+					reftable->dataObj == NULL ||
+					contable == NULL ||
+					contable->dataObj == NULL)
+					continue;
+
+				/*
+				 * Make referencing TABLE_DATA object depend on the
+				 * referenced table's TABLE_DATA object.
+				 */
+				addObjectDependency(&contable->dataObj->dobj,
+									reftable->dataObj->dobj.dumpId);
+			}
+			resetPQExpBuffer(query2);
 		}
 		if (extconfigarray)
 			free(extconfigarray);
-- 
2.3.0

