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