1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-21 00:42:43 +03:00

Tighten integrity checks on ALTER TABLE ... ALTER COLUMN ... RENAME.

When a column is renamed, we recursively rename the same column in
all descendent tables.  But if one of those tables also inherits that
column from a table outside the inheritance hierarchy rooted at the
named table, we must throw an error.  The previous coding correctly
prohibited the rename when the parent had inherited the column from
elsewhere, but overlooked the case where the parent was OK but a child
table also inherited the same column from a second, unrelated parent.

For now, not backpatched due to lack of complaints from the field.

KaiGai Kohei, with further changes by me.
Reviewed by Bernd Helme and Tom Lane.
This commit is contained in:
Robert Haas
2010-02-01 19:28:56 +00:00
parent 1526d4e38f
commit 63f9282f6e
9 changed files with 211 additions and 29 deletions

View File

@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_inherits.c,v 1.5 2010/01/02 16:57:36 momjian Exp $
* $PostgreSQL: pgsql/src/backend/catalog/pg_inherits.c,v 1.6 2010/02/01 19:28:56 rhaas Exp $
*
*-------------------------------------------------------------------------
*/
@@ -148,6 +148,9 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
* find_all_inheritors -
* Returns a list of relation OIDs including the given rel plus
* all relations that inherit from it, directly or indirectly.
* Optionally, it also returns the number of parents found for
* each such relation within the inheritance tree rooted at the
* given rel.
*
* The specified lock type is acquired on all child relations (but not on the
* given rel; caller should already have locked it). If lockmode is NoLock
@@ -155,9 +158,9 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
* against possible DROPs of child relations.
*/
List *
find_all_inheritors(Oid parentrelId, LOCKMODE lockmode)
find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
{
List *rels_list;
List *rels_list, *rel_numparents;
ListCell *l;
/*
@@ -168,11 +171,13 @@ find_all_inheritors(Oid parentrelId, LOCKMODE lockmode)
* doesn't fetch the next list element until the bottom of the loop.
*/
rels_list = list_make1_oid(parentrelId);
rel_numparents = list_make1_int(0);
foreach(l, rels_list)
{
Oid currentrel = lfirst_oid(l);
List *currentchildren;
ListCell *lc;
/* Get the direct children of this rel */
currentchildren = find_inheritance_children(currentrel, lockmode);
@@ -184,9 +189,37 @@ find_all_inheritors(Oid parentrelId, LOCKMODE lockmode)
* loop, though theoretically there can't be any cycles in the
* inheritance graph anyway.)
*/
rels_list = list_concat_unique_oid(rels_list, currentchildren);
foreach(lc, currentchildren)
{
Oid child_oid = lfirst_oid(lc);
bool found = false;
ListCell *lo;
ListCell *li;
/* if the rel is already there, bump number-of-parents counter */
forboth(lo, rels_list, li, rel_numparents)
{
if (lfirst_oid(lo) == child_oid)
{
lfirst_int(li)++;
found = true;
break;
}
}
/* if it's not there, add it. expect 1 parent, initially. */
if (!found)
{
rels_list = lappend_oid(rels_list, child_oid);
rel_numparents = lappend_int(rel_numparents, 1);
}
}
}
if (numparents)
*numparents = rel_numparents;
else
list_free(rel_numparents);
return rels_list;
}