From eb349b58ab8ebaa30c7bd0892393c3f062d7c0e0 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Fri, 30 Mar 2018 16:34:40 +0000 Subject: [PATCH v2 2/2] Add skip-locked option to RangeVarGetRelidExtended(). --- src/backend/catalog/namespace.c | 28 ++++++++++++++++++++++------ src/include/catalog/namespace.h | 3 ++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index d3eef63d5e..55ac8b55d7 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -210,6 +210,13 @@ static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames, * RELID_MISSING_OK, otherwise raise an error. * * If the flags contain RELID_NOWAIT, throw an error if we'd have to wait for a lock. + * If the flags contain RELID_SKIP_LOCKED, return InvalidOid if we'd have to wait for + * a lock. The flags cannot contain both RELID_NOWAIT and RELID_SKIP_LOCKED + * together. + * + * Note that if RELID_MISSING_OK and RELID_SKIP_LOCKED are both specified, a return + * value of InvalidOid could either mean the relation is missing or it could not be + * locked. * * Callback allows caller to check permissions or acquire additional locks * prior to grabbing the relation lock. @@ -225,6 +232,9 @@ RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool retry = false; bool missing_ok = ((flags & RELID_MISSING_OK) != 0); + /* verify that conflicting options are not specified */ + Assert((flags & RELID_NOWAIT) == 0 || (flags & RELID_SKIP_LOCKED) == 0); + /* * We check the catalog name and then ignore it. */ @@ -362,20 +372,24 @@ RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, */ if (!OidIsValid(relId)) AcceptInvalidationMessages(); - else if ((flags & RELID_NOWAIT) == 0) + else if ((flags & (RELID_NOWAIT | RELID_SKIP_LOCKED)) == 0) LockRelationOid(relId, lockmode); else if (!ConditionalLockRelationOid(relId, lockmode)) { + int elevel = ((flags & RELID_SKIP_LOCKED) != 0) ? DEBUG1 : ERROR; + if (relation->schemaname) - ereport(ERROR, + ereport(elevel, (errcode(ERRCODE_LOCK_NOT_AVAILABLE), errmsg("could not obtain lock on relation \"%s.%s\"", relation->schemaname, relation->relname))); else - ereport(ERROR, + ereport(elevel, (errcode(ERRCODE_LOCK_NOT_AVAILABLE), errmsg("could not obtain lock on relation \"%s\"", relation->relname))); + + return InvalidOid; } /* @@ -393,15 +407,17 @@ RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, oldRelId = relId; } - if (!OidIsValid(relId) && !missing_ok) + if (!OidIsValid(relId)) { + int elevel = missing_ok ? DEBUG1 : ERROR; + if (relation->schemaname) - ereport(ERROR, + ereport(elevel, (errcode(ERRCODE_UNDEFINED_TABLE), errmsg("relation \"%s.%s\" does not exist", relation->schemaname, relation->relname))); else - ereport(ERROR, + ereport(elevel, (errcode(ERRCODE_UNDEFINED_TABLE), errmsg("relation \"%s\" does not exist", relation->relname))); diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h index 60f110b639..6347a97c53 100644 --- a/src/include/catalog/namespace.h +++ b/src/include/catalog/namespace.h @@ -50,7 +50,8 @@ typedef struct OverrideSearchPath typedef enum RelidOption { RELID_MISSING_OK = 1 << 0, /* don't error if relation doesn't exist */ - RELID_NOWAIT = 1 << 1 /* error if relation cannot be locked */ + RELID_NOWAIT = 1 << 1, /* error if relation cannot be locked */ + RELID_SKIP_LOCKED = 1 << 2 /* skip if relation cannot be locked */ } RelidOption; typedef void (*RangeVarGetRelidCallback) (const RangeVar *relation, Oid relId, -- 2.16.2