From 684826d0a25f9c643ce6b4fba49d5d14effade73 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 5 Apr 2018 16:45:49 +0000 Subject: [PATCH v8 01/12] Add skip_locked argument to find_inheritance_children(). --- src/backend/catalog/pg_inherits.c | 26 +++++++++++++++++++++++--- src/backend/commands/lockcmds.c | 2 +- src/backend/commands/tablecmds.c | 16 ++++++++-------- src/backend/commands/trigger.c | 2 +- src/backend/utils/cache/partcache.c | 2 +- src/include/catalog/pg_inherits.h | 3 ++- 6 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c index 85baca54cc..1b936123c5 100644 --- a/src/backend/catalog/pg_inherits.c +++ b/src/backend/catalog/pg_inherits.c @@ -51,9 +51,14 @@ typedef struct SeenRelsEntry * given rel; caller should already have locked it). If lockmode is NoLock * then no locks are acquired, but caller must beware of race conditions * against possible DROPs of child relations. + * + * If skip_locked is true, any child relations that cannot be locked immediately + * without waiting are not added to the returned OID list, and skipped will be + * set to true if it is provided. Otherwise, skipped will be set to false if it + * is provided. */ List * -find_inheritance_children(Oid parentrelId, LOCKMODE lockmode) +find_inheritance_children(Oid parentrelId, LOCKMODE lockmode, bool skip_locked, bool *skipped) { List *list = NIL; Relation relation; @@ -65,13 +70,19 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode) int maxoids, numoids, i; + bool did_skip = false; /* * Can skip the scan if pg_class shows the relation has never had a * subclass. */ if (!has_subclass(parentrelId)) + { + if (skipped != NULL) + *skipped = did_skip; + return NIL; + } /* * Scan pg_inherits and build a working array of subclass OIDs. @@ -124,7 +135,13 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode) if (lockmode != NoLock) { /* Get the lock to synchronize against concurrent drop */ - LockRelationOid(inhrelid, lockmode); + if (!skip_locked) + LockRelationOid(inhrelid, lockmode); + else if (!ConditionalLockRelationOid(inhrelid, lockmode)) + { + did_skip = true; + continue; + } /* * Now that we have the lock, double-check to see if the relation @@ -145,6 +162,9 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode) pfree(oidarr); + if (skipped != NULL) + *skipped = did_skip; + return list; } @@ -199,7 +219,7 @@ find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents) ListCell *lc; /* Get the direct children of this rel */ - currentchildren = find_inheritance_children(currentrel, lockmode); + currentchildren = find_inheritance_children(currentrel, lockmode, false, NULL); /* * Add to the queue only those children not already seen. This avoids diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c index 71278b38cf..ef4d4a8c9d 100644 --- a/src/backend/commands/lockcmds.c +++ b/src/backend/commands/lockcmds.c @@ -119,7 +119,7 @@ LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, Oid userid) List *children; ListCell *lc; - children = find_inheritance_children(reloid, NoLock); + children = find_inheritance_children(reloid, NoLock, false, NULL); foreach(lc, children) { diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 8b848f91a7..4f0640e9ba 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -2781,7 +2781,7 @@ renameatt_internal(Oid myrelid, * expected_parents will only be 0 if we are not already recursing. */ if (expected_parents == 0 && - find_inheritance_children(myrelid, NoLock) != NIL) + find_inheritance_children(myrelid, NoLock, false, NULL) != NIL) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("inherited column \"%s\" must be renamed in child tables too", @@ -2980,7 +2980,7 @@ rename_constraint_internal(Oid myrelid, else { if (expected_parents == 0 && - find_inheritance_children(myrelid, NoLock) != NIL) + find_inheritance_children(myrelid, NoLock, false, NULL) != NIL) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("inherited constraint \"%s\" must be renamed in child tables too", @@ -5441,7 +5441,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, */ if (colDef->identity && recurse && - find_inheritance_children(myrelid, NoLock) != NIL) + find_inheritance_children(myrelid, NoLock, false, NULL) != NIL) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("cannot recursively add identity column to table that has child tables"))); @@ -5684,7 +5684,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel, * routines, we have to do this one level of recursion at a time; we can't * use find_all_inheritors to do it in one pass. */ - children = find_inheritance_children(RelationGetRelid(rel), lockmode); + children = find_inheritance_children(RelationGetRelid(rel), lockmode, false, NULL); /* * If we are told not to recurse, there had better not be any child @@ -6780,7 +6780,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, * routines, we have to do this one level of recursion at a time; we can't * use find_all_inheritors to do it in one pass. */ - children = find_inheritance_children(RelationGetRelid(rel), lockmode); + children = find_inheritance_children(RelationGetRelid(rel), lockmode, false, NULL); if (children) { @@ -7231,7 +7231,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, * routines, we have to do this one level of recursion at a time; we can't * use find_all_inheritors to do it in one pass. */ - children = find_inheritance_children(RelationGetRelid(rel), lockmode); + children = find_inheritance_children(RelationGetRelid(rel), lockmode, false, NULL); /* * Check if ONLY was specified with ALTER TABLE. If so, allow the @@ -8919,7 +8919,7 @@ ATExecDropConstraint(Relation rel, const char *constrName, * use find_all_inheritors to do it in one pass. */ if (!is_no_inherit_constraint) - children = find_inheritance_children(RelationGetRelid(rel), lockmode); + children = find_inheritance_children(RelationGetRelid(rel), lockmode, false, NULL); else children = NIL; @@ -9261,7 +9261,7 @@ ATPrepAlterColumnType(List **wqueue, } } else if (!recursing && - find_inheritance_children(RelationGetRelid(rel), NoLock) != NIL) + find_inheritance_children(RelationGetRelid(rel), NoLock, false, NULL) != NIL) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("type of inherited column \"%s\" must be changed in child tables too", diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 57519fe8d6..24de0c58c0 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -1109,7 +1109,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString, ListCell *l; List *idxs = NIL; - idxs = find_inheritance_children(indexOid, ShareRowExclusiveLock); + idxs = find_inheritance_children(indexOid, ShareRowExclusiveLock, false, NULL); foreach(l, idxs) childTbls = lappend_oid(childTbls, IndexGetRelation(lfirst_oid(l), diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c index 115a9fe78f..c160e755e2 100644 --- a/src/backend/utils/cache/partcache.c +++ b/src/backend/utils/cache/partcache.c @@ -285,7 +285,7 @@ RelationBuildPartitionDesc(Relation rel) PartitionRangeBound **rbounds = NULL; /* Get partition oids from pg_inherits */ - inhoids = find_inheritance_children(RelationGetRelid(rel), NoLock); + inhoids = find_inheritance_children(RelationGetRelid(rel), NoLock, false, NULL); /* Collect bound spec nodes in a list */ i = 0; diff --git a/src/include/catalog/pg_inherits.h b/src/include/catalog/pg_inherits.h index 2a98e02c6a..a89b3f44a5 100644 --- a/src/include/catalog/pg_inherits.h +++ b/src/include/catalog/pg_inherits.h @@ -44,7 +44,8 @@ CATALOG(pg_inherits,2611,InheritsRelationId) BKI_WITHOUT_OIDS typedef FormData_pg_inherits *Form_pg_inherits; -extern List *find_inheritance_children(Oid parentrelId, LOCKMODE lockmode); +extern List *find_inheritance_children(Oid parentrelId, LOCKMODE lockmode, + bool skip_locked, bool *skipped); extern List *find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **parents); extern bool has_subclass(Oid relationId); -- 2.16.2