| 1 | /*------------------------------------------------------------------------- | 
| 2 |  * | 
| 3 |  * relation.c | 
| 4 |  *	  Generic relation related routines. | 
| 5 |  * | 
| 6 |  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group | 
| 7 |  * Portions Copyright (c) 1994, Regents of the University of California | 
| 8 |  * | 
| 9 |  * | 
| 10 |  * IDENTIFICATION | 
| 11 |  *	  src/backend/access/common/relation.c | 
| 12 |  * | 
| 13 |  * NOTES | 
| 14 |  *	  This file contains relation_ routines that implement access to relations | 
| 15 |  *	  (tables, indexes, etc). Support that's specific to subtypes of relations | 
| 16 |  *	  should go into their respective files, not here. | 
| 17 |  * | 
| 18 |  *------------------------------------------------------------------------- | 
| 19 |  */ | 
| 20 |  | 
| 21 | #include "postgres.h" | 
| 22 |  | 
| 23 | #include "access/relation.h" | 
| 24 | #include "access/xact.h" | 
| 25 | #include "catalog/namespace.h" | 
| 26 | #include "miscadmin.h" | 
| 27 | #include "pgstat.h" | 
| 28 | #include "storage/lmgr.h" | 
| 29 | #include "utils/inval.h" | 
| 30 | #include "utils/syscache.h" | 
| 31 |  | 
| 32 |  | 
| 33 | /* ---------------- | 
| 34 |  *		relation_open - open any relation by relation OID | 
| 35 |  * | 
| 36 |  *		If lockmode is not "NoLock", the specified kind of lock is | 
| 37 |  *		obtained on the relation.  (Generally, NoLock should only be | 
| 38 |  *		used if the caller knows it has some appropriate lock on the | 
| 39 |  *		relation already.) | 
| 40 |  * | 
| 41 |  *		An error is raised if the relation does not exist. | 
| 42 |  * | 
| 43 |  *		NB: a "relation" is anything with a pg_class entry.  The caller is | 
| 44 |  *		expected to check whether the relkind is something it can handle. | 
| 45 |  * ---------------- | 
| 46 |  */ | 
| 47 | Relation | 
| 48 | relation_open(Oid relationId, LOCKMODE lockmode) | 
| 49 | { | 
| 50 | 	Relation	r; | 
| 51 |  | 
| 52 | 	Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); | 
| 53 |  | 
| 54 | 	/* Get the lock before trying to open the relcache entry */ | 
| 55 | 	if (lockmode != NoLock) | 
| 56 | 		LockRelationOid(relationId, lockmode); | 
| 57 |  | 
| 58 | 	/* The relcache does all the real work... */ | 
| 59 | 	r = RelationIdGetRelation(relationId); | 
| 60 |  | 
| 61 | 	if (!RelationIsValid(r)) | 
| 62 | 		elog(ERROR, "could not open relation with OID %u" , relationId); | 
| 63 |  | 
| 64 | 	/* | 
| 65 | 	 * If we didn't get the lock ourselves, assert that caller holds one, | 
| 66 | 	 * except in bootstrap mode where no locks are used. | 
| 67 | 	 */ | 
| 68 | 	Assert(lockmode != NoLock || | 
| 69 | 		   IsBootstrapProcessingMode() || | 
| 70 | 		   CheckRelationLockedByMe(r, AccessShareLock, true)); | 
| 71 |  | 
| 72 | 	/* Make note that we've accessed a temporary relation */ | 
| 73 | 	if (RelationUsesLocalBuffers(r)) | 
| 74 | 		MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE; | 
| 75 |  | 
| 76 | 	pgstat_initstats(r); | 
| 77 |  | 
| 78 | 	return r; | 
| 79 | } | 
| 80 |  | 
| 81 | /* ---------------- | 
| 82 |  *		try_relation_open - open any relation by relation OID | 
| 83 |  * | 
| 84 |  *		Same as relation_open, except return NULL instead of failing | 
| 85 |  *		if the relation does not exist. | 
| 86 |  * ---------------- | 
| 87 |  */ | 
| 88 | Relation | 
| 89 | try_relation_open(Oid relationId, LOCKMODE lockmode) | 
| 90 | { | 
| 91 | 	Relation	r; | 
| 92 |  | 
| 93 | 	Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); | 
| 94 |  | 
| 95 | 	/* Get the lock first */ | 
| 96 | 	if (lockmode != NoLock) | 
| 97 | 		LockRelationOid(relationId, lockmode); | 
| 98 |  | 
| 99 | 	/* | 
| 100 | 	 * Now that we have the lock, probe to see if the relation really exists | 
| 101 | 	 * or not. | 
| 102 | 	 */ | 
| 103 | 	if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relationId))) | 
| 104 | 	{ | 
| 105 | 		/* Release useless lock */ | 
| 106 | 		if (lockmode != NoLock) | 
| 107 | 			UnlockRelationOid(relationId, lockmode); | 
| 108 |  | 
| 109 | 		return NULL; | 
| 110 | 	} | 
| 111 |  | 
| 112 | 	/* Should be safe to do a relcache load */ | 
| 113 | 	r = RelationIdGetRelation(relationId); | 
| 114 |  | 
| 115 | 	if (!RelationIsValid(r)) | 
| 116 | 		elog(ERROR, "could not open relation with OID %u" , relationId); | 
| 117 |  | 
| 118 | 	/* If we didn't get the lock ourselves, assert that caller holds one */ | 
| 119 | 	Assert(lockmode != NoLock || | 
| 120 | 		   CheckRelationLockedByMe(r, AccessShareLock, true)); | 
| 121 |  | 
| 122 | 	/* Make note that we've accessed a temporary relation */ | 
| 123 | 	if (RelationUsesLocalBuffers(r)) | 
| 124 | 		MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE; | 
| 125 |  | 
| 126 | 	pgstat_initstats(r); | 
| 127 |  | 
| 128 | 	return r; | 
| 129 | } | 
| 130 |  | 
| 131 | /* ---------------- | 
| 132 |  *		relation_openrv - open any relation specified by a RangeVar | 
| 133 |  * | 
| 134 |  *		Same as relation_open, but the relation is specified by a RangeVar. | 
| 135 |  * ---------------- | 
| 136 |  */ | 
| 137 | Relation | 
| 138 | relation_openrv(const RangeVar *relation, LOCKMODE lockmode) | 
| 139 | { | 
| 140 | 	Oid			relOid; | 
| 141 |  | 
| 142 | 	/* | 
| 143 | 	 * Check for shared-cache-inval messages before trying to open the | 
| 144 | 	 * relation.  This is needed even if we already hold a lock on the | 
| 145 | 	 * relation, because GRANT/REVOKE are executed without taking any lock on | 
| 146 | 	 * the target relation, and we want to be sure we see current ACL | 
| 147 | 	 * information.  We can skip this if asked for NoLock, on the assumption | 
| 148 | 	 * that such a call is not the first one in the current command, and so we | 
| 149 | 	 * should be reasonably up-to-date already.  (XXX this all could stand to | 
| 150 | 	 * be redesigned, but for the moment we'll keep doing this like it's been | 
| 151 | 	 * done historically.) | 
| 152 | 	 */ | 
| 153 | 	if (lockmode != NoLock) | 
| 154 | 		AcceptInvalidationMessages(); | 
| 155 |  | 
| 156 | 	/* Look up and lock the appropriate relation using namespace search */ | 
| 157 | 	relOid = RangeVarGetRelid(relation, lockmode, false); | 
| 158 |  | 
| 159 | 	/* Let relation_open do the rest */ | 
| 160 | 	return relation_open(relOid, NoLock); | 
| 161 | } | 
| 162 |  | 
| 163 | /* ---------------- | 
| 164 |  *		relation_openrv_extended - open any relation specified by a RangeVar | 
| 165 |  * | 
| 166 |  *		Same as relation_openrv, but with an additional missing_ok argument | 
| 167 |  *		allowing a NULL return rather than an error if the relation is not | 
| 168 |  *		found.  (Note that some other causes, such as permissions problems, | 
| 169 |  *		will still result in an ereport.) | 
| 170 |  * ---------------- | 
| 171 |  */ | 
| 172 | Relation | 
| 173 | relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode, | 
| 174 | 						 bool missing_ok) | 
| 175 | { | 
| 176 | 	Oid			relOid; | 
| 177 |  | 
| 178 | 	/* | 
| 179 | 	 * Check for shared-cache-inval messages before trying to open the | 
| 180 | 	 * relation.  See comments in relation_openrv(). | 
| 181 | 	 */ | 
| 182 | 	if (lockmode != NoLock) | 
| 183 | 		AcceptInvalidationMessages(); | 
| 184 |  | 
| 185 | 	/* Look up and lock the appropriate relation using namespace search */ | 
| 186 | 	relOid = RangeVarGetRelid(relation, lockmode, missing_ok); | 
| 187 |  | 
| 188 | 	/* Return NULL on not-found */ | 
| 189 | 	if (!OidIsValid(relOid)) | 
| 190 | 		return NULL; | 
| 191 |  | 
| 192 | 	/* Let relation_open do the rest */ | 
| 193 | 	return relation_open(relOid, NoLock); | 
| 194 | } | 
| 195 |  | 
| 196 | /* ---------------- | 
| 197 |  *		relation_close - close any relation | 
| 198 |  * | 
| 199 |  *		If lockmode is not "NoLock", we then release the specified lock. | 
| 200 |  * | 
| 201 |  *		Note that it is often sensible to hold a lock beyond relation_close; | 
| 202 |  *		in that case, the lock is released automatically at xact end. | 
| 203 |  * ---------------- | 
| 204 |  */ | 
| 205 | void | 
| 206 | relation_close(Relation relation, LOCKMODE lockmode) | 
| 207 | { | 
| 208 | 	LockRelId	relid = relation->rd_lockInfo.lockRelId; | 
| 209 |  | 
| 210 | 	Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES); | 
| 211 |  | 
| 212 | 	/* The relcache does the real work... */ | 
| 213 | 	RelationClose(relation); | 
| 214 |  | 
| 215 | 	if (lockmode != NoLock) | 
| 216 | 		UnlockRelationId(&relid, lockmode); | 
| 217 | } | 
| 218 |  |