Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 182228b

Browse files
committed
Fix pg_dump for better handling of inherited columns.
Revise pg_dump's handling of inherited columns, which was last looked at seriously in 2001, to eliminate several misbehaviors associated with inherited default expressions and NOT NULL flags. In particular make sure that a column is printed in a child table's CREATE TABLE command if and only if it has attislocal = true; the former behavior would sometimes cause a column to become marked attislocal when it was not so marked in the source database. Also, stop relying on textual comparison of default expressions to decide if they're inherited; instead, don't use default-expression inheritance at all, but just install the default explicitly at each level of the hierarchy. This fixes the search-path-related misbehavior recently exhibited by Chester Young, and also removes some dubious assumptions about the order in which ALTER TABLE SET DEFAULT commands would be executed. Back-patch to all supported branches.
1 parent 1e7d008 commit 182228b

File tree

4 files changed

+168
-157
lines changed

4 files changed

+168
-157
lines changed

src/bin/pg_dump/common.c

Lines changed: 48 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,13 @@ flagInhTables(TableInfo *tblinfo, int numTables,
283283

284284
/* flagInhAttrs -
285285
* for each dumpable table in tblinfo, flag its inherited attributes
286-
* so when we dump the table out, we don't dump out the inherited attributes
286+
*
287+
* What we need to do here is detect child columns that inherit NOT NULL
288+
* bits from their parents (so that we needn't specify that again for the
289+
* child) and child columns that have DEFAULT NULL when their parents had
290+
* some non-null default. In the latter case, we make up a dummy AttrDefInfo
291+
* object so that we'll correctly emit the necessary DEFAULT NULL clause;
292+
* otherwise the backend will apply an inherited default to the column.
287293
*
288294
* modifies tblinfo
289295
*/
@@ -299,7 +305,6 @@ flagInhAttrs(TableInfo *tblinfo, int numTables)
299305
TableInfo *tbinfo = &(tblinfo[i]);
300306
int numParents;
301307
TableInfo **parents;
302-
TableInfo *parent;
303308

304309
/* Sequences and views never have parents */
305310
if (tbinfo->relkind == RELKIND_SEQUENCE ||
@@ -316,132 +321,70 @@ flagInhAttrs(TableInfo *tblinfo, int numTables)
316321
if (numParents == 0)
317322
continue; /* nothing to see here, move along */
318323

319-
/*----------------------------------------------------------------
320-
* For each attr, check the parent info: if no parent has an attr
321-
* with the same name, then it's not inherited. If there *is* an
322-
* attr with the same name, then only dump it if:
323-
*
324-
* - it is NOT NULL and zero parents are NOT NULL
325-
* OR
326-
* - it has a default value AND the default value does not match
327-
* all parent default values, or no parents specify a default.
328-
*
329-
* See discussion on -hackers around 2-Apr-2001.
330-
*----------------------------------------------------------------
331-
*/
324+
/* For each column, search for matching column names in parent(s) */
332325
for (j = 0; j < tbinfo->numatts; j++)
333326
{
334-
bool foundAttr; /* Attr was found in a parent */
335327
bool foundNotNull; /* Attr was NOT NULL in a parent */
336-
bool defaultsMatch; /* All non-empty defaults match */
337-
bool defaultsFound; /* Found a default in a parent */
338-
AttrDefInfo *attrDef;
339-
340-
foundAttr = false;
341-
foundNotNull = false;
342-
defaultsMatch = true;
343-
defaultsFound = false;
328+
bool foundDefault; /* Found a default in a parent */
344329

345-
attrDef = tbinfo->attrdefs[j];
330+
/* no point in examining dropped columns */
331+
if (tbinfo->attisdropped[j])
332+
continue;
346333

334+
foundNotNull = false;
335+
foundDefault = false;
347336
for (k = 0; k < numParents; k++)
348337
{
338+
TableInfo *parent = parents[k];
349339
int inhAttrInd;
350340

351-
parent = parents[k];
352341
inhAttrInd = strInArray(tbinfo->attnames[j],
353342
parent->attnames,
354343
parent->numatts);
355-
356-
if (inhAttrInd != -1)
344+
if (inhAttrInd >= 0)
357345
{
358-
AttrDefInfo *inhDef = parent->attrdefs[inhAttrInd];
359-
360-
foundAttr = true;
361346
foundNotNull |= parent->notnull[inhAttrInd];
362-
if (inhDef != NULL)
363-
{
364-
defaultsFound = true;
365-
366-
/*
367-
* If any parent has a default and the child doesn't,
368-
* we have to emit an explicit DEFAULT NULL clause for
369-
* the child, else the parent's default will win.
370-
*/
371-
if (attrDef == NULL)
372-
{
373-
attrDef = (AttrDefInfo *) malloc(sizeof(AttrDefInfo));
374-
attrDef->dobj.objType = DO_ATTRDEF;
375-
attrDef->dobj.catId.tableoid = 0;
376-
attrDef->dobj.catId.oid = 0;
377-
AssignDumpId(&attrDef->dobj);
378-
attrDef->adtable = tbinfo;
379-
attrDef->adnum = j + 1;
380-
attrDef->adef_expr = strdup("NULL");
381-
382-
attrDef->dobj.name = strdup(tbinfo->dobj.name);
383-
attrDef->dobj.namespace = tbinfo->dobj.namespace;
384-
385-
attrDef->dobj.dump = tbinfo->dobj.dump;
386-
387-
attrDef->separate = false;
388-
addObjectDependency(&tbinfo->dobj,
389-
attrDef->dobj.dumpId);
390-
391-
tbinfo->attrdefs[j] = attrDef;
392-
}
393-
if (strcmp(attrDef->adef_expr, inhDef->adef_expr) != 0)
394-
{
395-
defaultsMatch = false;
396-
397-
/*
398-
* Whenever there is a non-matching parent
399-
* default, add a dependency to force the parent
400-
* default to be dumped first, in case the
401-
* defaults end up being dumped as separate
402-
* commands. Otherwise the parent default will
403-
* override the child's when it is applied.
404-
*/
405-
addObjectDependency(&attrDef->dobj,
406-
inhDef->dobj.dumpId);
407-
}
408-
}
347+
foundDefault |= (parent->attrdefs[inhAttrInd] != NULL);
409348
}
410349
}
411350

412-
/*
413-
* Based on the scan of the parents, decide if we can rely on the
414-
* inherited attr
415-
*/
416-
if (foundAttr) /* Attr was inherited */
351+
/* Remember if we found inherited NOT NULL */
352+
tbinfo->inhNotNull[j] = foundNotNull;
353+
354+
/* Manufacture a DEFAULT NULL clause if necessary */
355+
if (foundDefault && tbinfo->attrdefs[j] == NULL)
417356
{
418-
/* Set inherited flag by default */
419-
tbinfo->inhAttrs[j] = true;
420-
tbinfo->inhAttrDef[j] = true;
421-
tbinfo->inhNotNull[j] = true;
422-
423-
/*
424-
* Clear it if attr had a default, but parents did not, or
425-
* mismatch
426-
*/
427-
if ((attrDef != NULL) && (!defaultsFound || !defaultsMatch))
357+
AttrDefInfo *attrDef;
358+
359+
attrDef = (AttrDefInfo *) malloc(sizeof(AttrDefInfo));
360+
attrDef->dobj.objType = DO_ATTRDEF;
361+
attrDef->dobj.catId.tableoid = 0;
362+
attrDef->dobj.catId.oid = 0;
363+
AssignDumpId(&attrDef->dobj);
364+
attrDef->dobj.name = strdup(tbinfo->dobj.name);
365+
attrDef->dobj.namespace = tbinfo->dobj.namespace;
366+
attrDef->dobj.dump = tbinfo->dobj.dump;
367+
368+
attrDef->adtable = tbinfo;
369+
attrDef->adnum = j + 1;
370+
attrDef->adef_expr = strdup("NULL");
371+
372+
/* Will column be dumped explicitly? */
373+
if (shouldPrintColumn(tbinfo, j))
428374
{
429-
tbinfo->inhAttrs[j] = false;
430-
tbinfo->inhAttrDef[j] = false;
375+
attrDef->separate = false;
376+
/* No dependency needed: NULL cannot have dependencies */
431377
}
432-
433-
/*
434-
* Clear it if NOT NULL and none of the parents were NOT NULL
435-
*/
436-
if (tbinfo->notnull[j] && !foundNotNull)
378+
else
437379
{
438-
tbinfo->inhAttrs[j] = false;
439-
tbinfo->inhNotNull[j] = false;
380+
/* column will be suppressed, print default separately */
381+
attrDef->separate = true;
382+
/* ensure it comes out after the table */
383+
addObjectDependency(&attrDef->dobj,
384+
tbinfo->dobj.dumpId);
440385
}
441386

442-
/* Clear it if attr has local definition */
443-
if (tbinfo->attislocal[j])
444-
tbinfo->inhAttrs[j] = false;
387+
tbinfo->attrdefs[j] = attrDef;
445388
}
446389
}
447390
}

0 commit comments

Comments
 (0)