88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.283 2009/05/1200:56:05 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.284 2009/05/1203:11:01 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
2929#include "catalog/pg_constraint.h"
3030#include "catalog/pg_depend.h"
3131#include "catalog/pg_inherits.h"
32+ #include "catalog/pg_inherits_fn.h"
3233#include "catalog/pg_namespace.h"
3334#include "catalog/pg_opclass.h"
3435#include "catalog/pg_tablespace.h"
@@ -796,7 +797,7 @@ ExecuteTruncate(TruncateStmt *stmt)
796797ListCell * child ;
797798List * children ;
798799
799- children = find_all_inheritors (myrelid );
800+ children = find_all_inheritors (myrelid , AccessExclusiveLock );
800801
801802foreach (child ,children )
802803{
@@ -805,7 +806,8 @@ ExecuteTruncate(TruncateStmt *stmt)
805806if (list_member_oid (relids ,childrelid ))
806807continue ;
807808
808- rel = heap_open (childrelid ,AccessExclusiveLock );
809+ /* find_all_inheritors already got lock */
810+ rel = heap_open (childrelid ,NoLock );
809811truncate_check_rel (rel );
810812rels = lappend (rels ,rel );
811813relids = lappend_oid (relids ,childrelid );
@@ -1871,7 +1873,7 @@ renameatt(Oid myrelid,
18711873ListCell * child ;
18721874List * children ;
18731875
1874- children = find_all_inheritors (myrelid );
1876+ children = find_all_inheritors (myrelid , AccessExclusiveLock );
18751877
18761878/*
18771879 * find_all_inheritors does the recursive search of the inheritance
@@ -1895,7 +1897,7 @@ renameatt(Oid myrelid,
18951897 * tables; else the rename would put them out of step.
18961898 */
18971899if (!recursing &&
1898- find_inheritance_children (myrelid )!= NIL )
1900+ find_inheritance_children (myrelid , NoLock )!= NIL )
18991901ereport (ERROR ,
19001902(errcode (ERRCODE_INVALID_TABLE_DEFINITION ),
19011903errmsg ("inherited column \"%s\" must be renamed in child tables too" ,
@@ -3289,7 +3291,7 @@ ATSimpleRecursion(List **wqueue, Relation rel,
32893291ListCell * child ;
32903292List * children ;
32913293
3292- children = find_all_inheritors (relid );
3294+ children = find_all_inheritors (relid , AccessExclusiveLock );
32933295
32943296/*
32953297 * find_all_inheritors does the recursive search of the inheritance
@@ -3303,7 +3305,8 @@ ATSimpleRecursion(List **wqueue, Relation rel,
33033305
33043306if (childrelid == relid )
33053307continue ;
3306- childrel = relation_open (childrelid ,AccessExclusiveLock );
3308+ /* find_all_inheritors already got lock */
3309+ childrel = relation_open (childrelid ,NoLock );
33073310CheckTableNotInUse (childrel ,"ALTER TABLE" );
33083311ATPrepCmd (wqueue ,childrel ,cmd , false, true);
33093312relation_close (childrel ,NoLock );
@@ -3327,14 +3330,15 @@ ATOneLevelRecursion(List **wqueue, Relation rel,
33273330ListCell * child ;
33283331List * children ;
33293332
3330- children = find_inheritance_children (relid );
3333+ children = find_inheritance_children (relid , AccessExclusiveLock );
33313334
33323335foreach (child ,children )
33333336{
33343337Oid childrelid = lfirst_oid (child );
33353338Relation childrel ;
33363339
3337- childrel = relation_open (childrelid ,AccessExclusiveLock );
3340+ /* find_inheritance_children already got lock */
3341+ childrel = relation_open (childrelid ,NoLock );
33383342CheckTableNotInUse (childrel ,"ALTER TABLE" );
33393343ATPrepCmd (wqueue ,childrel ,cmd , true, true);
33403344relation_close (childrel ,NoLock );
@@ -3480,7 +3484,7 @@ ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,
34803484 * If we are told not to recurse, there had better not be any child
34813485 * tables; else the addition would put them out of step.
34823486 */
3483- if (find_inheritance_children (RelationGetRelid (rel ))!= NIL )
3487+ if (find_inheritance_children (RelationGetRelid (rel ), NoLock )!= NIL )
34843488ereport (ERROR ,
34853489(errcode (ERRCODE_INVALID_TABLE_DEFINITION ),
34863490errmsg ("column must be added to child tables too" )));
@@ -4199,7 +4203,8 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
41994203 * routines, we have to do this one level of recursion at a time; we can't
42004204 * use find_all_inheritors to do it in one pass.
42014205 */
4202- children = find_inheritance_children (RelationGetRelid (rel ));
4206+ children = find_inheritance_children (RelationGetRelid (rel ),
4207+ AccessExclusiveLock );
42034208
42044209if (children )
42054210{
@@ -4213,7 +4218,8 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
42134218Relation childrel ;
42144219Form_pg_attribute childatt ;
42154220
4216- childrel = heap_open (childrelid ,AccessExclusiveLock );
4221+ /* find_inheritance_children already got lock */
4222+ childrel = heap_open (childrelid ,NoLock );
42174223CheckTableNotInUse (childrel ,"ALTER TABLE" );
42184224
42194225tuple = SearchSysCacheCopyAttName (childrelid ,colName );
@@ -4509,7 +4515,8 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
45094515 * routines, we have to do this one level of recursion at a time; we can't
45104516 * use find_all_inheritors to do it in one pass.
45114517 */
4512- children = find_inheritance_children (RelationGetRelid (rel ));
4518+ children = find_inheritance_children (RelationGetRelid (rel ),
4519+ AccessExclusiveLock );
45134520
45144521/*
45154522 * If we are told not to recurse, there had better not be any child
@@ -4526,7 +4533,8 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
45264533Relation childrel ;
45274534AlteredTableInfo * childtab ;
45284535
4529- childrel = heap_open (childrelid ,AccessExclusiveLock );
4536+ /* find_inheritance_children already got lock */
4537+ childrel = heap_open (childrelid ,NoLock );
45304538CheckTableNotInUse (childrel ,"ALTER TABLE" );
45314539
45324540/* Find or create work queue entry for this table */
@@ -5426,7 +5434,8 @@ ATExecDropConstraint(Relation rel, const char *constrName,
54265434 * use find_all_inheritors to do it in one pass.
54275435 */
54285436if (is_check_constraint )
5429- children = find_inheritance_children (RelationGetRelid (rel ));
5437+ children = find_inheritance_children (RelationGetRelid (rel ),
5438+ AccessExclusiveLock );
54305439else
54315440children = NIL ;
54325441
@@ -5435,7 +5444,8 @@ ATExecDropConstraint(Relation rel, const char *constrName,
54355444Oid childrelid = lfirst_oid (child );
54365445Relation childrel ;
54375446
5438- childrel = heap_open (childrelid ,AccessExclusiveLock );
5447+ /* find_inheritance_children already got lock */
5448+ childrel = heap_open (childrelid ,NoLock );
54395449CheckTableNotInUse (childrel ,"ALTER TABLE" );
54405450
54415451ScanKeyInit (& key ,
@@ -5659,7 +5669,7 @@ ATPrepAlterColumnType(List **wqueue,
56595669if (recurse )
56605670ATSimpleRecursion (wqueue ,rel ,cmd ,recurse );
56615671else if (!recursing &&
5662- find_inheritance_children (RelationGetRelid (rel ))!= NIL )
5672+ find_inheritance_children (RelationGetRelid (rel ), NoLock )!= NIL )
56635673ereport (ERROR ,
56645674(errcode (ERRCODE_INVALID_TABLE_DEFINITION ),
56655675errmsg ("type of inherited column \"%s\" must be changed in child tables too" ,
@@ -6945,8 +6955,11 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent)
69456955 * exclusive locks on the entire inheritance tree, which is a cure worse
69466956 * than the disease. find_all_inheritors() will cope with circularity
69476957 * anyway, so don't sweat it too much.
6958+ *
6959+ * We use weakest lock we can on child's children, namely AccessShareLock.
69486960 */
6949- children = find_all_inheritors (RelationGetRelid (child_rel ));
6961+ children = find_all_inheritors (RelationGetRelid (child_rel ),
6962+ AccessShareLock );
69506963
69516964if (list_member_oid (children ,RelationGetRelid (parent_rel )))
69526965ereport (ERROR ,