88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.126 2001/10/25 05:49:21 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.127 2001/11/02 16:30:29 tgl Exp $
1212 *
1313 *
1414 * INTERFACE ROUTINES
15- *heap_open- open a heap relation by relationId
15+ *relation_open- open any relation by relation OID
16+ *relation_openr- open any relation by name
17+ *relation_close- close any relation
18+ *heap_open- open a heap relation by relation OID
1619 *heap_openr- open a heap relation by name
17- *heap_open[r]_nofail - same, but return NULL on failure instead of elog
18- *heap_close- close a heap relation
20+ *heap_close- (now just a macro for relation_close)
1921 *heap_beginscan- begin relation scan
2022 *heap_rescan- restart a relation scan
2123 *heap_endscan- end relation scan
@@ -440,15 +442,21 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
440442 */
441443
442444/* ----------------
443- *heap_open - opena heap relation byrelationId
445+ *relation_open - openany relation byrelation OID
444446 *
445447 *If lockmode is not "NoLock", the specified kind of lock is
446- *obtained on the relation.
448+ *obtained on the relation. (Generally, NoLock should only be
449+ *used if the caller knows it has some appropriate lock on the
450+ *relation already.)
451+ *
447452 *An error is raised if the relation does not exist.
453+ *
454+ *NB: a "relation" is anything with a pg_class entry. The caller is
455+ *expected to check whether the relkind is something it can handle.
448456 * ----------------
449457 */
450458Relation
451- heap_open (Oid relationId ,LOCKMODE lockmode )
459+ relation_open (Oid relationId ,LOCKMODE lockmode )
452460{
453461Relation r ;
454462
@@ -466,26 +474,20 @@ heap_open(Oid relationId, LOCKMODE lockmode)
466474if (!RelationIsValid (r ))
467475elog (ERROR ,"Relation %u does not exist" ,relationId );
468476
469- /* Under no circumstances will we return an index as a relation. */
470- if (r -> rd_rel -> relkind == RELKIND_INDEX )
471- elog (ERROR ,"%s is an index relation" ,RelationGetRelationName (r ));
472-
473477if (lockmode != NoLock )
474478LockRelation (r ,lockmode );
475479
476480return r ;
477481}
478482
479483/* ----------------
480- *heap_openr - opena heap relation by name
484+ *relation_openr - openany relation by name
481485 *
482- *If lockmode is not "NoLock", the specified kind of lock is
483- *obtained on the relation.
484- *An error is raised if the relation does not exist.
486+ *As above, but lookup by name instead of OID.
485487 * ----------------
486488 */
487489Relation
488- heap_openr (const char * relationName ,LOCKMODE lockmode )
490+ relation_openr (const char * relationName ,LOCKMODE lockmode )
489491{
490492Relation r ;
491493
@@ -497,116 +499,111 @@ heap_openr(const char *relationName, LOCKMODE lockmode)
497499IncrHeapAccessStat (local_openr );
498500IncrHeapAccessStat (global_openr );
499501
502+ /*
503+ * Check for shared-cache-inval messages before trying to open the
504+ * relation. This is needed to cover the case where the name identifies
505+ * a rel that has been dropped and recreated since the start of our
506+ * transaction: if we don't flush the old relcache entry then we'll
507+ * latch onto that entry and suffer an error when we do LockRelation.
508+ * Note that relation_open does not need to do this, since a relation's
509+ * OID never changes.
510+ *
511+ * We skip this if asked for NoLock, on the assumption that the caller
512+ * has already ensured some appropriate lock is held.
513+ */
514+ if (lockmode != NoLock )
515+ AcceptInvalidationMessages ();
516+
500517/* The relcache does all the real work... */
501518r = RelationNameGetRelation (relationName );
502519
503520if (!RelationIsValid (r ))
504- elog (ERROR ,"Relation '%s' does not exist" ,relationName );
505-
506- /* Under no circumstances will we return an index as a relation. */
507- if (r -> rd_rel -> relkind == RELKIND_INDEX )
508- elog (ERROR ,"%s is an index relation" ,RelationGetRelationName (r ));
521+ elog (ERROR ,"Relation \"%s\" does not exist" ,relationName );
509522
510523if (lockmode != NoLock )
511524LockRelation (r ,lockmode );
512525
513- pgstat_initstats (& r -> pgstat_info ,r );
514-
515- pgstat_initstats (& r -> pgstat_info ,r );
516-
517526return r ;
518527}
519528
520529/* ----------------
521- *heap_open_nofail - open a heap relation by relationId,
522- *do not raise error on failure
530+ *relation_close - close any relation
531+ *
532+ *If lockmode is not "NoLock", we first release the specified lock.
523533 *
524- *The caller must check for a NULL return value indicating
525- *that no such relation exists.
526- *No lock is obtained on the relation, either.
534+ *Note that it is often sensible to hold a lock beyond relation_close;
535+ *in that case, the lock is released automatically at xact end.
527536 * ----------------
528537 */
529- Relation
530- heap_open_nofail ( Oid relationId )
538+ void
539+ relation_close ( Relation relation , LOCKMODE lockmode )
531540{
532- Relation r ;
541+ Assert ( lockmode >= NoLock && lockmode < MAX_LOCKMODES ) ;
533542
534543/*
535544 * increment access statistics
536545 */
537- IncrHeapAccessStat (local_open );
538- IncrHeapAccessStat (global_open );
539-
540- /* The relcache does all the real work... */
541- r = RelationIdGetRelation (relationId );
546+ IncrHeapAccessStat (local_close );
547+ IncrHeapAccessStat (global_close );
542548
543- /* Under no circumstances will we return an index as a relation. */
544- if (RelationIsValid (r )&& r -> rd_rel -> relkind == RELKIND_INDEX )
545- elog (ERROR ,"%s is an index relation" ,RelationGetRelationName (r ));
549+ if (lockmode != NoLock )
550+ UnlockRelation (relation ,lockmode );
546551
547- return r ;
552+ /* The relcache does the real work... */
553+ RelationClose (relation );
548554}
549555
556+
550557/* ----------------
551- *heap_openr_nofail - open a heap relation by name,
552- *do not raise error on failure
558+ *heap_open - open a heap relation by relation OID
553559 *
554- *The caller must check for a NULL return value indicating
555- *that no such relation exists.
556- *No lock is obtained on the relation, either.
560+ *This is essentially relation_open plus check that the relation
561+ *is not an index or special relation. (The caller should also check
562+ *that it's not a view before assuming it has storage.)
557563 * ----------------
558564 */
559565Relation
560- heap_openr_nofail ( const char * relationName )
566+ heap_open ( Oid relationId , LOCKMODE lockmode )
561567{
562568Relation r ;
563569
564- /*
565- * increment access statistics
566- */
567- IncrHeapAccessStat (local_openr );
568- IncrHeapAccessStat (global_openr );
570+ r = relation_open (relationId ,lockmode );
569571
570- /* The relcache does all the real work... */
571- r = RelationNameGetRelation (relationName );
572-
573- /* Under no circumstances will we return an index as a relation. */
574- if (RelationIsValid (r )&& r -> rd_rel -> relkind == RELKIND_INDEX )
575- elog (ERROR ,"%s is an index relation" ,RelationGetRelationName (r ));
576-
577- if (RelationIsValid (r ))
578- pgstat_initstats (& r -> pgstat_info ,r );
572+ if (r -> rd_rel -> relkind == RELKIND_INDEX )
573+ elog (ERROR ,"%s is an index relation" ,
574+ RelationGetRelationName (r ));
575+ else if (r -> rd_rel -> relkind == RELKIND_SPECIAL )
576+ elog (ERROR ,"%s is a special relation" ,
577+ RelationGetRelationName (r ));
579578
580- if (RelationIsValid (r ))
581- pgstat_initstats (& r -> pgstat_info ,r );
579+ pgstat_initstats (& r -> pgstat_info ,r );
582580
583581return r ;
584582}
585583
586584/* ----------------
587- *heap_close -close a heap relation
585+ *heap_openr -open a heap relation by name
588586 *
589- *If lockmode is not "NoLock", we first release the specified lock.
590- *Note that it is often sensible to hold a lock beyond heap_close;
591- *in that case, the lock is released automatically at xact end.
587+ *As above, but lookup by name instead of OID.
592588 * ----------------
593589 */
594- void
595- heap_close ( Relation relation ,LOCKMODE lockmode )
590+ Relation
591+ heap_openr ( const char * relationName ,LOCKMODE lockmode )
596592{
597- Assert ( lockmode >= NoLock && lockmode < MAX_LOCKMODES ) ;
593+ Relation r ;
598594
599- /*
600- * increment access statistics
601- */
602- IncrHeapAccessStat (local_close );
603- IncrHeapAccessStat (global_close );
595+ r = relation_openr (relationName ,lockmode );
604596
605- if (lockmode != NoLock )
606- UnlockRelation (relation ,lockmode );
597+ if (r -> rd_rel -> relkind == RELKIND_INDEX )
598+ elog (ERROR ,"%s is an index relation" ,
599+ RelationGetRelationName (r ));
600+ else if (r -> rd_rel -> relkind == RELKIND_SPECIAL )
601+ elog (ERROR ,"%s is a special relation" ,
602+ RelationGetRelationName (r ));
607603
608- /* The relcache does the real work... */
609- RelationClose (relation );
604+ pgstat_initstats (& r -> pgstat_info ,r );
605+
606+ return r ;
610607}
611608
612609
@@ -2332,8 +2329,7 @@ newsame:;
23322329}
23332330
23342331/* undo */
2335- if (XLByteLT (PageGetLSN (page ),lsn ))/* changes are not applied
2336- * ?! */
2332+ if (XLByteLT (PageGetLSN (page ),lsn ))/* changes not applied?! */
23372333elog (STOP ,"heap_update_undo: bad new tuple page LSN" );
23382334
23392335elog (STOP ,"heap_update_undo: unimplemented" );