LCOV - code coverage report
Current view: top level - src/backend/catalog - indexing.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta1 Lines: 53 54 98.1 %
Date: 2019-06-16 15:06:48 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * indexing.c
       4             :  *    This file contains routines to support indexes defined on system
       5             :  *    catalogs.
       6             :  *
       7             :  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
       8             :  * Portions Copyright (c) 1994, Regents of the University of California
       9             :  *
      10             :  *
      11             :  * IDENTIFICATION
      12             :  *    src/backend/catalog/indexing.c
      13             :  *
      14             :  *-------------------------------------------------------------------------
      15             :  */
      16             : #include "postgres.h"
      17             : 
      18             : #include "access/genam.h"
      19             : #include "access/heapam.h"
      20             : #include "access/htup_details.h"
      21             : #include "catalog/index.h"
      22             : #include "catalog/indexing.h"
      23             : #include "executor/executor.h"
      24             : #include "utils/rel.h"
      25             : 
      26             : 
      27             : /*
      28             :  * CatalogOpenIndexes - open the indexes on a system catalog.
      29             :  *
      30             :  * When inserting or updating tuples in a system catalog, call this
      31             :  * to prepare to update the indexes for the catalog.
      32             :  *
      33             :  * In the current implementation, we share code for opening/closing the
      34             :  * indexes with execUtils.c.  But we do not use ExecInsertIndexTuples,
      35             :  * because we don't want to create an EState.  This implies that we
      36             :  * do not support partial or expressional indexes on system catalogs,
      37             :  * nor can we support generalized exclusion constraints.
      38             :  * This could be fixed with localized changes here if we wanted to pay
      39             :  * the extra overhead of building an EState.
      40             :  */
      41             : CatalogIndexState
      42     1703892 : CatalogOpenIndexes(Relation heapRel)
      43             : {
      44             :     ResultRelInfo *resultRelInfo;
      45             : 
      46     1703892 :     resultRelInfo = makeNode(ResultRelInfo);
      47     1703892 :     resultRelInfo->ri_RangeTableIndex = 0;   /* dummy */
      48     1703892 :     resultRelInfo->ri_RelationDesc = heapRel;
      49     1703892 :     resultRelInfo->ri_TrigDesc = NULL;   /* we don't fire triggers */
      50             : 
      51     1703892 :     ExecOpenIndices(resultRelInfo, false);
      52             : 
      53     1703892 :     return resultRelInfo;
      54             : }
      55             : 
      56             : /*
      57             :  * CatalogCloseIndexes - clean up resources allocated by CatalogOpenIndexes
      58             :  */
      59             : void
      60     1703890 : CatalogCloseIndexes(CatalogIndexState indstate)
      61             : {
      62     1703890 :     ExecCloseIndices(indstate);
      63     1703890 :     pfree(indstate);
      64     1703890 : }
      65             : 
      66             : /*
      67             :  * CatalogIndexInsert - insert index entries for one catalog tuple
      68             :  *
      69             :  * This should be called for each inserted or updated catalog tuple.
      70             :  *
      71             :  * This is effectively a cut-down version of ExecInsertIndexTuples.
      72             :  */
      73             : static void
      74     2822502 : CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
      75             : {
      76             :     int         i;
      77             :     int         numIndexes;
      78             :     RelationPtr relationDescs;
      79             :     Relation    heapRelation;
      80             :     TupleTableSlot *slot;
      81             :     IndexInfo **indexInfoArray;
      82             :     Datum       values[INDEX_MAX_KEYS];
      83             :     bool        isnull[INDEX_MAX_KEYS];
      84             : 
      85             :     /*
      86             :      * HOT update does not require index inserts. But with asserts enabled we
      87             :      * want to check that it'd be legal to currently insert into the
      88             :      * table/index.
      89             :      */
      90             : #ifndef USE_ASSERT_CHECKING
      91     2822502 :     if (HeapTupleIsHeapOnly(heapTuple))
      92      864864 :         return;
      93             : #endif
      94             : 
      95             :     /*
      96             :      * Get information from the state structure.  Fall out if nothing to do.
      97             :      */
      98     2688036 :     numIndexes = indstate->ri_NumIndices;
      99     2688036 :     if (numIndexes == 0)
     100      595932 :         return;
     101     2092104 :     relationDescs = indstate->ri_IndexRelationDescs;
     102     2092104 :     indexInfoArray = indstate->ri_IndexRelationInfo;
     103     2092104 :     heapRelation = indstate->ri_RelationDesc;
     104             : 
     105             :     /* Need a slot to hold the tuple being examined */
     106     2092104 :     slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
     107             :                                     &TTSOpsHeapTuple);
     108     2092104 :     ExecStoreHeapTuple(heapTuple, slot, false);
     109             : 
     110             :     /*
     111             :      * for each index, form and insert the index tuple
     112             :      */
     113     6104638 :     for (i = 0; i < numIndexes; i++)
     114             :     {
     115             :         IndexInfo  *indexInfo;
     116             :         Relation    index;
     117             : 
     118     4012536 :         indexInfo = indexInfoArray[i];
     119     4012536 :         index = relationDescs[i];
     120             : 
     121             :         /* If the index is marked as read-only, ignore it */
     122     4012536 :         if (!indexInfo->ii_ReadyForInserts)
     123           0 :             continue;
     124             : 
     125             :         /*
     126             :          * Expressional and partial indexes on system catalogs are not
     127             :          * supported, nor exclusion constraints, nor deferred uniqueness
     128             :          */
     129             :         Assert(indexInfo->ii_Expressions == NIL);
     130             :         Assert(indexInfo->ii_Predicate == NIL);
     131             :         Assert(indexInfo->ii_ExclusionOps == NULL);
     132             :         Assert(index->rd_index->indimmediate);
     133             :         Assert(indexInfo->ii_NumIndexKeyAttrs != 0);
     134             : 
     135             :         /* see earlier check above */
     136             : #ifdef USE_ASSERT_CHECKING
     137             :         if (HeapTupleIsHeapOnly(heapTuple))
     138             :         {
     139             :             Assert(!ReindexIsProcessingIndex(RelationGetRelid(index)));
     140             :             continue;
     141             :         }
     142             : #endif                          /* USE_ASSERT_CHECKING */
     143             : 
     144             :         /*
     145             :          * FormIndexDatum fills in its values and isnull parameters with the
     146             :          * appropriate values for the column(s) of the index.
     147             :          */
     148     4012536 :         FormIndexDatum(indexInfo,
     149             :                        slot,
     150             :                        NULL,    /* no expression eval to do */
     151             :                        values,
     152             :                        isnull);
     153             : 
     154             :         /*
     155             :          * The index AM does the rest.
     156             :          */
     157     4012536 :         index_insert(index,     /* index relation */
     158             :                      values,    /* array of index Datums */
     159             :                      isnull,    /* is-null flags */
     160             :                      &(heapTuple->t_self),   /* tid of heap tuple */
     161             :                      heapRelation,
     162     4012536 :                      index->rd_index->indisunique ?
     163             :                      UNIQUE_CHECK_YES : UNIQUE_CHECK_NO,
     164             :                      indexInfo);
     165             :     }
     166             : 
     167     2092102 :     ExecDropSingleTupleTableSlot(slot);
     168             : }
     169             : 
     170             : /*
     171             :  * CatalogTupleInsert - do heap and indexing work for a new catalog tuple
     172             :  *
     173             :  * Insert the tuple data in "tup" into the specified catalog relation.
     174             :  * The Oid of the inserted tuple is returned.
     175             :  *
     176             :  * This is a convenience routine for the common case of inserting a single
     177             :  * tuple in a system catalog; it inserts a new heap tuple, keeping indexes
     178             :  * current.  Avoid using it for multiple tuples, since opening the indexes
     179             :  * and building the index info structures is moderately expensive.
     180             :  * (Use CatalogTupleInsertWithInfo in such cases.)
     181             :  */
     182             : void
     183      765602 : CatalogTupleInsert(Relation heapRel, HeapTuple tup)
     184             : {
     185             :     CatalogIndexState indstate;
     186             : 
     187      765602 :     indstate = CatalogOpenIndexes(heapRel);
     188             : 
     189      765602 :     simple_heap_insert(heapRel, tup);
     190             : 
     191      765602 :     CatalogIndexInsert(indstate, tup);
     192      765600 :     CatalogCloseIndexes(indstate);
     193      765600 : }
     194             : 
     195             : /*
     196             :  * CatalogTupleInsertWithInfo - as above, but with caller-supplied index info
     197             :  *
     198             :  * This should be used when it's important to amortize CatalogOpenIndexes/
     199             :  * CatalogCloseIndexes work across multiple insertions.  At some point we
     200             :  * might cache the CatalogIndexState data somewhere (perhaps in the relcache)
     201             :  * so that callers needn't trouble over this ... but we don't do so today.
     202             :  */
     203             : void
     204     1869966 : CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup,
     205             :                            CatalogIndexState indstate)
     206             : {
     207     1869966 :     simple_heap_insert(heapRel, tup);
     208             : 
     209     1869966 :     CatalogIndexInsert(indstate, tup);
     210     1869966 : }
     211             : 
     212             : /*
     213             :  * CatalogTupleUpdate - do heap and indexing work for updating a catalog tuple
     214             :  *
     215             :  * Update the tuple identified by "otid", replacing it with the data in "tup".
     216             :  *
     217             :  * This is a convenience routine for the common case of updating a single
     218             :  * tuple in a system catalog; it updates one heap tuple, keeping indexes
     219             :  * current.  Avoid using it for multiple tuples, since opening the indexes
     220             :  * and building the index info structures is moderately expensive.
     221             :  * (Use CatalogTupleUpdateWithInfo in such cases.)
     222             :  */
     223             : void
     224      185026 : CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
     225             : {
     226             :     CatalogIndexState indstate;
     227             : 
     228      185026 :     indstate = CatalogOpenIndexes(heapRel);
     229             : 
     230      185026 :     simple_heap_update(heapRel, otid, tup);
     231             : 
     232      185026 :     CatalogIndexInsert(indstate, tup);
     233      185026 :     CatalogCloseIndexes(indstate);
     234      185026 : }
     235             : 
     236             : /*
     237             :  * CatalogTupleUpdateWithInfo - as above, but with caller-supplied index info
     238             :  *
     239             :  * This should be used when it's important to amortize CatalogOpenIndexes/
     240             :  * CatalogCloseIndexes work across multiple updates.  At some point we
     241             :  * might cache the CatalogIndexState data somewhere (perhaps in the relcache)
     242             :  * so that callers needn't trouble over this ... but we don't do so today.
     243             :  */
     244             : void
     245        1908 : CatalogTupleUpdateWithInfo(Relation heapRel, ItemPointer otid, HeapTuple tup,
     246             :                            CatalogIndexState indstate)
     247             : {
     248        1908 :     simple_heap_update(heapRel, otid, tup);
     249             : 
     250        1908 :     CatalogIndexInsert(indstate, tup);
     251        1908 : }
     252             : 
     253             : /*
     254             :  * CatalogTupleDelete - do heap and indexing work for deleting a catalog tuple
     255             :  *
     256             :  * Delete the tuple identified by "tid" in the specified catalog.
     257             :  *
     258             :  * With Postgres heaps, there is no index work to do at deletion time;
     259             :  * cleanup will be done later by VACUUM.  However, callers of this function
     260             :  * shouldn't have to know that; we'd like a uniform abstraction for all
     261             :  * catalog tuple changes.  Hence, provide this currently-trivial wrapper.
     262             :  *
     263             :  * The abstraction is a bit leaky in that we don't provide an optimized
     264             :  * CatalogTupleDeleteWithInfo version, because there is currently nothing to
     265             :  * optimize.  If we ever need that, rather than touching a lot of call sites,
     266             :  * it might be better to do something about caching CatalogIndexState.
     267             :  */
     268             : void
     269      461994 : CatalogTupleDelete(Relation heapRel, ItemPointer tid)
     270             : {
     271      461994 :     simple_heap_delete(heapRel, tid);
     272      461994 : }

Generated by: LCOV version 1.13