1/*-------------------------------------------------------------------------
4 * This file contains routines to support indexes defined on system
7 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * src/backend/catalog/indexing.c
14 *-------------------------------------------------------------------------
29 * CatalogOpenIndexes - open the indexes on a system catalog.
31 * When inserting or updating tuples in a system catalog, call this
32 * to prepare to update the indexes for the catalog.
34 * In the current implementation, we share code for opening/closing the
35 * indexes with execUtils.c. But we do not use ExecInsertIndexTuples,
36 * because we don't want to create an EState. This implies that we
37 * do not support partial or expressional indexes on system catalogs,
38 * nor can we support generalized exclusion constraints.
39 * This could be fixed with localized changes here if we wanted to pay
40 * the extra overhead of building an EState.
50 resultRelInfo->
ri_TrigDesc = NULL;
/* we don't fire triggers */
58 * CatalogCloseIndexes - clean up resources allocated by CatalogOpenIndexes
68 * CatalogIndexInsert - insert index entries for one catalog tuple
70 * This should be called for each inserted or updated catalog tuple.
72 * This is effectively a cut-down version of ExecInsertIndexTuples.
89 * HOT update does not require index inserts. But with asserts enabled we
90 * want to check that it'd be legal to currently insert into the
93#ifndef USE_ASSERT_CHECKING
98 /* When only updating summarized indexes, the tuple has to be HOT. */
102 * Get information from the state structure. Fall out if nothing to do.
111 /* Need a slot to hold the tuple being examined */
117 * for each index, form and insert the index tuple
119 for (
i = 0;
i < numIndexes;
i++)
124 indexInfo = indexInfoArray[
i];
127 /* If the index is marked as read-only, ignore it */
132 * Expressional and partial indexes on system catalogs are not
133 * supported, nor exclusion constraints, nor deferred uniqueness
141 /* see earlier check above */
142#ifdef USE_ASSERT_CHECKING
148#endif /* USE_ASSERT_CHECKING */
151 * Skip insertions into non-summarizing indexes if we only need to
152 * update summarizing indexes.
158 * FormIndexDatum fills in its values and isnull parameters with the
159 * appropriate values for the column(s) of the index.
163 NULL,
/* no expression eval to do */
168 * The index AM does the rest.
171 values,
/* array of index Datums */
172 isnull,
/* is-null flags */
173 &(heapTuple->
t_self),
/* tid of heap tuple */
175 index->rd_index->indisunique ?
185 * Subroutine to verify that catalog constraints are honored.
187 * Tuples inserted via CatalogTupleInsert/CatalogTupleUpdate are generally
188 * "hand made", so that it's possible that they fail to satisfy constraints
189 * that would be checked if they were being inserted by the executor. That's
190 * a coding error, so we only bother to check for it in assert-enabled builds.
192#ifdef USE_ASSERT_CHECKING
198 * Currently, the only constraints implemented for system catalogs are
199 * attnotnull constraints.
215#else /* !USE_ASSERT_CHECKING */
217 #define CatalogTupleCheckConstraints(heapRel, tup) ((void) 0)
219#endif /* USE_ASSERT_CHECKING */
222 * CatalogTupleInsert - do heap and indexing work for a new catalog tuple
224 * Insert the tuple data in "tup" into the specified catalog relation.
226 * This is a convenience routine for the common case of inserting a single
227 * tuple in a system catalog; it inserts a new heap tuple, keeping indexes
228 * current. Avoid using it for multiple tuples, since opening the indexes
229 * and building the index info structures is moderately expensive.
230 * (Use CatalogTupleInsertWithInfo in such cases.)
248 * CatalogTupleInsertWithInfo - as above, but with caller-supplied index info
250 * This should be used when it's important to amortize CatalogOpenIndexes/
251 * CatalogCloseIndexes work across multiple insertions. At some point we
252 * might cache the CatalogIndexState data somewhere (perhaps in the relcache)
253 * so that callers needn't trouble over this ... but we don't do so today.
267 * CatalogTuplesMultiInsertWithInfo - as above, but for multiple tuples
269 * Insert multiple tuples into the given catalog relation at once, with an
270 * amortized cost of CatalogOpenIndexes.
284 * There is no equivalent to heap_multi_insert for the catalog indexes, so
285 * we must loop over and insert individually.
287 for (
int i = 0;
i < ntuples;
i++)
302 * CatalogTupleUpdate - do heap and indexing work for updating a catalog tuple
304 * Update the tuple identified by "otid", replacing it with the data in "tup".
306 * This is a convenience routine for the common case of updating a single
307 * tuple in a system catalog; it updates one heap tuple, keeping indexes
308 * current. Avoid using it for multiple tuples, since opening the indexes
309 * and building the index info structures is moderately expensive.
310 * (Use CatalogTupleUpdateWithInfo in such cases.)
329 * CatalogTupleUpdateWithInfo - as above, but with caller-supplied index info
331 * This should be used when it's important to amortize CatalogOpenIndexes/
332 * CatalogCloseIndexes work across multiple updates. At some point we
333 * might cache the CatalogIndexState data somewhere (perhaps in the relcache)
334 * so that callers needn't trouble over this ... but we don't do so today.
350 * CatalogTupleDelete - do heap and indexing work for deleting a catalog tuple
352 * Delete the tuple identified by "tid" in the specified catalog.
354 * With Postgres heaps, there is no index work to do at deletion time;
355 * cleanup will be done later by VACUUM. However, callers of this function
356 * shouldn't have to know that; we'd like a uniform abstraction for all
357 * catalog tuple changes. Hence, provide this currently-trivial wrapper.
359 * The abstraction is a bit leaky in that we don't provide an optimized
360 * CatalogTupleDeleteWithInfo version, because there is currently nothing to
361 * optimize. If we ever need that, rather than touching a lot of call sites,
362 * it might be better to do something about caching CatalogIndexState.
static Datum values[MAXATTR]
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
const TupleTableSlotOps TTSOpsHeapTuple
TupleTableSlot * ExecStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
Assert(PointerIsAligned(start, uint64))
void simple_heap_delete(Relation relation, ItemPointer tid)
void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup, TU_UpdateIndexes *update_indexes)
void simple_heap_insert(Relation relation, HeapTuple tup)
void heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples, CommandId cid, int options, BulkInsertState bistate)
void heap_freetuple(HeapTuple htup)
static bool HeapTupleHasNulls(const HeapTupleData *tuple)
static bool HeapTupleIsHeapOnly(const HeapTupleData *tuple)
bool ReindexIsProcessingIndex(Oid indexOid)
void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
bool index_insert(Relation indexRelation, Datum *values, bool *isnull, ItemPointer heap_t_ctid, Relation heapRelation, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
static void CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple, TU_UpdateIndexes updateIndexes)
void CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, int ntuples, CatalogIndexState indstate)
#define CatalogTupleCheckConstraints(heapRel, tup)
void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate)
void CatalogCloseIndexes(CatalogIndexState indstate)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
void CatalogTupleUpdateWithInfo(Relation heapRel, ItemPointer otid, HeapTuple tup, CatalogIndexState indstate)
void pfree(void *pointer)
FormData_pg_attribute * Form_pg_attribute
#define RelationGetRelid(relation)
#define RelationGetDescr(relation)
RelationPtr ri_IndexRelationDescs
TriggerDesc * ri_TrigDesc
IndexInfo ** ri_IndexRelationInfo
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
static bool att_isnull(int ATT, const bits8 *BITS)
CommandId GetCurrentCommandId(bool used)