PostgreSQL Source Code  git master
indexing.c
Go to the documentation of this file.
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  */
43 {
44  ResultRelInfo *resultRelInfo;
45 
46  resultRelInfo = makeNode(ResultRelInfo);
47  resultRelInfo->ri_RangeTableIndex = 0; /* dummy */
48  resultRelInfo->ri_RelationDesc = heapRel;
49  resultRelInfo->ri_TrigDesc = NULL; /* we don't fire triggers */
50 
51  ExecOpenIndices(resultRelInfo, false);
52 
53  return resultRelInfo;
54 }
55 
56 /*
57  * CatalogCloseIndexes - clean up resources allocated by CatalogOpenIndexes
58  */
59 void
61 {
62  ExecCloseIndices(indstate);
63  pfree(indstate);
64 }
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
75 {
76  int i;
77  int numIndexes;
78  RelationPtr relationDescs;
79  Relation heapRelation;
80  TupleTableSlot *slot;
81  IndexInfo **indexInfoArray;
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  if (HeapTupleIsHeapOnly(heapTuple))
92  return;
93 #endif
94 
95  /*
96  * Get information from the state structure. Fall out if nothing to do.
97  */
98  numIndexes = indstate->ri_NumIndices;
99  if (numIndexes == 0)
100  return;
101  relationDescs = indstate->ri_IndexRelationDescs;
102  indexInfoArray = indstate->ri_IndexRelationInfo;
103  heapRelation = indstate->ri_RelationDesc;
104 
105  /* Need a slot to hold the tuple being examined */
106  slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
107  &TTSOpsHeapTuple);
108  ExecStoreHeapTuple(heapTuple, slot, false);
109 
110  /*
111  * for each index, form and insert the index tuple
112  */
113  for (i = 0; i < numIndexes; i++)
114  {
115  IndexInfo *indexInfo;
116  Relation index;
117 
118  indexInfo = indexInfoArray[i];
119  index = relationDescs[i];
120 
121  /* If the index is marked as read-only, ignore it */
122  if (!indexInfo->ii_ReadyForInserts)
123  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  {
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  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  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  index->rd_index->indisunique ?
164  indexInfo);
165  }
166 
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
184 {
185  CatalogIndexState indstate;
186 
187  indstate = CatalogOpenIndexes(heapRel);
188 
189  simple_heap_insert(heapRel, tup);
190 
191  CatalogIndexInsert(indstate, tup);
192  CatalogCloseIndexes(indstate);
193 }
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
205  CatalogIndexState indstate)
206 {
207  simple_heap_insert(heapRel, tup);
208 
209  CatalogIndexInsert(indstate, tup);
210 }
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
225 {
226  CatalogIndexState indstate;
227 
228  indstate = CatalogOpenIndexes(heapRel);
229 
230  simple_heap_update(heapRel, otid, tup);
231 
232  CatalogIndexInsert(indstate, tup);
233  CatalogCloseIndexes(indstate);
234 }
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
246  CatalogIndexState indstate)
247 {
248  simple_heap_update(heapRel, otid, tup);
249 
250  CatalogIndexInsert(indstate, tup);
251 }
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
270 {
271  simple_heap_delete(heapRel, tid);
272 }
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
Definition: index.c:2517
int ri_NumIndices
Definition: execnodes.h:414
#define NIL
Definition: pg_list.h:65
Relation ri_RelationDesc
Definition: execnodes.h:411
List * ii_Predicate
Definition: execnodes.h:162
#define RelationGetDescr(relation)
Definition: rel.h:449
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1208
static void CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
Definition: indexing.c:74
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
Index ri_RangeTableIndex
Definition: execnodes.h:408
void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
Definition: execIndexing.c:151
Definition: type.h:89
Form_pg_index rd_index
Definition: rel.h:143
void pfree(void *pointer)
Definition: mcxt.c:1056
int ii_NumIndexKeyAttrs
Definition: execnodes.h:158
ItemPointerData t_self
Definition: htup.h:65
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1224
bool ii_ReadyForInserts
Definition: execnodes.h:171
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:423
void simple_heap_insert(Relation relation, HeapTuple tup)
Definition: heapam.c:2384
void CatalogTupleUpdateWithInfo(Relation heapRel, ItemPointer otid, HeapTuple tup, CatalogIndexState indstate)
Definition: indexing.c:245
uintptr_t Datum
Definition: postgres.h:367
void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate)
Definition: indexing.c:204
#define makeNode(_type_)
Definition: nodes.h:573
List * ii_Expressions
Definition: execnodes.h:160
#define HeapTupleIsHeapOnly(tuple)
Definition: htup_details.h:685
#define Assert(condition)
Definition: c.h:733
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:42
#define INDEX_MAX_KEYS
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
void simple_heap_delete(Relation relation, ItemPointer tid)
Definition: heapam.c:2847
void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
Definition: heapam.c:3885
static Datum values[MAXATTR]
Definition: bootstrap.c:167
Oid * ii_ExclusionOps
Definition: execnodes.h:164
IndexInfo ** ri_IndexRelationInfo
Definition: execnodes.h:420
int i
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:84
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:60
bool ReindexIsProcessingIndex(Oid indexOid)
Definition: index.c:3742
#define RelationGetRelid(relation)
Definition: rel.h:423
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:226
RelationPtr ri_IndexRelationDescs
Definition: execnodes.h:417
TupleTableSlot * ExecStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1322
bool index_insert(Relation indexRelation, Datum *values, bool *isnull, ItemPointer heap_t_ctid, Relation heapRelation, IndexUniqueCheck checkUnique, IndexInfo *indexInfo)
Definition: indexam.c:170