From 006f42c74d46505b2b4dc753be25c91b0f9efec5 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 28 Oct 2007 19:08:02 +0000
Subject: [PATCH] Fix a couple of issues with pg_dump's handling of inheritance
 child tables that have default expressions different from their parent. 
 First, if the parent table's default expression has to be split out as a
 separate ALTER TABLE command, we need a dependency constraint to ensure that
 the child's command is given second.  This is because the ALTER TABLE on the
 parent will propagate to the child.  (We can't prevent that by using ONLY on
 the parent's command, since it's possible that other children exist that
 should receive the inherited default.)  Second, if the child has a NULL
 default where the parent does not, we have to explicitly say DEFAULT NULL on
 the child in order for this state to be preserved after reload.  (The latter
 actually doesn't work right because of a backend bug, but that is a separate
 issue.)

Backpatch as far as 8.0.  7.x pg_dump has enough issues with altered tables
(due to lack of dependency analysis) that trying to fix this one doesn't seem
very productive.
---
 src/bin/pg_dump/common.c | 52 +++++++++++++++++++++++++++++++++-------
 1 file changed, 43 insertions(+), 9 deletions(-)

diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 639f2b92f9d..b9451055cff 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.98 2007/09/23 23:39:36 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.99 2007/10/28 19:08:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -326,19 +326,53 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
 
 				if (inhAttrInd != -1)
 				{
+					AttrDefInfo *inhDef = parent->attrdefs[inhAttrInd];
+
 					foundAttr = true;
 					foundNotNull |= parent->notnull[inhAttrInd];
-					if (attrDef != NULL)		/* If we have a default, check
-												 * parent */
+					if (inhDef != NULL)
 					{
-						AttrDefInfo *inhDef;
+						defaultsFound = true;
+						/*
+						 * If any parent has a default and the child doesn't,
+						 * we have to emit an explicit DEFAULT NULL clause
+						 * for the child, else the parent's default will win.
+						 */
+						if (attrDef == NULL)
+						{
+							attrDef = (AttrDefInfo *) malloc(sizeof(AttrDefInfo));
+							attrDef->dobj.objType = DO_ATTRDEF;
+							attrDef->dobj.catId.tableoid = 0;
+							attrDef->dobj.catId.oid = 0;
+							AssignDumpId(&attrDef->dobj);
+							attrDef->adtable = tbinfo;
+							attrDef->adnum = j + 1;
+							attrDef->adef_expr = strdup("NULL");
+
+							attrDef->dobj.name = strdup(tbinfo->dobj.name);
+							attrDef->dobj.namespace = tbinfo->dobj.namespace;
 
-						inhDef = parent->attrdefs[inhAttrInd];
-						if (inhDef != NULL)
+							attrDef->dobj.dump = tbinfo->dobj.dump;
+
+							attrDef->separate = false;
+							addObjectDependency(&tbinfo->dobj,
+												attrDef->dobj.dumpId);
+
+							tbinfo->attrdefs[j] = attrDef;
+						}
+						if (strcmp(attrDef->adef_expr, inhDef->adef_expr) != 0)
 						{
-							defaultsFound = true;
-							defaultsMatch &= (strcmp(attrDef->adef_expr,
-													 inhDef->adef_expr) == 0);
+							defaultsMatch = false;
+							/*
+							 * Whenever there is a non-matching parent
+							 * default, add a dependency to force the parent
+							 * default to be dumped first, in case the
+							 * defaults end up being dumped as separate
+							 * commands.  Otherwise the parent default will
+							 * override the child's when it is applied.
+							 */
+							addObjectDependency(&attrDef->dobj,
+												inhDef->dobj.dumpId);
 						}
 					}
 				}
-- 
GitLab