PostgreSQL Source Code git master
Loading...
Searching...
No Matches
index.h File Reference
Include dependency graph for index.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ReindexParams
 
struct  ValidateIndexState
 

Macros

#define DEFAULT_INDEX_TYPE   "btree"
 
#define REINDEXOPT_VERBOSE   0x01 /* print progress info */
 
#define REINDEXOPT_REPORT_PROGRESS   0x02 /* report pgstat progress */
 
#define REINDEXOPT_MISSING_OK   0x04 /* skip missing relations */
 
#define REINDEXOPT_CONCURRENTLY   0x08 /* concurrent mode */
 
#define INDEX_CREATE_IS_PRIMARY   (1 << 0)
 
#define INDEX_CREATE_ADD_CONSTRAINT   (1 << 1)
 
#define INDEX_CREATE_SKIP_BUILD   (1 << 2)
 
#define INDEX_CREATE_CONCURRENT   (1 << 3)
 
#define INDEX_CREATE_IF_NOT_EXISTS   (1 << 4)
 
#define INDEX_CREATE_PARTITIONED   (1 << 5)
 
#define INDEX_CREATE_INVALID   (1 << 6)
 
#define INDEX_CONSTR_CREATE_MARK_AS_PRIMARY   (1 << 0)
 
#define INDEX_CONSTR_CREATE_DEFERRABLE   (1 << 1)
 
#define INDEX_CONSTR_CREATE_INIT_DEFERRED   (1 << 2)
 
#define INDEX_CONSTR_CREATE_UPDATE_INDEX   (1 << 3)
 
#define INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS   (1 << 4)
 
#define INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS   (1 << 5)
 
#define REINDEX_REL_PROCESS_TOAST   0x01
 
#define REINDEX_REL_SUPPRESS_INDEX_USE   0x02
 
#define REINDEX_REL_CHECK_CONSTRAINTS   0x04
 
#define REINDEX_REL_FORCE_INDEXES_UNLOGGED   0x08
 
#define REINDEX_REL_FORCE_INDEXES_PERMANENT   0x10
 

Typedefs

typedef struct ReindexParams ReindexParams
 
typedef struct ValidateIndexState ValidateIndexState
 

Enumerations

enum  IndexStateFlagsAction { INDEX_CREATE_SET_READY , INDEX_CREATE_SET_VALID , INDEX_DROP_CLEAR_VALID , INDEX_DROP_SET_DEAD }
 

Functions

void index_check_primary_key (Relation heapRel, const IndexInfo *indexInfo, bool is_alter_table, const IndexStmt *stmt)
 
Oid index_create (Relation heapRelation, const char *indexRelationName, Oid indexRelationId, Oid parentIndexRelid, Oid parentConstraintId, RelFileNumber relFileNumber, IndexInfo *indexInfo, const List *indexColNames, Oid accessMethodId, Oid tableSpaceId, const Oid *collationIds, const Oid *opclassIds, const Datum *opclassOptions, const int16 *coloptions, const NullableDatum *stattargets, Datum reloptions, bits16 flags, bits16 constr_flags, bool allow_system_table_mods, bool is_internal, Oid *constraintId)
 
Oid index_concurrently_create_copy (Relation heapRelation, Oid oldIndexId, Oid tablespaceOid, const char *newName)
 
void index_concurrently_build (Oid heapRelationId, Oid indexRelationId)
 
void index_concurrently_swap (Oid newIndexId, Oid oldIndexId, const char *oldName)
 
void index_concurrently_set_dead (Oid heapId, Oid indexId)
 
ObjectAddress index_constraint_create (Relation heapRelation, Oid indexRelationId, Oid parentConstraintId, const IndexInfo *indexInfo, const char *constraintName, char constraintType, bits16 constr_flags, bool allow_system_table_mods, bool is_internal)
 
void index_drop (Oid indexId, bool concurrent, bool concurrent_lock_mode)
 
IndexInfoBuildIndexInfo (Relation index)
 
IndexInfoBuildDummyIndexInfo (Relation index)
 
bool CompareIndexInfo (const IndexInfo *info1, const IndexInfo *info2, const Oid *collations1, const Oid *collations2, const Oid *opfamilies1, const Oid *opfamilies2, const AttrMap *attmap)
 
void BuildSpeculativeIndexInfo (Relation index, IndexInfo *ii)
 
void FormIndexDatum (IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)
 
void index_build (Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isreindex, bool parallel)
 
void validate_index (Oid heapId, Oid indexId, Snapshot snapshot)
 
void index_set_state_flags (Oid indexId, IndexStateFlagsAction action)
 
Oid IndexGetRelation (Oid indexId, bool missing_ok)
 
void reindex_index (const ReindexStmt *stmt, Oid indexId, bool skip_constraint_checks, char persistence, const ReindexParams *params)
 
bool reindex_relation (const ReindexStmt *stmt, Oid relid, int flags, const ReindexParams *params)
 
bool ReindexIsProcessingHeap (Oid heapOid)
 
bool ReindexIsProcessingIndex (Oid indexOid)
 
void ResetReindexState (int nestLevel)
 
Size EstimateReindexStateSpace (void)
 
void SerializeReindexState (Size maxsize, char *start_address)
 
void RestoreReindexState (const void *reindexstate)
 
void IndexSetParentIndex (Relation partitionIdx, Oid parentOid)
 
static int64 itemptr_encode (const ItemPointerData *itemptr)
 
static void itemptr_decode (ItemPointer itemptr, int64 encoded)
 

Macro Definition Documentation

◆ DEFAULT_INDEX_TYPE

#define DEFAULT_INDEX_TYPE   "btree"

Definition at line 21 of file index.h.

◆ INDEX_CONSTR_CREATE_DEFERRABLE

#define INDEX_CONSTR_CREATE_DEFERRABLE   (1 << 1)

Definition at line 92 of file index.h.

◆ INDEX_CONSTR_CREATE_INIT_DEFERRED

#define INDEX_CONSTR_CREATE_INIT_DEFERRED   (1 << 2)

Definition at line 93 of file index.h.

◆ INDEX_CONSTR_CREATE_MARK_AS_PRIMARY

#define INDEX_CONSTR_CREATE_MARK_AS_PRIMARY   (1 << 0)

Definition at line 91 of file index.h.

◆ INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS

#define INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS   (1 << 4)

Definition at line 95 of file index.h.

◆ INDEX_CONSTR_CREATE_UPDATE_INDEX

#define INDEX_CONSTR_CREATE_UPDATE_INDEX   (1 << 3)

Definition at line 94 of file index.h.

◆ INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS

#define INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS   (1 << 5)

Definition at line 96 of file index.h.

◆ INDEX_CREATE_ADD_CONSTRAINT

#define INDEX_CREATE_ADD_CONSTRAINT   (1 << 1)

Definition at line 62 of file index.h.

◆ INDEX_CREATE_CONCURRENT

#define INDEX_CREATE_CONCURRENT   (1 << 3)

Definition at line 64 of file index.h.

◆ INDEX_CREATE_IF_NOT_EXISTS

#define INDEX_CREATE_IF_NOT_EXISTS   (1 << 4)

Definition at line 65 of file index.h.

◆ INDEX_CREATE_INVALID

#define INDEX_CREATE_INVALID   (1 << 6)

Definition at line 67 of file index.h.

◆ INDEX_CREATE_IS_PRIMARY

#define INDEX_CREATE_IS_PRIMARY   (1 << 0)

Definition at line 61 of file index.h.

◆ INDEX_CREATE_PARTITIONED

#define INDEX_CREATE_PARTITIONED   (1 << 5)

Definition at line 66 of file index.h.

◆ INDEX_CREATE_SKIP_BUILD

#define INDEX_CREATE_SKIP_BUILD   (1 << 2)

Definition at line 63 of file index.h.

◆ REINDEX_REL_CHECK_CONSTRAINTS

#define REINDEX_REL_CHECK_CONSTRAINTS   0x04

Definition at line 161 of file index.h.

◆ REINDEX_REL_FORCE_INDEXES_PERMANENT

#define REINDEX_REL_FORCE_INDEXES_PERMANENT   0x10

Definition at line 163 of file index.h.

◆ REINDEX_REL_FORCE_INDEXES_UNLOGGED

#define REINDEX_REL_FORCE_INDEXES_UNLOGGED   0x08

Definition at line 162 of file index.h.

◆ REINDEX_REL_PROCESS_TOAST

#define REINDEX_REL_PROCESS_TOAST   0x01

Definition at line 159 of file index.h.

◆ REINDEX_REL_SUPPRESS_INDEX_USE

#define REINDEX_REL_SUPPRESS_INDEX_USE   0x02

Definition at line 160 of file index.h.

◆ REINDEXOPT_CONCURRENTLY

#define REINDEXOPT_CONCURRENTLY   0x08 /* concurrent mode */

Definition at line 44 of file index.h.

◆ REINDEXOPT_MISSING_OK

#define REINDEXOPT_MISSING_OK   0x04 /* skip missing relations */

Definition at line 43 of file index.h.

◆ REINDEXOPT_REPORT_PROGRESS

#define REINDEXOPT_REPORT_PROGRESS   0x02 /* report pgstat progress */

Definition at line 42 of file index.h.

◆ REINDEXOPT_VERBOSE

#define REINDEXOPT_VERBOSE   0x01 /* print progress info */

Definition at line 41 of file index.h.

Typedef Documentation

◆ ReindexParams

◆ ValidateIndexState

Enumeration Type Documentation

◆ IndexStateFlagsAction

Enumerator
INDEX_CREATE_SET_READY 
INDEX_CREATE_SET_VALID 
INDEX_DROP_CLEAR_VALID 
INDEX_DROP_SET_DEAD 

Definition at line 24 of file index.h.

25{
IndexStateFlagsAction
Definition index.h:25
@ INDEX_CREATE_SET_VALID
Definition index.h:27
@ INDEX_DROP_CLEAR_VALID
Definition index.h:28
@ INDEX_DROP_SET_DEAD
Definition index.h:29
@ INDEX_CREATE_SET_READY
Definition index.h:26

Function Documentation

◆ BuildDummyIndexInfo()

IndexInfo * BuildDummyIndexInfo ( Relation  index)
extern

Definition at line 2488 of file index.c.

2489{
2490 IndexInfo *ii;
2491 Form_pg_index indexStruct = index->rd_index;
2492 int i;
2493 int numAtts;
2494
2495 /* check the number of keys, and copy attr numbers into the IndexInfo */
2496 numAtts = indexStruct->indnatts;
2498 elog(ERROR, "invalid indnatts %d for index %u",
2500
2501 /*
2502 * Create the node, using dummy index expressions, and pretending there is
2503 * no predicate.
2504 */
2505 ii = makeIndexInfo(indexStruct->indnatts,
2506 indexStruct->indnkeyatts,
2507 index->rd_rel->relam,
2509 NIL,
2510 indexStruct->indisunique,
2511 indexStruct->indnullsnotdistinct,
2512 indexStruct->indisready,
2513 false,
2514 index->rd_indam->amsummarizing,
2515 indexStruct->indisexclusion && indexStruct->indisunique);
2516
2517 /* fill in attribute numbers */
2518 for (i = 0; i < numAtts; i++)
2519 ii->ii_IndexAttrNumbers[i] = indexStruct->indkey.values[i];
2520
2521 /* We ignore the exclusion constraint if any */
2522
2523 return ii;
2524}
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
int i
Definition isn.c:77
IndexInfo * makeIndexInfo(int numattrs, int numkeyattrs, Oid amoid, List *expressions, List *predicates, bool unique, bool nulls_not_distinct, bool isready, bool concurrent, bool summarizing, bool withoutoverlaps)
Definition makefuncs.c:834
#define INDEX_MAX_KEYS
END_CATALOG_STRUCT typedef FormData_pg_index * Form_pg_index
Definition pg_index.h:74
#define NIL
Definition pg_list.h:68
static int fb(int x)
#define RelationGetRelid(relation)
Definition rel.h:514
List * RelationGetDummyIndexExpressions(Relation relation)
Definition relcache.c:5145
AttrNumber ii_IndexAttrNumbers[INDEX_MAX_KEYS]
Definition execnodes.h:177
Definition type.h:96

References elog, ERROR, fb(), Form_pg_index, i, IndexInfo::ii_IndexAttrNumbers, INDEX_MAX_KEYS, makeIndexInfo(), NIL, RelationGetDummyIndexExpressions(), and RelationGetRelid.

Referenced by RelationTruncateIndexes().

◆ BuildIndexInfo()

IndexInfo * BuildIndexInfo ( Relation  index)
extern

Definition at line 2428 of file index.c.

2429{
2430 IndexInfo *ii;
2431 Form_pg_index indexStruct = index->rd_index;
2432 int i;
2433 int numAtts;
2434
2435 /* check the number of keys, and copy attr numbers into the IndexInfo */
2436 numAtts = indexStruct->indnatts;
2438 elog(ERROR, "invalid indnatts %d for index %u",
2440
2441 /*
2442 * Create the node, fetching any expressions needed for expressional
2443 * indexes and index predicate if any.
2444 */
2445 ii = makeIndexInfo(indexStruct->indnatts,
2446 indexStruct->indnkeyatts,
2447 index->rd_rel->relam,
2450 indexStruct->indisunique,
2451 indexStruct->indnullsnotdistinct,
2452 indexStruct->indisready,
2453 false,
2454 index->rd_indam->amsummarizing,
2455 indexStruct->indisexclusion && indexStruct->indisunique);
2456
2457 /* fill in attribute numbers */
2458 for (i = 0; i < numAtts; i++)
2459 ii->ii_IndexAttrNumbers[i] = indexStruct->indkey.values[i];
2460
2461 /* fetch exclusion constraint info if any */
2462 if (indexStruct->indisexclusion)
2463 {
2465 &ii->ii_ExclusionOps,
2466 &ii->ii_ExclusionProcs,
2467 &ii->ii_ExclusionStrats);
2468 }
2469
2470 return ii;
2471}
List * RelationGetIndexPredicate(Relation relation)
Definition relcache.c:5199
List * RelationGetIndexExpressions(Relation relation)
Definition relcache.c:5086
void RelationGetExclusionInfo(Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
Definition relcache.c:5642
uint16 * ii_ExclusionStrats
Definition execnodes.h:194
Oid * ii_ExclusionOps
Definition execnodes.h:190
Oid * ii_ExclusionProcs
Definition execnodes.h:192

References elog, ERROR, fb(), Form_pg_index, i, IndexInfo::ii_ExclusionOps, IndexInfo::ii_ExclusionProcs, IndexInfo::ii_ExclusionStrats, IndexInfo::ii_IndexAttrNumbers, INDEX_MAX_KEYS, makeIndexInfo(), RelationGetExclusionInfo(), RelationGetIndexExpressions(), RelationGetIndexPredicate(), and RelationGetRelid.

Referenced by _brin_parallel_scan_and_build(), _bt_parallel_scan_and_sort(), _gin_parallel_scan_and_build(), ATExecAddIndexConstraint(), ATExecAttachPartitionIdx(), AttachPartitionEnsureIndexes(), brinsummarize(), bt_check_every_level(), build_index_value_desc(), DefineIndex(), do_analyze_rel(), ExecOpenIndices(), index_concurrently_build(), index_concurrently_create_copy(), reindex_index(), tuplesort_begin_cluster(), unique_key_recheck(), and validate_index().

◆ BuildSpeculativeIndexInfo()

void BuildSpeculativeIndexInfo ( Relation  index,
IndexInfo ii 
)
extern

Definition at line 2669 of file index.c.

2670{
2671 int indnkeyatts;
2672 int i;
2673
2675
2676 /*
2677 * fetch info for checking unique indexes
2678 */
2679 Assert(ii->ii_Unique);
2680
2684
2685 /*
2686 * We have to look up the operator's strategy number. This provides a
2687 * cross-check that the operator does match the index.
2688 */
2689 /* We need the func OIDs and strategy numbers too */
2690 for (i = 0; i < indnkeyatts; i++)
2691 {
2692 ii->ii_UniqueStrats[i] =
2694 index->rd_rel->relam,
2695 index->rd_opfamily[i],
2696 false);
2697 ii->ii_UniqueOps[i] =
2698 get_opfamily_member(index->rd_opfamily[i],
2699 index->rd_opcintype[i],
2700 index->rd_opcintype[i],
2701 ii->ii_UniqueStrats[i]);
2702 if (!OidIsValid(ii->ii_UniqueOps[i]))
2703 elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
2704 ii->ii_UniqueStrats[i], index->rd_opcintype[i],
2705 index->rd_opcintype[i], index->rd_opfamily[i]);
2707 }
2708}
StrategyNumber IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, bool missing_ok)
Definition amapi.c:161
#define Assert(condition)
Definition c.h:927
uint16_t uint16
Definition c.h:599
#define OidIsValid(objectId)
Definition c.h:842
@ COMPARE_EQ
Definition cmptype.h:36
#define palloc_array(type, count)
Definition fe_memutils.h:76
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1503
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition lsyscache.c:168
unsigned int Oid
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition rel.h:533
bool ii_Unique
Definition execnodes.h:202
Oid * ii_UniqueOps
Definition execnodes.h:197
uint16 * ii_UniqueStrats
Definition execnodes.h:199
Oid * ii_UniqueProcs
Definition execnodes.h:198

References Assert, COMPARE_EQ, elog, ERROR, fb(), get_opcode(), get_opfamily_member(), i, IndexInfo::ii_Unique, IndexInfo::ii_UniqueOps, IndexInfo::ii_UniqueProcs, IndexInfo::ii_UniqueStrats, IndexAmTranslateCompareType(), IndexRelationGetNumberOfKeyAttributes, OidIsValid, and palloc_array.

Referenced by BuildConflictIndexInfo(), and ExecOpenIndices().

◆ CompareIndexInfo()

bool CompareIndexInfo ( const IndexInfo info1,
const IndexInfo info2,
const Oid collations1,
const Oid collations2,
const Oid opfamilies1,
const Oid opfamilies2,
const AttrMap attmap 
)
extern

Definition at line 2537 of file index.c.

2541{
2542 int i;
2543
2544 if (info1->ii_Unique != info2->ii_Unique)
2545 return false;
2546
2547 if (info1->ii_NullsNotDistinct != info2->ii_NullsNotDistinct)
2548 return false;
2549
2550 /* indexes are only equivalent if they have the same access method */
2551 if (info1->ii_Am != info2->ii_Am)
2552 return false;
2553
2554 /* and same number of attributes */
2555 if (info1->ii_NumIndexAttrs != info2->ii_NumIndexAttrs)
2556 return false;
2557
2558 /* and same number of key attributes */
2559 if (info1->ii_NumIndexKeyAttrs != info2->ii_NumIndexKeyAttrs)
2560 return false;
2561
2562 /*
2563 * and columns match through the attribute map (actual attribute numbers
2564 * might differ!) Note that this checks that index columns that are
2565 * expressions appear in the same positions. We will next compare the
2566 * expressions themselves.
2567 */
2568 for (i = 0; i < info1->ii_NumIndexAttrs; i++)
2569 {
2570 if (attmap->maplen < info2->ii_IndexAttrNumbers[i])
2571 elog(ERROR, "incorrect attribute map");
2572
2573 /* ignore expressions for now (but check their collation/opfamily) */
2574 if (!(info1->ii_IndexAttrNumbers[i] == InvalidAttrNumber &&
2575 info2->ii_IndexAttrNumbers[i] == InvalidAttrNumber))
2576 {
2577 /* fail if just one index has an expression in this column */
2578 if (info1->ii_IndexAttrNumbers[i] == InvalidAttrNumber ||
2579 info2->ii_IndexAttrNumbers[i] == InvalidAttrNumber)
2580 return false;
2581
2582 /* both are columns, so check for match after mapping */
2583 if (attmap->attnums[info2->ii_IndexAttrNumbers[i] - 1] !=
2584 info1->ii_IndexAttrNumbers[i])
2585 return false;
2586 }
2587
2588 /* collation and opfamily are not valid for included columns */
2589 if (i >= info1->ii_NumIndexKeyAttrs)
2590 continue;
2591
2592 if (collations1[i] != collations2[i])
2593 return false;
2594 if (opfamilies1[i] != opfamilies2[i])
2595 return false;
2596 }
2597
2598 /*
2599 * For expression indexes: either both are expression indexes, or neither
2600 * is; if they are, make sure the expressions match.
2601 */
2602 if ((info1->ii_Expressions != NIL) != (info2->ii_Expressions != NIL))
2603 return false;
2604 if (info1->ii_Expressions != NIL)
2605 {
2606 bool found_whole_row;
2607 Node *mapped;
2608
2609 mapped = map_variable_attnos((Node *) info2->ii_Expressions,
2610 1, 0, attmap,
2611 InvalidOid, &found_whole_row);
2612 if (found_whole_row)
2613 {
2614 /*
2615 * we could throw an error here, but seems out of scope for this
2616 * routine.
2617 */
2618 return false;
2619 }
2620
2621 if (!equal(info1->ii_Expressions, mapped))
2622 return false;
2623 }
2624
2625 /* Partial index predicates must be identical, if they exist */
2626 if ((info1->ii_Predicate == NULL) != (info2->ii_Predicate == NULL))
2627 return false;
2628 if (info1->ii_Predicate != NULL)
2629 {
2630 bool found_whole_row;
2631 Node *mapped;
2632
2633 mapped = map_variable_attnos((Node *) info2->ii_Predicate,
2634 1, 0, attmap,
2635 InvalidOid, &found_whole_row);
2636 if (found_whole_row)
2637 {
2638 /*
2639 * we could throw an error here, but seems out of scope for this
2640 * routine.
2641 */
2642 return false;
2643 }
2644 if (!equal(info1->ii_Predicate, mapped))
2645 return false;
2646 }
2647
2648 /* No support currently for comparing exclusion indexes. */
2649 if (info1->ii_ExclusionOps != NULL || info2->ii_ExclusionOps != NULL)
2650 return false;
2651
2652 return true;
2653}
#define InvalidAttrNumber
Definition attnum.h:23
bool equal(const void *a, const void *b)
Definition equalfuncs.c:223
#define InvalidOid
Node * map_variable_attnos(Node *node, int target_varno, int sublevels_up, const AttrMap *attno_map, Oid to_rowtype, bool *found_whole_row)
Definition nodes.h:135

References elog, equal(), ERROR, fb(), i, InvalidAttrNumber, InvalidOid, map_variable_attnos(), and NIL.

Referenced by ATExecAttachPartitionIdx(), AttachPartitionEnsureIndexes(), and DefineIndex().

◆ EstimateReindexStateSpace()

Size EstimateReindexStateSpace ( void  )
extern

Definition at line 4242 of file index.c.

4243{
4246}
static List * pendingReindexedIndexes
Definition index.c:4111
static int list_length(const List *l)
Definition pg_list.h:152
Size mul_size(Size s1, Size s2)
Definition shmem.c:497

References fb(), list_length(), mul_size(), and pendingReindexedIndexes.

Referenced by InitializeParallelDSM().

◆ FormIndexDatum()

void FormIndexDatum ( IndexInfo indexInfo,
TupleTableSlot slot,
EState estate,
Datum values,
bool isnull 
)
extern

Definition at line 2730 of file index.c.

2735{
2737 int i;
2738
2739 if (indexInfo->ii_Expressions != NIL &&
2740 indexInfo->ii_ExpressionsState == NIL)
2741 {
2742 /* First time through, set up expression evaluation state */
2743 indexInfo->ii_ExpressionsState =
2744 ExecPrepareExprList(indexInfo->ii_Expressions, estate);
2745 /* Check caller has set up context correctly */
2746 Assert(GetPerTupleExprContext(estate)->ecxt_scantuple == slot);
2747 }
2749
2750 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
2751 {
2752 int keycol = indexInfo->ii_IndexAttrNumbers[i];
2753 Datum iDatum;
2754 bool isNull;
2755
2756 if (keycol < 0)
2757 iDatum = slot_getsysattr(slot, keycol, &isNull);
2758 else if (keycol != 0)
2759 {
2760 /*
2761 * Plain index column; get the value we need directly from the
2762 * heap tuple.
2763 */
2764 iDatum = slot_getattr(slot, keycol, &isNull);
2765 }
2766 else
2767 {
2768 /*
2769 * Index expression --- need to evaluate it.
2770 */
2771 if (indexpr_item == NULL)
2772 elog(ERROR, "wrong number of index expressions");
2774 GetPerTupleExprContext(estate),
2775 &isNull);
2777 }
2778 values[i] = iDatum;
2779 isnull[i] = isNull;
2780 }
2781
2782 if (indexpr_item != NULL)
2783 elog(ERROR, "wrong number of index expressions");
2784}
static Datum values[MAXATTR]
Definition bootstrap.c:187
List * ExecPrepareExprList(List *nodes, EState *estate)
Definition execExpr.c:872
#define GetPerTupleExprContext(estate)
Definition executor.h:659
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:438
#define lfirst(lc)
Definition pg_list.h:172
static ListCell * list_head(const List *l)
Definition pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition pg_list.h:343
uint64_t Datum
Definition postgres.h:70
int ii_NumIndexAttrs
Definition execnodes.h:169
List * ii_ExpressionsState
Definition execnodes.h:182
List * ii_Expressions
Definition execnodes.h:180
static Datum slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition tuptable.h:438
static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
Definition tuptable.h:417

References Assert, elog, ERROR, ExecEvalExprSwitchContext(), ExecPrepareExprList(), fb(), GetPerTupleExprContext, i, IndexInfo::ii_Expressions, IndexInfo::ii_ExpressionsState, IndexInfo::ii_IndexAttrNumbers, IndexInfo::ii_NumIndexAttrs, lfirst, list_head(), lnext(), NIL, slot_getattr(), slot_getsysattr(), and values.

Referenced by build_index_value_desc(), CatalogIndexInsert(), check_exclusion_or_unique_constraint(), comparetup_cluster_tiebreak(), compute_index_stats(), ExecCheckIndexConstraints(), ExecInsertIndexTuples(), heapam_index_build_range_scan(), heapam_index_validate_scan(), IndexCheckExclusion(), and unique_key_recheck().

◆ index_build()

void index_build ( Relation  heapRelation,
Relation  indexRelation,
IndexInfo indexInfo,
bool  isreindex,
bool  parallel 
)
extern

Definition at line 3002 of file index.c.

3007{
3008 IndexBuildResult *stats;
3009 Oid save_userid;
3010 int save_sec_context;
3011 int save_nestlevel;
3012
3013 /*
3014 * sanity checks
3015 */
3016 Assert(RelationIsValid(indexRelation));
3017 Assert(indexRelation->rd_indam);
3018 Assert(indexRelation->rd_indam->ambuild);
3019 Assert(indexRelation->rd_indam->ambuildempty);
3020
3021 /*
3022 * Determine worker process details for parallel CREATE INDEX. Currently,
3023 * only btree, GIN, and BRIN have support for parallel builds.
3024 *
3025 * Note that planner considers parallel safety for us.
3026 */
3028 indexRelation->rd_indam->amcanbuildparallel)
3029 indexInfo->ii_ParallelWorkers =
3031 RelationGetRelid(indexRelation));
3032
3033 if (indexInfo->ii_ParallelWorkers == 0)
3035 (errmsg_internal("building index \"%s\" on table \"%s\" serially",
3036 RelationGetRelationName(indexRelation),
3037 RelationGetRelationName(heapRelation))));
3038 else
3040 (errmsg_internal("building index \"%s\" on table \"%s\" with request for %d parallel workers",
3041 RelationGetRelationName(indexRelation),
3042 RelationGetRelationName(heapRelation),
3043 indexInfo->ii_ParallelWorkers)));
3044
3045 /*
3046 * Switch to the table owner's userid, so that any index functions are run
3047 * as that user. Also lock down security-restricted operations and
3048 * arrange to make GUC variable changes local to this command.
3049 */
3050 GetUserIdAndSecContext(&save_userid, &save_sec_context);
3051 SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
3052 save_sec_context | SECURITY_RESTRICTED_OPERATION);
3053 save_nestlevel = NewGUCNestLevel();
3055
3056 /* Set up initial progress report status */
3057 {
3058 const int progress_index[] = {
3065 };
3066 const int64 progress_vals[] = {
3069 0, 0, 0, 0
3070 };
3071
3073 }
3074
3075 /*
3076 * Call the access method's build procedure
3077 */
3078 stats = indexRelation->rd_indam->ambuild(heapRelation, indexRelation,
3079 indexInfo);
3080 Assert(stats);
3081
3082 /*
3083 * If this is an unlogged index, we may need to write out an init fork for
3084 * it -- but we must first check whether one already exists. If, for
3085 * example, an unlogged relation is truncated in the transaction that
3086 * created it, or truncated twice in a subsequent transaction, the
3087 * relfilenumber won't change, and nothing needs to be done here.
3088 */
3089 if (indexRelation->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED &&
3090 !smgrexists(RelationGetSmgr(indexRelation), INIT_FORKNUM))
3091 {
3092 smgrcreate(RelationGetSmgr(indexRelation), INIT_FORKNUM, false);
3093 log_smgrcreate(&indexRelation->rd_locator, INIT_FORKNUM);
3094 indexRelation->rd_indam->ambuildempty(indexRelation);
3095 }
3096
3097 /*
3098 * If we found any potentially broken HOT chains, mark the index as not
3099 * being usable until the current transaction is below the event horizon.
3100 * See src/backend/access/heap/README.HOT for discussion. While it might
3101 * become safe to use the index earlier based on actual cleanup activity
3102 * and other active transactions, the test for that would be much more
3103 * complex and would require some form of blocking, so keep it simple and
3104 * fast by just using the current transaction.
3105 *
3106 * However, when reindexing an existing index, we should do nothing here.
3107 * Any HOT chains that are broken with respect to the index must predate
3108 * the index's original creation, so there is no need to change the
3109 * index's usability horizon. Moreover, we *must not* try to change the
3110 * index's pg_index entry while reindexing pg_index itself, and this
3111 * optimization nicely prevents that. The more complex rules needed for a
3112 * reindex are handled separately after this function returns.
3113 *
3114 * We also need not set indcheckxmin during a concurrent index build,
3115 * because we won't set indisvalid true until all transactions that care
3116 * about the broken HOT chains are gone.
3117 *
3118 * Therefore, this code path can only be taken during non-concurrent
3119 * CREATE INDEX. Thus the fact that heap_update will set the pg_index
3120 * tuple's xmin doesn't matter, because that tuple was created in the
3121 * current transaction anyway. That also means we don't need to worry
3122 * about any concurrent readers of the tuple; no other transaction can see
3123 * it yet.
3124 */
3125 if (indexInfo->ii_BrokenHotChain &&
3126 !isreindex &&
3127 !indexInfo->ii_Concurrent)
3128 {
3129 Oid indexId = RelationGetRelid(indexRelation);
3133
3135
3139 elog(ERROR, "cache lookup failed for index %u", indexId);
3141
3142 /* If it's a new index, indcheckxmin shouldn't be set ... */
3143 Assert(!indexForm->indcheckxmin);
3144
3145 indexForm->indcheckxmin = true;
3147
3150 }
3151
3152 /*
3153 * Update heap and index pg_class rows
3154 */
3155 index_update_stats(heapRelation,
3156 true,
3157 stats->heap_tuples);
3158
3159 index_update_stats(indexRelation,
3160 false,
3161 stats->index_tuples);
3162
3163 /* Make the updated catalog row versions visible */
3165
3166 /*
3167 * If it's for an exclusion constraint, make a second pass over the heap
3168 * to verify that the constraint is satisfied. We must not do this until
3169 * the index is fully valid. (Broken HOT chains shouldn't matter, though;
3170 * see comments for IndexCheckExclusion.)
3171 */
3172 if (indexInfo->ii_ExclusionOps != NULL)
3173 IndexCheckExclusion(heapRelation, indexRelation, indexInfo);
3174
3175 /* Roll back any GUC changes executed by index functions */
3176 AtEOXact_GUC(false, save_nestlevel);
3177
3178 /* Restore userid and security context */
3179 SetUserIdAndSecContext(save_userid, save_sec_context);
3180}
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
int64_t int64
Definition c.h:597
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define DEBUG1
Definition elog.h:30
#define ereport(elevel,...)
Definition elog.h:150
int NewGUCNestLevel(void)
Definition guc.c:2110
void RestrictSearchPath(void)
Definition guc.c:2121
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition guc.c:2137
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1383
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
static void index_update_stats(Relation rel, bool hasindex, double reltuples)
Definition index.c:2809
static void IndexCheckExclusion(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo)
Definition index.c:3195
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
#define RowExclusiveLock
Definition lockdefs.h:38
#define SECURITY_RESTRICTED_OPERATION
Definition miscadmin.h:319
#define IsNormalProcessingMode()
Definition miscadmin.h:479
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition miscinit.c:613
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition miscinit.c:620
int plan_create_index_workers(Oid tableOid, Oid indexOid)
Definition planner.c:7021
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
#define PROGRESS_CREATEIDX_PHASE_BUILD
Definition progress.h:120
#define PROGRESS_CREATEIDX_TUPLES_TOTAL
Definition progress.h:112
#define PROGRESS_SCAN_BLOCKS_DONE
Definition progress.h:148
#define PROGRESS_CREATEIDX_TUPLES_DONE
Definition progress.h:113
#define PROGRESS_CREATEIDX_SUBPHASE
Definition progress.h:111
#define PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE
Definition progress.h:132
#define PROGRESS_CREATEIDX_PHASE
Definition progress.h:110
#define PROGRESS_SCAN_BLOCKS_TOTAL
Definition progress.h:147
static SMgrRelation RelationGetSmgr(Relation rel)
Definition rel.h:576
#define RelationGetRelationName(relation)
Definition rel.h:548
#define RelationIsValid(relation)
Definition rel.h:489
@ INIT_FORKNUM
Definition relpath.h:61
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition smgr.c:481
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition smgr.c:462
void log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum)
Definition storage.c:187
ambuildempty_function ambuildempty
Definition amapi.h:296
ambuild_function ambuild
Definition amapi.h:295
bool amcanbuildparallel
Definition amapi.h:276
double heap_tuples
Definition genam.h:38
double index_tuples
Definition genam.h:39
bool ii_BrokenHotChain
Definition execnodes.h:214
int ii_ParallelWorkers
Definition execnodes.h:220
bool ii_Concurrent
Definition execnodes.h:212
const struct IndexAmRoutine * rd_indam
Definition rel.h:206
RelFileLocator rd_locator
Definition rel.h:57
Form_pg_class rd_rel
Definition rel.h:111
#define SearchSysCacheCopy1(cacheId, key1)
Definition syscache.h:91
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
void CommandCounterIncrement(void)
Definition xact.c:1102

References IndexAmRoutine::ambuild, IndexAmRoutine::ambuildempty, IndexAmRoutine::amcanbuildparallel, Assert, AtEOXact_GUC(), CatalogTupleUpdate(), CommandCounterIncrement(), DEBUG1, elog, ereport, errmsg_internal(), ERROR, fb(), Form_pg_index, GETSTRUCT(), GetUserIdAndSecContext(), heap_freetuple(), IndexBuildResult::heap_tuples, HeapTupleIsValid, IndexInfo::ii_BrokenHotChain, IndexInfo::ii_Concurrent, IndexInfo::ii_ExclusionOps, IndexInfo::ii_ParallelWorkers, IndexBuildResult::index_tuples, index_update_stats(), IndexCheckExclusion(), INIT_FORKNUM, IsNormalProcessingMode, log_smgrcreate(), NewGUCNestLevel(), ObjectIdGetDatum(), pgstat_progress_update_multi_param(), plan_create_index_workers(), PROGRESS_CREATEIDX_PHASE, PROGRESS_CREATEIDX_PHASE_BUILD, PROGRESS_CREATEIDX_SUBPHASE, PROGRESS_CREATEIDX_SUBPHASE_INITIALIZE, PROGRESS_CREATEIDX_TUPLES_DONE, PROGRESS_CREATEIDX_TUPLES_TOTAL, PROGRESS_SCAN_BLOCKS_DONE, PROGRESS_SCAN_BLOCKS_TOTAL, RelationData::rd_indam, RelationData::rd_locator, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, RelationGetSmgr(), RelationIsValid, RestrictSearchPath(), RowExclusiveLock, SearchSysCacheCopy1, SECURITY_RESTRICTED_OPERATION, SetUserIdAndSecContext(), smgrcreate(), smgrexists(), table_close(), and table_open().

Referenced by build_indices(), index_concurrently_build(), index_create(), reindex_index(), and RelationTruncateIndexes().

◆ index_check_primary_key()

void index_check_primary_key ( Relation  heapRel,
const IndexInfo indexInfo,
bool  is_alter_table,
const IndexStmt stmt 
)
extern

Definition at line 202 of file index.c.

206{
207 int i;
208
209 /*
210 * If ALTER TABLE or CREATE TABLE .. PARTITION OF, check that there isn't
211 * already a PRIMARY KEY. In CREATE TABLE for an ordinary relation, we
212 * have faith that the parser rejected multiple pkey clauses; and CREATE
213 * INDEX doesn't have a way to say PRIMARY KEY, so it's no problem either.
214 */
215 if ((is_alter_table || heapRel->rd_rel->relispartition) &&
216 relationHasPrimaryKey(heapRel))
217 {
220 errmsg("multiple primary keys for table \"%s\" are not allowed",
221 RelationGetRelationName(heapRel))));
222 }
223
224 /*
225 * Indexes created with NULLS NOT DISTINCT cannot be used for primary key
226 * constraints. While there is no direct syntax to reach here, it can be
227 * done by creating a separate index and attaching it via ALTER TABLE ..
228 * USING INDEX.
229 */
230 if (indexInfo->ii_NullsNotDistinct)
231 {
234 errmsg("primary keys cannot use NULLS NOT DISTINCT indexes")));
235 }
236
237 /*
238 * Check that all of the attributes in a primary key are marked as not
239 * null. (We don't really expect to see that; it'd mean the parser messed
240 * up. But it seems wise to check anyway.)
241 */
242 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
243 {
247
248 if (attnum == 0)
251 errmsg("primary keys cannot be expressions")));
252
253 /* System attributes are never null, so no need to check */
254 if (attnum < 0)
255 continue;
256
261 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
262 attnum, RelationGetRelid(heapRel));
264
265 if (!attform->attnotnull)
268 errmsg("primary key column \"%s\" is not marked NOT NULL",
269 NameStr(attform->attname))));
270
272 }
273}
int16 AttrNumber
Definition attnum.h:21
#define NameStr(name)
Definition c.h:819
int errcode(int sqlerrcode)
Definition elog.c:874
static bool relationHasPrimaryKey(Relation rel)
Definition index.c:148
static char * errmsg
int16 attnum
FormData_pg_attribute * Form_pg_attribute
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
bool ii_NullsNotDistinct
Definition execnodes.h:204
int ii_NumIndexKeyAttrs
Definition execnodes.h:171
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:230

References attnum, elog, ereport, errcode(), errmsg, ERROR, fb(), GETSTRUCT(), HeapTupleIsValid, i, IndexInfo::ii_IndexAttrNumbers, IndexInfo::ii_NullsNotDistinct, IndexInfo::ii_NumIndexKeyAttrs, Int16GetDatum(), NameStr, ObjectIdGetDatum(), RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, relationHasPrimaryKey(), ReleaseSysCache(), and SearchSysCache2().

Referenced by ATExecAddIndexConstraint(), and DefineIndex().

◆ index_concurrently_build()

void index_concurrently_build ( Oid  heapRelationId,
Oid  indexRelationId 
)
extern

Definition at line 1485 of file index.c.

1487{
1488 Relation heapRel;
1489 Oid save_userid;
1490 int save_sec_context;
1491 int save_nestlevel;
1492 Relation indexRelation;
1493 IndexInfo *indexInfo;
1494
1495 /* This had better make sure that a snapshot is active */
1497
1498 /* Open and lock the parent heap relation */
1500
1501 /*
1502 * Switch to the table owner's userid, so that any index functions are run
1503 * as that user. Also lock down security-restricted operations and
1504 * arrange to make GUC variable changes local to this command.
1505 */
1506 GetUserIdAndSecContext(&save_userid, &save_sec_context);
1507 SetUserIdAndSecContext(heapRel->rd_rel->relowner,
1508 save_sec_context | SECURITY_RESTRICTED_OPERATION);
1509 save_nestlevel = NewGUCNestLevel();
1511
1513
1514 /*
1515 * We have to re-build the IndexInfo struct, since it was lost in the
1516 * commit of the transaction where this concurrent index was created at
1517 * the catalog level.
1518 */
1519 indexInfo = BuildIndexInfo(indexRelation);
1520 Assert(!indexInfo->ii_ReadyForInserts);
1521 indexInfo->ii_Concurrent = true;
1522 indexInfo->ii_BrokenHotChain = false;
1523
1524 /* Now build the index */
1525 index_build(heapRel, indexRelation, indexInfo, false, true);
1526
1527 /* Roll back any GUC changes executed by index functions */
1528 AtEOXact_GUC(false, save_nestlevel);
1529
1530 /* Restore userid and security context */
1531 SetUserIdAndSecContext(save_userid, save_sec_context);
1532
1533 /* Close both the relations, but keep the locks */
1534 table_close(heapRel, NoLock);
1535 index_close(indexRelation, NoLock);
1536
1537 /*
1538 * Update the pg_index row to mark the index as ready for inserts. Once we
1539 * commit this transaction, any new transactions that open the table must
1540 * insert new entries into the index for insertions and non-HOT updates.
1541 */
1543}
void index_set_state_flags(Oid indexId, IndexStateFlagsAction action)
Definition index.c:3503
IndexInfo * BuildIndexInfo(Relation index)
Definition index.c:2428
void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isreindex, bool parallel)
Definition index.c:3002
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:177
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:133
#define NoLock
Definition lockdefs.h:34
#define ShareUpdateExclusiveLock
Definition lockdefs.h:39
bool ActiveSnapshotSet(void)
Definition snapmgr.c:812
bool ii_ReadyForInserts
Definition execnodes.h:206

References ActiveSnapshotSet(), Assert, AtEOXact_GUC(), BuildIndexInfo(), fb(), GetUserIdAndSecContext(), IndexInfo::ii_BrokenHotChain, IndexInfo::ii_Concurrent, IndexInfo::ii_ReadyForInserts, index_build(), index_close(), INDEX_CREATE_SET_READY, index_open(), index_set_state_flags(), NewGUCNestLevel(), NoLock, RelationData::rd_rel, RestrictSearchPath(), RowExclusiveLock, SECURITY_RESTRICTED_OPERATION, SetUserIdAndSecContext(), ShareUpdateExclusiveLock, table_close(), and table_open().

Referenced by DefineIndex(), and ReindexRelationConcurrently().

◆ index_concurrently_create_copy()

Oid index_concurrently_create_copy ( Relation  heapRelation,
Oid  oldIndexId,
Oid  tablespaceOid,
const char newName 
)
extern

Definition at line 1300 of file index.c.

1302{
1303 Relation indexRelation;
1305 *newInfo;
1308 classTuple;
1316 bool isnull;
1318 List *indexExprs = NIL;
1319 List *indexPreds = NIL;
1320
1321 indexRelation = index_open(oldIndexId, RowExclusiveLock);
1322
1323 /* The new index needs some information from the old index */
1324 oldInfo = BuildIndexInfo(indexRelation);
1325
1326 /*
1327 * Concurrent build of an index with exclusion constraints is not
1328 * supported.
1329 */
1330 if (oldInfo->ii_ExclusionOps != NULL)
1331 ereport(ERROR,
1333 errmsg("concurrent index creation for exclusion constraints is not supported")));
1334
1335 /* Get the array of class and column options IDs from index info */
1338 elog(ERROR, "cache lookup failed for index %u", oldIndexId);
1342
1346
1347 /* Fetch reloptions of index if any */
1350 elog(ERROR, "cache lookup failed for relation %u", oldIndexId);
1352 Anum_pg_class_reloptions, &isnull);
1353
1354 /*
1355 * Fetch the list of expressions and predicates directly from the
1356 * catalogs. This cannot rely on the information from IndexInfo of the
1357 * old index as these have been flattened for the planner.
1358 */
1359 if (oldInfo->ii_Expressions != NIL)
1360 {
1362 char *exprString;
1363
1369 }
1370 if (oldInfo->ii_Predicate != NIL)
1371 {
1373 char *predString;
1374
1379
1380 /* Also convert to implicit-AND format */
1383 }
1384
1385 /*
1386 * Build the index information for the new index. Note that rebuild of
1387 * indexes with exclusion constraints is not supported, hence there is no
1388 * need to fill all the ii_Exclusion* fields.
1389 */
1390 newInfo = makeIndexInfo(oldInfo->ii_NumIndexAttrs,
1391 oldInfo->ii_NumIndexKeyAttrs,
1392 oldInfo->ii_Am,
1393 indexExprs,
1394 indexPreds,
1395 oldInfo->ii_Unique,
1396 oldInfo->ii_NullsNotDistinct,
1397 false, /* not ready for inserts */
1398 true,
1399 indexRelation->rd_indam->amsummarizing,
1400 oldInfo->ii_WithoutOverlaps);
1401
1402 /*
1403 * Extract the list of column names and the column numbers for the new
1404 * index information. All this information will be used for the index
1405 * creation.
1406 */
1407 for (int i = 0; i < oldInfo->ii_NumIndexAttrs; i++)
1408 {
1409 TupleDesc indexTupDesc = RelationGetDescr(indexRelation);
1411
1413 newInfo->ii_IndexAttrNumbers[i] = oldInfo->ii_IndexAttrNumbers[i];
1414 }
1415
1416 /* Extract opclass options for each attribute */
1417 opclassOptions = palloc0_array(Datum, newInfo->ii_NumIndexAttrs);
1418 for (int i = 0; i < newInfo->ii_NumIndexAttrs; i++)
1420
1421 /* Extract statistic targets for each attribute */
1422 stattargets = palloc0_array(NullableDatum, newInfo->ii_NumIndexAttrs);
1423 for (int i = 0; i < newInfo->ii_NumIndexAttrs; i++)
1424 {
1425 HeapTuple tp;
1426 Datum dat;
1427
1429 if (!HeapTupleIsValid(tp))
1430 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1431 i + 1, oldIndexId);
1433 ReleaseSysCache(tp);
1434 stattargets[i].value = dat;
1435 stattargets[i].isnull = isnull;
1436 }
1437
1438 /*
1439 * Now create the new index.
1440 *
1441 * For a partition index, we adjust the partition dependency later, to
1442 * ensure a consistent state at all times. That is why parentIndexRelid
1443 * is not set here.
1444 */
1445 newIndexId = index_create(heapRelation,
1446 newName,
1447 InvalidOid, /* indexRelationId */
1448 InvalidOid, /* parentIndexRelid */
1449 InvalidOid, /* parentConstraintId */
1450 InvalidRelFileNumber, /* relFileNumber */
1451 newInfo,
1453 indexRelation->rd_rel->relam,
1454 tablespaceOid,
1455 indexRelation->rd_indcollation,
1456 indclass->values,
1458 indcoloptions->values,
1462 0,
1463 true, /* allow table to be a system catalog? */
1464 false, /* is_internal? */
1465 NULL);
1466
1467 /* Close the relations used and clean up */
1468 index_close(indexRelation, NoLock);
1471
1472 return newIndexId;
1473}
#define TextDatumGetCString(d)
Definition builtins.h:99
#define palloc0_array(type, count)
Definition fe_memutils.h:77
Oid index_create(Relation heapRelation, const char *indexRelationName, Oid indexRelationId, Oid parentIndexRelid, Oid parentConstraintId, RelFileNumber relFileNumber, IndexInfo *indexInfo, const List *indexColNames, Oid accessMethodId, Oid tableSpaceId, const Oid *collationIds, const Oid *opclassIds, const Datum *opclassOptions, const int16 *coloptions, const NullableDatum *stattargets, Datum reloptions, bits16 flags, bits16 constr_flags, bool allow_system_table_mods, bool is_internal, Oid *constraintId)
Definition index.c:726
#define INDEX_CREATE_SKIP_BUILD
Definition index.h:63
#define INDEX_CREATE_CONCURRENT
Definition index.h:64
List * lappend(List *list, void *datum)
Definition list.c:339
Datum get_attoptions(Oid relid, int16 attnum)
Definition lsyscache.c:1087
List * make_ands_implicit(Expr *clause)
Definition makefuncs.c:810
void pfree(void *pointer)
Definition mcxt.c:1616
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
void * stringToNode(const char *str)
Definition read.c:90
#define RelationGetDescr(relation)
Definition rel.h:540
#define InvalidRelFileNumber
Definition relpath.h:26
bool amsummarizing
Definition amapi.h:282
Definition pg_list.h:54
Oid * rd_indcollation
Definition rel.h:217
Definition c.h:799
Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition syscache.c:625
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:220
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:595
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178

References IndexAmRoutine::amsummarizing, BuildIndexInfo(), DatumGetPointer(), elog, ereport, errcode(), errmsg, ERROR, fb(), get_attoptions(), HeapTupleIsValid, i, index_close(), index_create(), INDEX_CREATE_CONCURRENT, INDEX_CREATE_SKIP_BUILD, index_open(), Int16GetDatum(), InvalidOid, InvalidRelFileNumber, lappend(), make_ands_implicit(), makeIndexInfo(), NameStr, NIL, NoLock, ObjectIdGetDatum(), palloc0_array, pfree(), RelationData::rd_indam, RelationData::rd_indcollation, RelationData::rd_rel, RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), SearchSysCache2(), stringToNode(), SysCacheGetAttr(), SysCacheGetAttrNotNull(), TextDatumGetCString, and TupleDescAttr().

Referenced by ReindexRelationConcurrently().

◆ index_concurrently_set_dead()

void index_concurrently_set_dead ( Oid  heapId,
Oid  indexId 
)
extern

Definition at line 1823 of file index.c.

1824{
1827
1828 /*
1829 * No more predicate locks will be acquired on this index, and we're about
1830 * to stop doing inserts into the index which could show conflicts with
1831 * existing predicate locks, so now is the time to move them to the heap
1832 * relation.
1833 */
1837
1838 /*
1839 * Now we are sure that nobody uses the index for queries; they just might
1840 * have it open for updating it. So now we can unset indisready and
1841 * indislive, then wait till nobody could be using it at all anymore.
1842 */
1844
1845 /*
1846 * Invalidate the relcache for the table, so that after this commit all
1847 * sessions will refresh the table's index list. Forgetting just the
1848 * index's relcache entry is not enough.
1849 */
1851
1852 /*
1853 * Close the relations again, though still holding session lock.
1854 */
1857}
void CacheInvalidateRelcache(Relation relation)
Definition inval.c:1635
void TransferPredicateLocksToHeapRelation(Relation relation)
Definition predicate.c:3132

References CacheInvalidateRelcache(), fb(), index_close(), INDEX_DROP_SET_DEAD, index_open(), index_set_state_flags(), NoLock, ShareUpdateExclusiveLock, table_close(), table_open(), and TransferPredicateLocksToHeapRelation().

Referenced by index_drop(), and ReindexRelationConcurrently().

◆ index_concurrently_swap()

void index_concurrently_swap ( Oid  newIndexId,
Oid  oldIndexId,
const char oldName 
)
extern

Definition at line 1552 of file index.c.

1553{
1555 pg_index,
1557 pg_trigger;
1568 bool isPartition;
1571 ListCell *lc;
1572
1573 /*
1574 * Take a necessary lock on the old and new index before swapping them.
1575 */
1578
1579 /* Now swap names and dependencies of those indexes */
1581
1585 elog(ERROR, "could not find tuple for relation %u", oldIndexId);
1589 elog(ERROR, "could not find tuple for relation %u", newIndexId);
1590
1593
1594 /* Swap the names */
1595 namestrcpy(&newClassForm->relname, NameStr(oldClassForm->relname));
1596 namestrcpy(&oldClassForm->relname, oldName);
1597
1598 /* Swap the partition flags to track inheritance properly */
1599 isPartition = newClassForm->relispartition;
1600 newClassForm->relispartition = oldClassForm->relispartition;
1601 oldClassForm->relispartition = isPartition;
1602
1605
1608
1609 /* Now swap index info */
1611
1615 elog(ERROR, "could not find tuple for relation %u", oldIndexId);
1619 elog(ERROR, "could not find tuple for relation %u", newIndexId);
1620
1623
1624 /*
1625 * Copy constraint flags from the old index. This is safe because the old
1626 * index guaranteed uniqueness.
1627 */
1628 newIndexForm->indisprimary = oldIndexForm->indisprimary;
1629 oldIndexForm->indisprimary = false;
1630 newIndexForm->indisexclusion = oldIndexForm->indisexclusion;
1631 oldIndexForm->indisexclusion = false;
1632 newIndexForm->indimmediate = oldIndexForm->indimmediate;
1633 oldIndexForm->indimmediate = true;
1634
1635 /* Preserve indisreplident in the new index */
1636 newIndexForm->indisreplident = oldIndexForm->indisreplident;
1637
1638 /* Preserve indisclustered in the new index */
1639 newIndexForm->indisclustered = oldIndexForm->indisclustered;
1640
1641 /*
1642 * Mark the new index as valid, and the old index as invalid similarly to
1643 * what index_set_state_flags() does.
1644 */
1645 newIndexForm->indisvalid = true;
1646 oldIndexForm->indisvalid = false;
1647 oldIndexForm->indisclustered = false;
1648 oldIndexForm->indisreplident = false;
1649
1652
1655
1656 /*
1657 * Move constraints and triggers over to the new index
1658 */
1659
1661
1663
1666
1669
1670 foreach(lc, constraintOids)
1671 {
1675 ScanKeyData key[1];
1676 SysScanDesc scan;
1678
1679 /* Move the constraint from the old to the new index */
1683 elog(ERROR, "could not find tuple for constraint %u", constraintOid);
1684
1686
1687 if (conForm->conindid == oldIndexId)
1688 {
1689 conForm->conindid = newIndexId;
1690
1692 }
1693
1695
1696 /* Search for trigger records */
1697 ScanKeyInit(&key[0],
1701
1703 NULL, 1, key);
1704
1706 {
1708
1709 if (tgForm->tgconstrindid != oldIndexId)
1710 continue;
1711
1712 /* Make a modifiable copy */
1715
1716 tgForm->tgconstrindid = newIndexId;
1717
1719
1721 }
1722
1723 systable_endscan(scan);
1724 }
1725
1726 /*
1727 * Move comment if any
1728 */
1729 {
1731 ScanKeyData skey[3];
1733 HeapTuple tuple;
1735 bool nulls[Natts_pg_description] = {0};
1736 bool replaces[Natts_pg_description] = {0};
1737
1740
1741 ScanKeyInit(&skey[0],
1745 ScanKeyInit(&skey[1],
1749 ScanKeyInit(&skey[2],
1752 Int32GetDatum(0));
1753
1755
1757 NULL, 3, skey);
1758
1759 while ((tuple = systable_getnext(sd)) != NULL)
1760 {
1762 values, nulls, replaces);
1763 CatalogTupleUpdate(description, &tuple->t_self, tuple);
1764
1765 break; /* Assume there can be only one match */
1766 }
1767
1770 }
1771
1772 /*
1773 * Swap inheritance relationship with parent index
1774 */
1776 {
1778 Oid parentIndexRelid = linitial_oid(ancestors);
1779
1782
1783 list_free(ancestors);
1784 }
1785
1786 /*
1787 * Swap all dependencies of and on the old index to the new one, and
1788 * vice-versa. Note that a call to CommandCounterIncrement() would cause
1789 * duplicate entries in pg_depend, so this should not be done.
1790 */
1793
1796
1797 /* copy over statistics from old to new index */
1799
1800 /* Copy data of pg_statistic from the old index to the new one */
1802
1803 /* Close relations */
1808
1809 /* The lock taken previously is not released until the end of transaction */
1812}
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
void CopyStatistics(Oid fromrelid, Oid torelid)
Definition heap.c:3442
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1129
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:697
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
void list_free(List *list)
Definition list.c:1546
bool get_rel_relispartition(Oid relid)
Definition lsyscache.c:2245
void namestrcpy(Name name, const char *str)
Definition name.c:233
List * get_partition_ancestors(Oid relid)
Definition partition.c:134
FormData_pg_class * Form_pg_class
Definition pg_class.h:160
END_CATALOG_STRUCT typedef FormData_pg_constraint * Form_pg_constraint
long changeDependenciesOf(Oid classId, Oid oldObjectId, Oid newObjectId)
Definition pg_depend.c:567
List * get_index_ref_constraints(Oid indexId)
Definition pg_depend.c:1117
long changeDependenciesOn(Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition pg_depend.c:623
Oid get_index_constraint(Oid indexId)
Definition pg_depend.c:1061
bool DeleteInheritsTuple(Oid inhrelid, Oid inhparent, bool expect_detach_pending, const char *childname)
void StoreSingleInheritance(Oid relationId, Oid parentOid, int32 seqNumber)
#define linitial_oid(l)
Definition pg_list.h:180
#define lfirst_oid(lc)
Definition pg_list.h:174
END_CATALOG_STRUCT typedef FormData_pg_trigger * Form_pg_trigger
Definition pg_trigger.h:84
void pgstat_copy_relation_stats(Relation dst, Relation src)
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:47
#define BTEqualStrategyNumber
Definition stratnum.h:31
ItemPointerData t_self
Definition htup.h:65
const char * description

References BTEqualStrategyNumber, CatalogTupleUpdate(), changeDependenciesOf(), changeDependenciesOn(), CopyStatistics(), DeleteInheritsTuple(), description, elog, ERROR, fb(), Form_pg_constraint, Form_pg_index, Form_pg_trigger, get_index_constraint(), get_index_ref_constraints(), get_partition_ancestors(), get_rel_relispartition(), GETSTRUCT(), heap_copytuple(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, Int32GetDatum(), lappend_oid(), lfirst_oid, linitial_oid, list_free(), NameStr, namestrcpy(), NIL, NoLock, ObjectIdGetDatum(), OidIsValid, pgstat_copy_relation_stats(), relation_close(), relation_open(), RelationGetDescr, RowExclusiveLock, ScanKeyInit(), SearchSysCacheCopy1, ShareUpdateExclusiveLock, StoreSingleInheritance(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), and values.

Referenced by ReindexRelationConcurrently().

◆ index_constraint_create()

ObjectAddress index_constraint_create ( Relation  heapRelation,
Oid  indexRelationId,
Oid  parentConstraintId,
const IndexInfo indexInfo,
const char constraintName,
char  constraintType,
bits16  constr_flags,
bool  allow_system_table_mods,
bool  is_internal 
)
extern

Definition at line 1885 of file index.c.

1894{
1895 Oid namespaceId = RelationGetNamespace(heapRelation);
1897 idxaddr;
1898 Oid conOid;
1899 bool deferrable;
1900 bool initdeferred;
1901 bool mark_as_primary;
1902 bool islocal;
1903 bool noinherit;
1905 int16 inhcount;
1906
1907 deferrable = (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) != 0;
1908 initdeferred = (constr_flags & INDEX_CONSTR_CREATE_INIT_DEFERRED) != 0;
1911
1912 /* constraint creation support doesn't work while bootstrapping */
1914
1915 /* enforce system-table restriction */
1917 IsSystemRelation(heapRelation) &&
1919 ereport(ERROR,
1921 errmsg("user-defined indexes on system catalog tables are not supported")));
1922
1923 /* primary/unique constraints shouldn't have any expressions */
1924 if (indexInfo->ii_Expressions &&
1926 elog(ERROR, "constraints cannot have index expressions");
1927
1928 /*
1929 * If we're manufacturing a constraint for a pre-existing index, we need
1930 * to get rid of the existing auto dependencies for the index (the ones
1931 * that index_create() would have made instead of calling this function).
1932 *
1933 * Note: this code would not necessarily do the right thing if the index
1934 * has any expressions or predicate, but we'd never be turning such an
1935 * index into a UNIQUE or PRIMARY KEY constraint.
1936 */
1940
1942 {
1943 islocal = false;
1944 inhcount = 1;
1945 noinherit = false;
1946 }
1947 else
1948 {
1949 islocal = true;
1950 inhcount = 0;
1951 noinherit = true;
1952 }
1953
1954 /*
1955 * Construct a pg_constraint entry.
1956 */
1960 deferrable,
1961 initdeferred,
1962 true, /* Is Enforced */
1963 true,
1965 RelationGetRelid(heapRelation),
1966 indexInfo->ii_IndexAttrNumbers,
1967 indexInfo->ii_NumIndexKeyAttrs,
1968 indexInfo->ii_NumIndexAttrs,
1969 InvalidOid, /* no domain */
1970 indexRelationId, /* index OID */
1971 InvalidOid, /* no foreign key */
1972 NULL,
1973 NULL,
1974 NULL,
1975 NULL,
1976 0,
1977 ' ',
1978 ' ',
1979 NULL,
1980 0,
1981 ' ',
1982 indexInfo->ii_ExclusionOps,
1983 NULL, /* no check constraint */
1984 NULL,
1985 islocal,
1986 inhcount,
1987 noinherit,
1989 is_internal);
1990
1991 /*
1992 * Register the index as internally dependent on the constraint.
1993 *
1994 * Note that the constraint has a dependency on the table, so we don't
1995 * need (or want) any direct dependency from the index to the table.
1996 */
2000
2001 /*
2002 * Also, if this is a constraint on a partition, give it partition-type
2003 * dependencies on the parent constraint as well as the table.
2004 */
2006 {
2008
2012 RelationGetRelid(heapRelation));
2014 }
2015
2016 /*
2017 * If the constraint is deferrable, create the deferred uniqueness
2018 * checking trigger. (The trigger will be given an internal dependency on
2019 * the constraint by CreateTrigger.)
2020 */
2021 if (deferrable)
2022 {
2024
2025 trigger->replace = false;
2026 trigger->isconstraint = true;
2027 trigger->trigname = (constraintType == CONSTRAINT_PRIMARY) ?
2028 "PK_ConstraintTrigger" :
2029 "Unique_ConstraintTrigger";
2030 trigger->relation = NULL;
2031 trigger->funcname = SystemFuncName("unique_key_recheck");
2032 trigger->args = NIL;
2033 trigger->row = true;
2034 trigger->timing = TRIGGER_TYPE_AFTER;
2036 trigger->columns = NIL;
2037 trigger->whenClause = NULL;
2038 trigger->transitionRels = NIL;
2039 trigger->deferrable = true;
2040 trigger->initdeferred = initdeferred;
2041 trigger->constrrel = NULL;
2042
2045 InvalidOid, NULL, true, false);
2046 }
2047
2048 /*
2049 * If needed, mark the index as primary and/or deferred in pg_index.
2050 *
2051 * Note: When making an existing index into a constraint, caller must have
2052 * a table lock that prevents concurrent table updates; otherwise, there
2053 * is a risk that concurrent readers of the table will miss seeing this
2054 * index at all.
2055 */
2057 (mark_as_primary || deferrable))
2058 {
2062 bool dirty = false;
2063 bool marked_as_primary = false;
2064
2066
2070 elog(ERROR, "cache lookup failed for index %u", indexRelationId);
2072
2073 if (mark_as_primary && !indexForm->indisprimary)
2074 {
2075 indexForm->indisprimary = true;
2076 dirty = true;
2077 marked_as_primary = true;
2078 }
2079
2080 if (deferrable && indexForm->indimmediate)
2081 {
2082 indexForm->indimmediate = false;
2083 dirty = true;
2084 }
2085
2086 if (dirty)
2087 {
2089
2090 /*
2091 * When we mark an existing index as primary, force a relcache
2092 * flush on its parent table, so that all sessions will become
2093 * aware that the table now has a primary key. This is important
2094 * because it affects some replication behaviors.
2095 */
2097 CacheInvalidateRelcache(heapRelation);
2098
2100 InvalidOid, is_internal);
2101 }
2102
2105 }
2106
2107 return myself;
2108}
int16_t int16
Definition c.h:595
bool IsSystemRelation(Relation relation)
Definition catalog.c:74
@ DEPENDENCY_AUTO
Definition dependency.h:34
@ DEPENDENCY_INTERNAL
Definition dependency.h:35
@ DEPENDENCY_PARTITION_PRI
Definition dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition dependency.h:37
#define INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS
Definition index.h:96
#define INDEX_CONSTR_CREATE_UPDATE_INDEX
Definition index.h:94
#define INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS
Definition index.h:95
#define INDEX_CONSTR_CREATE_DEFERRABLE
Definition index.h:92
#define INDEX_CONSTR_CREATE_MARK_AS_PRIMARY
Definition index.h:91
#define INDEX_CONSTR_CREATE_INIT_DEFERRED
Definition index.h:93
#define IsBootstrapProcessingMode()
Definition miscadmin.h:477
#define makeNode(_type_)
Definition nodes.h:161
#define InvokeObjectPostAlterHookArg(classId, objectId, subId, auxiliaryId, is_internal)
#define ObjectAddressSet(addr, class_id, object_id)
List * SystemFuncName(char *name)
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isEnforced, bool isValidated, Oid parentConstrId, Oid relId, const int16 *constraintKey, int constraintNKeys, int constraintNTotalKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, const int16 *fkDeleteSetCols, int numFkDeleteSetCols, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, bool conIsLocal, int16 conInhCount, bool conNoInherit, bool conPeriod, bool is_internal)
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition pg_depend.c:47
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition pg_depend.c:353
#define RelationGetNamespace(relation)
Definition rel.h:555
ObjectAddress CreateTrigger(CreateTrigStmt *stmt, const char *queryString, Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, Oid funcoid, Oid parentTriggerOid, Node *whenClause, bool isInternal, bool in_partition)
Definition trigger.c:160

References Assert, CacheInvalidateRelcache(), CatalogTupleUpdate(), CreateConstraintEntry(), CreateTrigger(), deleteDependencyRecordsForClass(), DEPENDENCY_AUTO, DEPENDENCY_INTERNAL, DEPENDENCY_PARTITION_PRI, DEPENDENCY_PARTITION_SEC, elog, ereport, errcode(), errmsg, ERROR, fb(), Form_pg_index, GETSTRUCT(), heap_freetuple(), HeapTupleIsValid, IndexInfo::ii_ExclusionOps, IndexInfo::ii_Expressions, IndexInfo::ii_IndexAttrNumbers, IndexInfo::ii_NumIndexAttrs, IndexInfo::ii_NumIndexKeyAttrs, INDEX_CONSTR_CREATE_DEFERRABLE, INDEX_CONSTR_CREATE_INIT_DEFERRED, INDEX_CONSTR_CREATE_MARK_AS_PRIMARY, INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS, INDEX_CONSTR_CREATE_UPDATE_INDEX, INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS, InvalidOid, InvokeObjectPostAlterHookArg, IsBootstrapProcessingMode, IsNormalProcessingMode, IsSystemRelation(), makeNode, NIL, ObjectAddressSet, ObjectIdGetDatum(), OidIsValid, recordDependencyOn(), RelationGetNamespace, RelationGetRelid, RowExclusiveLock, SearchSysCacheCopy1, SystemFuncName(), table_close(), and table_open().

Referenced by ATExecAddIndexConstraint(), and index_create().

◆ index_create()

Oid index_create ( Relation  heapRelation,
const char indexRelationName,
Oid  indexRelationId,
Oid  parentIndexRelid,
Oid  parentConstraintId,
RelFileNumber  relFileNumber,
IndexInfo indexInfo,
const List indexColNames,
Oid  accessMethodId,
Oid  tableSpaceId,
const Oid collationIds,
const Oid opclassIds,
const Datum opclassOptions,
const int16 coloptions,
const NullableDatum stattargets,
Datum  reloptions,
bits16  flags,
bits16  constr_flags,
bool  allow_system_table_mods,
bool  is_internal,
Oid constraintId 
)
extern

Definition at line 726 of file index.c.

747{
748 Oid heapRelationId = RelationGetRelid(heapRelation);
750 Relation indexRelation;
752 bool shared_relation;
753 bool mapped_relation;
754 bool is_exclusion;
756 int i;
757 char relpersistence;
758 bool isprimary = (flags & INDEX_CREATE_IS_PRIMARY) != 0;
759 bool invalid = (flags & INDEX_CREATE_INVALID) != 0;
760 bool concurrent = (flags & INDEX_CREATE_CONCURRENT) != 0;
761 bool partitioned = (flags & INDEX_CREATE_PARTITIONED) != 0;
762 char relkind;
763 TransactionId relfrozenxid;
764 MultiXactId relminmxid;
766
767 /* constraint flags can only be set when a constraint is requested */
768 Assert((constr_flags == 0) ||
769 ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0));
770 /* partitioned indexes must never be "built" by themselves */
772
774 is_exclusion = (indexInfo->ii_ExclusionOps != NULL);
775
777
778 /*
779 * The index will be in the same namespace as its parent table, and is
780 * shared across databases if and only if the parent is. Likewise, it
781 * will use the relfilenumber map if and only if the parent does; and it
782 * inherits the parent's relpersistence.
783 */
784 namespaceId = RelationGetNamespace(heapRelation);
785 shared_relation = heapRelation->rd_rel->relisshared;
786 mapped_relation = RelationIsMapped(heapRelation);
787 relpersistence = heapRelation->rd_rel->relpersistence;
788
789 /*
790 * check parameters
791 */
792 if (indexInfo->ii_NumIndexAttrs < 1)
793 elog(ERROR, "must index at least one column");
794
796 IsSystemRelation(heapRelation) &&
800 errmsg("user-defined indexes on system catalog tables are not supported")));
801
802 /*
803 * Btree text_pattern_ops uses texteq as the equality operator, which is
804 * fine as long as the collation is deterministic; texteq then reduces to
805 * bitwise equality and so it is semantically compatible with the other
806 * operators and functions in that opclass. But with a nondeterministic
807 * collation, texteq could yield results that are incompatible with the
808 * actual behavior of the index (which is determined by the opclass's
809 * comparison function). We prevent such problems by refusing creation of
810 * an index with that opclass and a nondeterministic collation.
811 *
812 * The same applies to varchar_pattern_ops and bpchar_pattern_ops. If we
813 * find more cases, we might decide to create a real mechanism for marking
814 * opclasses as incompatible with nondeterminism; but for now, this small
815 * hack suffices.
816 *
817 * Another solution is to use a special operator, not texteq, as the
818 * equality opclass member; but that is undesirable because it would
819 * prevent index usage in many queries that work fine today.
820 */
821 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
822 {
823 Oid collation = collationIds[i];
824 Oid opclass = opclassIds[i];
825
826 if (collation)
827 {
828 if ((opclass == TEXT_BTREE_PATTERN_OPS_OID ||
830 opclass == BPCHAR_BTREE_PATTERN_OPS_OID) &&
832 {
834
837 elog(ERROR, "cache lookup failed for operator class %u", opclass);
840 errmsg("nondeterministic collations are not supported for operator class \"%s\"",
843 }
844 }
845 }
846
847 /*
848 * Concurrent index build on a system catalog is unsafe because we tend to
849 * release locks before committing in catalogs.
850 */
851 if (concurrent &&
852 IsCatalogRelation(heapRelation))
855 errmsg("concurrent index creation on system catalog tables is not supported")));
856
857 /*
858 * This case is currently not supported. There's no way to ask for it in
859 * the grammar with CREATE INDEX, but it can happen with REINDEX.
860 */
861 if (concurrent && is_exclusion)
864 errmsg("concurrent index creation for exclusion constraints is not supported")));
865
866 /*
867 * We cannot allow indexing a shared relation after initdb (because
868 * there's no way to make the entry in other databases' pg_class).
869 */
873 errmsg("shared indexes cannot be created after initdb")));
874
875 /*
876 * Shared relations must be in pg_global, too (last-ditch check)
877 */
879 elog(ERROR, "shared relations must be placed in pg_global tablespace");
880
881 /*
882 * Check for duplicate name (both as to the index, and as to the
883 * associated constraint if any). Such cases would fail on the relevant
884 * catalogs' unique indexes anyway, but we prefer to give a friendlier
885 * error message.
886 */
888 {
889 if ((flags & INDEX_CREATE_IF_NOT_EXISTS) != 0)
890 {
893 errmsg("relation \"%s\" already exists, skipping",
896 return InvalidOid;
897 }
898
901 errmsg("relation \"%s\" already exists",
903 }
904
905 if ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0 &&
908 {
909 /*
910 * INDEX_CREATE_IF_NOT_EXISTS does not apply here, since the
911 * conflicting constraint is not an index.
912 */
915 errmsg("constraint \"%s\" for relation \"%s\" already exists",
917 }
918
919 /*
920 * construct tuple descriptor for index tuples
921 */
923 indexInfo,
927 opclassIds);
928
929 /*
930 * Allocate an OID for the index, unless we were told what to use.
931 *
932 * The OID will be the relfilenumber as well, so make sure it doesn't
933 * collide with either pg_class OIDs or existing physical files.
934 */
936 {
937 /* Use binary-upgrade override for pg_class.oid and relfilenumber */
938 if (IsBinaryUpgrade)
939 {
943 errmsg("pg_class index OID value not set when in binary upgrade mode")));
944
947
948 /* Override the index relfilenumber */
949 if ((relkind == RELKIND_INDEX) &&
953 errmsg("index relfilenumber value not set when in binary upgrade mode")));
956
957 /*
958 * Note that we want create_storage = true for binary upgrade. The
959 * storage we create here will be replaced later, but we need to
960 * have something on disk in the meanwhile.
961 */
963 }
964 else
965 {
967 GetNewRelFileNumber(tableSpaceId, pg_class, relpersistence);
968 }
969 }
970
971 /*
972 * create the index relation's relcache entry and, if necessary, the
973 * physical disk file. (If we fail further down, it's the smgr's
974 * responsibility to remove the disk file again, if any.)
975 */
976 indexRelation = heap_create(indexRelationName,
983 relkind,
984 relpersistence,
988 &relfrozenxid,
989 &relminmxid,
991
992 Assert(relfrozenxid == InvalidTransactionId);
993 Assert(relminmxid == InvalidMultiXactId);
994 Assert(indexRelationId == RelationGetRelid(indexRelation));
995
996 /*
997 * Obtain exclusive lock on it. Although no other transactions can see it
998 * until we commit, this prevents deadlock-risk complaints from lock
999 * manager in cases such as CLUSTER.
1000 */
1001 LockRelation(indexRelation, AccessExclusiveLock);
1002
1003 /*
1004 * Fill in fields of the index's pg_class entry that are not set correctly
1005 * by heap_create.
1006 *
1007 * XXX should have a cleaner way to create cataloged indexes
1008 */
1009 indexRelation->rd_rel->relowner = heapRelation->rd_rel->relowner;
1010 indexRelation->rd_rel->relam = accessMethodId;
1011 indexRelation->rd_rel->relispartition = OidIsValid(parentIndexRelid);
1012
1013 /*
1014 * store index's pg_class entry
1015 */
1016 InsertPgClassTuple(pg_class, indexRelation,
1017 RelationGetRelid(indexRelation),
1018 (Datum) 0,
1019 reloptions);
1020
1021 /* done with pg_class */
1023
1024 /*
1025 * now update the object id's of all the attribute tuple forms in the
1026 * index relation's tuple descriptor
1027 */
1028 InitializeAttributeOids(indexRelation,
1029 indexInfo->ii_NumIndexAttrs,
1031
1032 /*
1033 * append ATTRIBUTE tuples for the index
1034 */
1036
1037 /* ----------------
1038 * update pg_index
1039 * (append INDEX tuple)
1040 *
1041 * Note that this stows away a representation of "predicate".
1042 * (Or, could define a rule to maintain the predicate) --Nels, Feb '92
1043 * ----------------
1044 */
1046 indexInfo,
1050 !concurrent && !invalid,
1051 !concurrent);
1052
1053 /*
1054 * Register relcache invalidation on the indexes' heap relation, to
1055 * maintain consistency of its index list
1056 */
1057 CacheInvalidateRelcache(heapRelation);
1058
1059 /* update pg_inherits and the parent's relhassubclass, if needed */
1061 {
1065 }
1066
1067 /*
1068 * Register constraint and dependencies for the index.
1069 *
1070 * If the index is from a CONSTRAINT clause, construct a pg_constraint
1071 * entry. The index will be linked to the constraint, which in turn is
1072 * linked to the table. If it's not a CONSTRAINT, we need to make a
1073 * dependency directly on the table.
1074 *
1075 * We don't need a dependency on the namespace, because there'll be an
1076 * indirect dependency via our parent table.
1077 *
1078 * During bootstrap we can't register any dependencies, and we don't try
1079 * to make a constraint either.
1080 */
1082 {
1084 referenced;
1085 ObjectAddresses *addrs;
1086
1088
1089 if ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0)
1090 {
1091 char constraintType;
1093
1094 if (isprimary)
1096 else if (indexInfo->ii_Unique)
1098 else if (is_exclusion)
1100 else
1101 {
1102 elog(ERROR, "constraint must be PRIMARY, UNIQUE or EXCLUDE");
1103 constraintType = 0; /* keep compiler quiet */
1104 }
1105
1106 localaddr = index_constraint_create(heapRelation,
1109 indexInfo,
1114 is_internal);
1115 if (constraintId)
1116 *constraintId = localaddr.objectId;
1117 }
1118 else
1119 {
1120 bool have_simple_col = false;
1121
1122 addrs = new_object_addresses();
1123
1124 /* Create auto dependencies on simply-referenced columns */
1125 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
1126 {
1127 if (indexInfo->ii_IndexAttrNumbers[i] != 0)
1128 {
1131 indexInfo->ii_IndexAttrNumbers[i]);
1133 have_simple_col = true;
1134 }
1135 }
1136
1137 /*
1138 * If there are no simply-referenced columns, give the index an
1139 * auto dependency on the whole table. In most cases, this will
1140 * be redundant, but it might not be if the index expressions and
1141 * predicate contain no Vars or only whole-row Vars.
1142 */
1143 if (!have_simple_col)
1144 {
1148 }
1149
1151 free_object_addresses(addrs);
1152 }
1153
1154 /*
1155 * If this is an index partition, create partition dependencies on
1156 * both the parent index and the table. (Note: these must be *in
1157 * addition to*, not instead of, all other dependencies. Otherwise
1158 * we'll be short some dependencies after DETACH PARTITION.)
1159 */
1161 {
1164
1167 }
1168
1169 /* placeholder for normal dependencies */
1170 addrs = new_object_addresses();
1171
1172 /* Store dependency on collations */
1173
1174 /* The default collation is pinned, so don't bother recording it */
1175 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
1176 {
1178 {
1181 }
1182 }
1183
1184 /* Store dependency on operator classes */
1185 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
1186 {
1189 }
1190
1192 free_object_addresses(addrs);
1193
1194 /* Store dependencies on anything mentioned in index expressions */
1195 if (indexInfo->ii_Expressions)
1196 {
1198 (Node *) indexInfo->ii_Expressions,
1201 DEPENDENCY_AUTO, false);
1202 }
1203
1204 /* Store dependencies on anything mentioned in predicate */
1205 if (indexInfo->ii_Predicate)
1206 {
1208 (Node *) indexInfo->ii_Predicate,
1211 DEPENDENCY_AUTO, false);
1212 }
1213 }
1214 else
1215 {
1216 /* Bootstrap mode - assert we weren't asked for constraint support */
1217 Assert((flags & INDEX_CREATE_ADD_CONSTRAINT) == 0);
1218 }
1219
1220 /* Post creation hook for new index */
1222 indexRelationId, 0, is_internal);
1223
1224 /*
1225 * Advance the command counter so that we can see the newly-entered
1226 * catalog tuples for the index.
1227 */
1229
1230 /*
1231 * In bootstrap mode, we have to fill in the index strategy structure with
1232 * information from the catalogs. If we aren't bootstrapping, then the
1233 * relcache entry has already been rebuilt thanks to sinval update during
1234 * CommandCounterIncrement.
1235 */
1237 RelationInitIndexAccessInfo(indexRelation);
1238 else
1239 Assert(indexRelation->rd_indexcxt != NULL);
1240
1241 indexRelation->rd_index->indnkeyatts = indexInfo->ii_NumIndexKeyAttrs;
1242
1243 /* Validate opclass-specific options */
1244 if (opclassOptions)
1245 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
1246 (void) index_opclass_options(indexRelation, i + 1,
1248 true);
1249
1250 /*
1251 * If this is bootstrap (initdb) time, then we don't actually fill in the
1252 * index yet. We'll be creating more indexes and classes later, so we
1253 * delay filling them in until just before we're done with bootstrapping.
1254 * Similarly, if the caller specified to skip the build then filling the
1255 * index is delayed till later (ALTER TABLE can save work in some cases
1256 * with this). Otherwise, we call the AM routine that constructs the
1257 * index.
1258 */
1260 {
1262 }
1263 else if ((flags & INDEX_CREATE_SKIP_BUILD) != 0)
1264 {
1265 /*
1266 * Caller is responsible for filling the index later on. However,
1267 * we'd better make sure that the heap relation is correctly marked as
1268 * having an index.
1269 */
1270 index_update_stats(heapRelation,
1271 true,
1272 -1.0);
1273 /* Make the above update visible */
1275 }
1276 else
1277 {
1278 index_build(heapRelation, indexRelation, indexInfo, false, true);
1279 }
1280
1281 /*
1282 * Close the index; but we keep the lock that we acquired above until end
1283 * of transaction. Closing the heap is caller's responsibility.
1284 */
1285 index_close(indexRelation, NoLock);
1286
1287 return indexRelationId;
1288}
void index_register(Oid heap, Oid ind, const IndexInfo *indexInfo)
Definition bootstrap.c:1122
TransactionId MultiXactId
Definition c.h:730
uint32 TransactionId
Definition c.h:720
RelFileNumber GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
Definition catalog.c:557
bool IsCatalogRelation(Relation relation)
Definition catalog.c:104
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
ObjectAddresses * new_object_addresses(void)
void free_object_addresses(ObjectAddresses *addrs)
@ DEPENDENCY_NORMAL
Definition dependency.h:33
#define NOTICE
Definition elog.h:35
bool IsBinaryUpgrade
Definition globals.c:121
void InsertPgClassTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions)
Definition heap.c:910
Relation heap_create(const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, RelFileNumber relfilenumber, Oid accessmtd, TupleDesc tupDesc, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool allow_system_table_mods, TransactionId *relfrozenxid, MultiXactId *relminmxid, bool create_storage)
Definition heap.c:285
RelFileNumber binary_upgrade_next_index_pg_class_relfilenumber
Definition index.c:86
static void InitializeAttributeOids(Relation indexRelation, int numatts, Oid indexoid)
Definition index.c:494
Oid binary_upgrade_next_index_pg_class_oid
Definition index.c:85
static void AppendAttributeTuples(Relation indexRelation, const Datum *attopts, const NullableDatum *stattargets)
Definition index.c:512
static TupleDesc ConstructTupleDescriptor(Relation heapRelation, const IndexInfo *indexInfo, const List *indexColNames, Oid accessMethodId, const Oid *collationIds, const Oid *opclassIds)
Definition index.c:281
ObjectAddress index_constraint_create(Relation heapRelation, Oid indexRelationId, Oid parentConstraintId, const IndexInfo *indexInfo, const char *constraintName, char constraintType, bits16 constr_flags, bool allow_system_table_mods, bool is_internal)
Definition index.c:1885
static void UpdateIndexRelation(Oid indexoid, Oid heapoid, Oid parentIndexId, const IndexInfo *indexInfo, const Oid *collationOids, const Oid *opclassOids, const int16 *coloptions, bool primary, bool isexclusion, bool immediate, bool isvalid, bool isready)
Definition index.c:563
#define INDEX_CREATE_IS_PRIMARY
Definition index.h:61
#define INDEX_CREATE_IF_NOT_EXISTS
Definition index.h:65
#define INDEX_CREATE_PARTITIONED
Definition index.h:66
#define INDEX_CREATE_INVALID
Definition index.h:67
#define INDEX_CREATE_ADD_CONSTRAINT
Definition index.h:62
bytea * index_opclass_options(Relation indrel, AttrNumber attnum, Datum attoptions, bool validate)
Definition indexam.c:1048
invalidindex index d is invalid
Definition isn.c:138
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:107
void LockRelation(Relation relation, LOCKMODE lockmode)
Definition lmgr.c:246
#define AccessExclusiveLock
Definition lockdefs.h:43
bool get_collation_isdeterministic(Oid colloid)
Definition lsyscache.c:1198
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition lsyscache.c:2103
#define InvalidMultiXactId
Definition multixact.h:25
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
bool ConstraintNameIsUsed(ConstraintCategory conCat, Oid objId, const char *conname)
@ CONSTRAINT_RELATION
END_CATALOG_STRUCT typedef FormData_pg_opclass * Form_pg_opclass
Definition pg_opclass.h:87
#define RelationIsMapped(relation)
Definition rel.h:563
void RelationInitIndexAccessInfo(Relation relation)
Definition relcache.c:1434
#define RelFileNumberIsValid(relnumber)
Definition relpath.h:27
#define ERRCODE_DUPLICATE_OBJECT
Definition streamutil.c:30
List * ii_Predicate
Definition execnodes.h:185
Form_pg_index rd_index
Definition rel.h:192
MemoryContext rd_indexcxt
Definition rel.h:204
void SetRelationHasSubclass(Oid relationId, bool relhassubclass)
Definition tablecmds.c:3667
#define InvalidTransactionId
Definition transam.h:31

References AccessExclusiveLock, add_exact_object_address(), AppendAttributeTuples(), Assert, binary_upgrade_next_index_pg_class_oid, binary_upgrade_next_index_pg_class_relfilenumber, CacheInvalidateRelcache(), CommandCounterIncrement(), CONSTRAINT_RELATION, ConstraintNameIsUsed(), ConstructTupleDescriptor(), DEPENDENCY_AUTO, DEPENDENCY_NORMAL, DEPENDENCY_PARTITION_PRI, DEPENDENCY_PARTITION_SEC, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg, ERROR, fb(), Form_pg_opclass, free_object_addresses(), get_collation_isdeterministic(), get_relname_relid(), GetNewRelFileNumber(), GETSTRUCT(), heap_create(), HeapTupleIsValid, i, IndexInfo::ii_ExclusionOps, IndexInfo::ii_Expressions, IndexInfo::ii_IndexAttrNumbers, IndexInfo::ii_NumIndexAttrs, IndexInfo::ii_NumIndexKeyAttrs, IndexInfo::ii_Predicate, IndexInfo::ii_Unique, index_build(), index_close(), INDEX_CONSTR_CREATE_DEFERRABLE, index_constraint_create(), INDEX_CREATE_ADD_CONSTRAINT, INDEX_CREATE_CONCURRENT, INDEX_CREATE_IF_NOT_EXISTS, INDEX_CREATE_INVALID, INDEX_CREATE_IS_PRIMARY, INDEX_CREATE_PARTITIONED, INDEX_CREATE_SKIP_BUILD, index_opclass_options(), index_register(), index_update_stats(), InitializeAttributeOids(), InsertPgClassTuple(), invalid, InvalidMultiXactId, InvalidOid, InvalidRelFileNumber, InvalidTransactionId, InvokeObjectPostCreateHookArg, IsBinaryUpgrade, IsBootstrapProcessingMode, IsCatalogRelation(), IsNormalProcessingMode, IsSystemRelation(), LockRelation(), LockRelationOid(), NameStr, new_object_addresses(), NoLock, NOTICE, ObjectAddressSet, ObjectAddressSubSet, ObjectIdGetDatum(), OidIsValid, RelationData::rd_index, RelationData::rd_indexcxt, RelationData::rd_rel, record_object_address_dependencies(), recordDependencyOn(), recordDependencyOnSingleRelExpr(), RelationGetNamespace, RelationGetRelationName, RelationGetRelid, RelationInitIndexAccessInfo(), RelationIsMapped, ReleaseSysCache(), RelFileNumberIsValid, RowExclusiveLock, SearchSysCache1(), SetRelationHasSubclass(), ShareUpdateExclusiveLock, StoreSingleInheritance(), table_close(), table_open(), and UpdateIndexRelation().

Referenced by create_toast_table(), DefineIndex(), and index_concurrently_create_copy().

◆ index_drop()

void index_drop ( Oid  indexId,
bool  concurrent,
bool  concurrent_lock_mode 
)
extern

Definition at line 2122 of file index.c.

2123{
2124 Oid heapId;
2127 Relation indexRelation;
2128 HeapTuple tuple;
2129 bool hasexprs;
2130 LockRelId heaprelid,
2131 indexrelid;
2133 LOCKMODE lockmode;
2134
2135 /*
2136 * A temporary relation uses a non-concurrent DROP. Other backends can't
2137 * access a temporary relation, so there's no harm in grabbing a stronger
2138 * lock (see comments in RemoveRelations), and a non-concurrent DROP is
2139 * more efficient.
2140 */
2142 (!concurrent && !concurrent_lock_mode));
2143
2144 /*
2145 * To drop an index safely, we must grab exclusive lock on its parent
2146 * table. Exclusive lock on the index alone is insufficient because
2147 * another backend might be about to execute a query on the parent table.
2148 * If it relies on a previously cached list of index OIDs, then it could
2149 * attempt to access the just-dropped index. We must therefore take a
2150 * table lock strong enough to prevent all queries on the table from
2151 * proceeding until we commit and send out a shared-cache-inval notice
2152 * that will make them update their index lists.
2153 *
2154 * In the concurrent case we avoid this requirement by disabling index use
2155 * in multiple steps and waiting out any transactions that might be using
2156 * the index, so we don't need exclusive lock on the parent table. Instead
2157 * we take ShareUpdateExclusiveLock, to ensure that two sessions aren't
2158 * doing CREATE/DROP INDEX CONCURRENTLY on the same index. (We will get
2159 * AccessExclusiveLock on the index below, once we're sure nobody else is
2160 * using it.)
2161 */
2164 userHeapRelation = table_open(heapId, lockmode);
2166
2167 /*
2168 * We might still have open queries using it in our own session, which the
2169 * above locking won't prevent, so test explicitly.
2170 */
2172
2173 /*
2174 * Drop Index Concurrently is more or less the reverse process of Create
2175 * Index Concurrently.
2176 *
2177 * First we unset indisvalid so queries starting afterwards don't use the
2178 * index to answer queries anymore. We have to keep indisready = true so
2179 * transactions that are still scanning the index can continue to see
2180 * valid index contents. For instance, if they are using READ COMMITTED
2181 * mode, and another transaction makes changes and commits, they need to
2182 * see those new tuples in the index.
2183 *
2184 * After all transactions that could possibly have used the index for
2185 * queries end, we can unset indisready and indislive, then wait till
2186 * nobody could be touching it anymore. (Note: we need indislive because
2187 * this state must be distinct from the initial state during CREATE INDEX
2188 * CONCURRENTLY, which has indislive true while indisready and indisvalid
2189 * are false. That's because in that state, transactions must examine the
2190 * index for HOT-safety decisions, while in this state we don't want them
2191 * to open it at all.)
2192 *
2193 * Since all predicate locks on the index are about to be made invalid, we
2194 * must promote them to predicate locks on the heap. In the
2195 * non-concurrent case we can just do that now. In the concurrent case
2196 * it's a bit trickier. The predicate locks must be moved when there are
2197 * no index scans in progress on the index and no more can subsequently
2198 * start, so that no new predicate locks can be made on the index. Also,
2199 * they must be moved before heap inserts stop maintaining the index, else
2200 * the conflict with the predicate lock on the index gap could be missed
2201 * before the lock on the heap relation is in place to detect a conflict
2202 * based on the heap tuple insert.
2203 */
2204 if (concurrent)
2205 {
2206 /*
2207 * We must commit our transaction in order to make the first pg_index
2208 * state update visible to other sessions. If the DROP machinery has
2209 * already performed any other actions (removal of other objects,
2210 * pg_depend entries, etc), the commit would make those actions
2211 * permanent, which would leave us with inconsistent catalog state if
2212 * we fail partway through the following sequence. Since DROP INDEX
2213 * CONCURRENTLY is restricted to dropping just one index that has no
2214 * dependencies, we should get here before anything's been done ---
2215 * but let's check that to be sure. We can verify that the current
2216 * transaction has not executed any transactional updates by checking
2217 * that no XID has been assigned.
2218 */
2220 ereport(ERROR,
2222 errmsg("DROP INDEX CONCURRENTLY must be first action in transaction")));
2223
2224 /*
2225 * Mark index invalid by updating its pg_index entry
2226 */
2228
2229 /*
2230 * Invalidate the relcache for the table, so that after this commit
2231 * all sessions will refresh any cached plans that might reference the
2232 * index.
2233 */
2235
2236 /* save lockrelid and locktag for below, then close but keep locks */
2237 heaprelid = userHeapRelation->rd_lockInfo.lockRelId;
2238 SET_LOCKTAG_RELATION(heaplocktag, heaprelid.dbId, heaprelid.relId);
2239 indexrelid = userIndexRelation->rd_lockInfo.lockRelId;
2240
2243
2244 /*
2245 * We must commit our current transaction so that the indisvalid
2246 * update becomes visible to other transactions; then start another.
2247 * Note that any previously-built data structures are lost in the
2248 * commit. The only data we keep past here are the relation IDs.
2249 *
2250 * Before committing, get a session-level lock on the table, to ensure
2251 * that neither it nor the index can be dropped before we finish. This
2252 * cannot block, even if someone else is waiting for access, because
2253 * we already have the same lock within our transaction.
2254 */
2257
2261
2262 /*
2263 * Now we must wait until no running transaction could be using the
2264 * index for a query. Use AccessExclusiveLock here to check for
2265 * running transactions that hold locks of any kind on the table. Note
2266 * we do not need to worry about xacts that open the table for reading
2267 * after this point; they will see the index as invalid when they open
2268 * the relation.
2269 *
2270 * Note: the reason we use actual lock acquisition here, rather than
2271 * just checking the ProcArray and sleeping, is that deadlock is
2272 * possible if one of the transactions in question is blocked trying
2273 * to acquire an exclusive lock on our table. The lock code will
2274 * detect deadlock and error out properly.
2275 *
2276 * Note: we report progress through WaitForLockers() unconditionally
2277 * here, even though it will only be used when we're called by REINDEX
2278 * CONCURRENTLY and not when called by DROP INDEX CONCURRENTLY.
2279 */
2281
2282 /*
2283 * Updating pg_index might involve TOAST table access, so ensure we
2284 * have a valid snapshot.
2285 */
2287
2288 /* Finish invalidation of index and mark it as dead */
2290
2292
2293 /*
2294 * Again, commit the transaction to make the pg_index update visible
2295 * to other sessions.
2296 */
2299
2300 /*
2301 * Wait till every transaction that saw the old index state has
2302 * finished. See above about progress reporting.
2303 */
2305
2306 /*
2307 * Re-open relations to allow us to complete our actions.
2308 *
2309 * At this point, nothing should be accessing the index, but lets
2310 * leave nothing to chance and grab AccessExclusiveLock on the index
2311 * before the physical deletion.
2312 */
2315 }
2316 else
2317 {
2318 /* Not concurrent, so just transfer predicate locks and we're good */
2320 }
2321
2322 /*
2323 * Schedule physical removal of the files (if any)
2324 */
2325 if (RELKIND_HAS_STORAGE(userIndexRelation->rd_rel->relkind))
2327
2328 /* ensure that stats are dropped if transaction commits */
2330
2331 /*
2332 * Close and flush the index's relcache entry, to ensure relcache doesn't
2333 * try to rebuild it while we're deleting catalog entries. We keep the
2334 * lock though.
2335 */
2337
2339
2340 /*
2341 * Updating pg_index might involve TOAST table access, so ensure we have a
2342 * valid snapshot.
2343 */
2345
2346 /*
2347 * fix INDEX relation, and check for expressional index
2348 */
2350
2352 if (!HeapTupleIsValid(tuple))
2353 elog(ERROR, "cache lookup failed for index %u", indexId);
2354
2356 RelationGetDescr(indexRelation));
2357
2358 CatalogTupleDelete(indexRelation, &tuple->t_self);
2359
2360 ReleaseSysCache(tuple);
2361 table_close(indexRelation, RowExclusiveLock);
2362
2364
2365 /*
2366 * if it has any expression columns, we might have stored statistics about
2367 * them.
2368 */
2369 if (hasexprs)
2371
2372 /*
2373 * fix ATTRIBUTE relation
2374 */
2376
2377 /*
2378 * fix RELATION relation
2379 */
2381
2382 /*
2383 * fix INHERITS relation
2384 */
2386
2387 /*
2388 * We are presently too lazy to attempt to compute the new correct value
2389 * of relhasindex (the next VACUUM will fix it if necessary). So there is
2390 * no need to update the pg_class tuple for the owning relation. But we
2391 * must send out a shared-cache-inval notice on the owning relation to
2392 * ensure other backends update their relcache lists of indexes. (In the
2393 * concurrent case, this is redundant but harmless.)
2394 */
2396
2397 /*
2398 * Close owning rel, but keep lock
2399 */
2401
2402 /*
2403 * Release the session locks before we go.
2404 */
2405 if (concurrent)
2406 {
2409 }
2410}
void DeleteRelationTuple(Oid relid)
Definition heap.c:1576
void DeleteAttributeTuples(Oid relid)
Definition heap.c:1605
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition heap.c:3495
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition heaptuple.c:456
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition index.c:3583
void index_concurrently_set_dead(Oid heapId, Oid indexId)
Definition index.c:1823
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition indexing.c:365
void LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition lmgr.c:391
void WaitForLockers(LOCKTAG heaplocktag, LOCKMODE lockmode, bool progress)
Definition lmgr.c:989
void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
Definition lmgr.c:404
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition lock.h:183
int LOCKMODE
Definition lockdefs.h:26
char get_rel_persistence(Oid relid)
Definition lsyscache.c:2296
void pgstat_drop_relation(Relation rel)
void RelationForgetRelation(Oid rid)
Definition relcache.c:2881
Snapshot GetTransactionSnapshot(void)
Definition snapmgr.c:272
void PushActiveSnapshot(Snapshot snapshot)
Definition snapmgr.c:682
void PopActiveSnapshot(void)
Definition snapmgr.c:775
void RelationDropStorage(Relation rel)
Definition storage.c:207
Oid relId
Definition rel.h:40
Oid dbId
Definition rel.h:41
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition tablecmds.c:4436
TransactionId GetTopTransactionIdIfAny(void)
Definition xact.c:443
void StartTransactionCommand(void)
Definition xact.c:3081
void CommitTransactionCommand(void)
Definition xact.c:3179

References AccessExclusiveLock, Assert, CacheInvalidateRelcache(), CatalogTupleDelete(), CheckTableNotInUse(), CommitTransactionCommand(), LockRelId::dbId, DeleteAttributeTuples(), DeleteInheritsTuple(), DeleteRelationTuple(), elog, ereport, errcode(), errmsg, ERROR, fb(), get_rel_persistence(), GetTopTransactionIdIfAny(), GetTransactionSnapshot(), heap_attisnull(), HeapTupleIsValid, index_close(), index_concurrently_set_dead(), INDEX_DROP_CLEAR_VALID, index_open(), index_set_state_flags(), IndexGetRelation(), InvalidOid, InvalidTransactionId, LockRelationIdForSession(), NoLock, ObjectIdGetDatum(), pgstat_drop_relation(), PopActiveSnapshot(), PushActiveSnapshot(), RelationDropStorage(), RelationForgetRelation(), RelationGetDescr, ReleaseSysCache(), LockRelId::relId, RemoveStatistics(), RowExclusiveLock, SearchSysCache1(), SET_LOCKTAG_RELATION, ShareUpdateExclusiveLock, StartTransactionCommand(), HeapTupleData::t_self, table_close(), table_open(), TransferPredicateLocksToHeapRelation(), UnlockRelationIdForSession(), and WaitForLockers().

Referenced by doDeletion().

◆ index_set_state_flags()

void index_set_state_flags ( Oid  indexId,
IndexStateFlagsAction  action 
)
extern

Definition at line 3503 of file index.c.

3504{
3508
3509 /* Open pg_index and fetch a writable copy of the index's tuple */
3511
3515 elog(ERROR, "cache lookup failed for index %u", indexId);
3517
3518 /* Perform the requested state change on the copy */
3519 switch (action)
3520 {
3522 /* Set indisready during a CREATE INDEX CONCURRENTLY sequence */
3523 Assert(indexForm->indislive);
3524 Assert(!indexForm->indisready);
3525 Assert(!indexForm->indisvalid);
3526 indexForm->indisready = true;
3527 break;
3529 /* Set indisvalid during a CREATE INDEX CONCURRENTLY sequence */
3530 Assert(indexForm->indislive);
3531 Assert(indexForm->indisready);
3532 Assert(!indexForm->indisvalid);
3533 indexForm->indisvalid = true;
3534 break;
3536
3537 /*
3538 * Clear indisvalid during a DROP INDEX CONCURRENTLY sequence
3539 *
3540 * If indisready == true we leave it set so the index still gets
3541 * maintained by active transactions. We only need to ensure that
3542 * indisvalid is false. (We don't assert that either is initially
3543 * true, though, since we want to be able to retry a DROP INDEX
3544 * CONCURRENTLY that failed partway through.)
3545 *
3546 * Note: the CLUSTER logic assumes that indisclustered cannot be
3547 * set on any invalid index, so clear that flag too. For
3548 * cleanliness, also clear indisreplident.
3549 */
3550 indexForm->indisvalid = false;
3551 indexForm->indisclustered = false;
3552 indexForm->indisreplident = false;
3553 break;
3555
3556 /*
3557 * Clear indisready/indislive during DROP INDEX CONCURRENTLY
3558 *
3559 * We clear both indisready and indislive, because we not only
3560 * want to stop updates, we want to prevent sessions from touching
3561 * the index at all.
3562 */
3563 Assert(!indexForm->indisvalid);
3564 Assert(!indexForm->indisclustered);
3565 Assert(!indexForm->indisreplident);
3566 indexForm->indisready = false;
3567 indexForm->indislive = false;
3568 break;
3569 }
3570
3571 /* ... and update it */
3573
3575}

References Assert, CatalogTupleUpdate(), elog, ERROR, fb(), Form_pg_index, GETSTRUCT(), HeapTupleIsValid, INDEX_CREATE_SET_READY, INDEX_CREATE_SET_VALID, INDEX_DROP_CLEAR_VALID, INDEX_DROP_SET_DEAD, ObjectIdGetDatum(), RowExclusiveLock, SearchSysCacheCopy1, table_close(), and table_open().

Referenced by DefineIndex(), index_concurrently_build(), index_concurrently_set_dead(), and index_drop().

◆ IndexGetRelation()

◆ IndexSetParentIndex()

void IndexSetParentIndex ( Relation  partitionIdx,
Oid  parentOid 
)
extern

Definition at line 4470 of file indexcmds.c.

4471{
4473 ScanKeyData key[2];
4474 SysScanDesc scan;
4475 Oid partRelid = RelationGetRelid(partitionIdx);
4476 HeapTuple tuple;
4477 bool fix_dependencies;
4478
4479 /* Make sure this is an index */
4480 Assert(partitionIdx->rd_rel->relkind == RELKIND_INDEX ||
4481 partitionIdx->rd_rel->relkind == RELKIND_PARTITIONED_INDEX);
4482
4483 /*
4484 * Scan pg_inherits for rows linking our index to some parent.
4485 */
4487 ScanKeyInit(&key[0],
4491 ScanKeyInit(&key[1],
4494 Int32GetDatum(1));
4496 NULL, 2, key);
4497 tuple = systable_getnext(scan);
4498
4499 if (!HeapTupleIsValid(tuple))
4500 {
4501 if (parentOid == InvalidOid)
4502 {
4503 /*
4504 * No pg_inherits row, and no parent wanted: nothing to do in this
4505 * case.
4506 */
4507 fix_dependencies = false;
4508 }
4509 else
4510 {
4512 fix_dependencies = true;
4513 }
4514 }
4515 else
4516 {
4518
4519 if (parentOid == InvalidOid)
4520 {
4521 /*
4522 * There exists a pg_inherits row, which we want to clear; do so.
4523 */
4525 fix_dependencies = true;
4526 }
4527 else
4528 {
4529 /*
4530 * A pg_inherits row exists. If it's the same we want, then we're
4531 * good; if it differs, that amounts to a corrupt catalog and
4532 * should not happen.
4533 */
4534 if (inhForm->inhparent != parentOid)
4535 {
4536 /* unexpected: we should not get called in this case */
4537 elog(ERROR, "bogus pg_inherit row: inhrelid %u inhparent %u",
4538 inhForm->inhrelid, inhForm->inhparent);
4539 }
4540
4541 /* already in the right state */
4542 fix_dependencies = false;
4543 }
4544 }
4545
4546 /* done with pg_inherits */
4547 systable_endscan(scan);
4549
4550 /* set relhassubclass if an index partition has been added to the parent */
4551 if (OidIsValid(parentOid))
4552 {
4555 }
4556
4557 /* set relispartition correctly on the partition */
4559
4560 if (fix_dependencies)
4561 {
4562 /*
4563 * Insert/delete pg_depend rows. If setting a parent, add PARTITION
4564 * dependencies on the parent index and the table; if removing a
4565 * parent, delete PARTITION dependencies.
4566 */
4567 if (OidIsValid(parentOid))
4568 {
4570 ObjectAddress parentIdx;
4571 ObjectAddress partitionTbl;
4572
4576 partitionIdx->rd_index->indrelid);
4577 recordDependencyOn(&partIdx, &parentIdx,
4579 recordDependencyOn(&partIdx, &partitionTbl,
4581 }
4582 else
4583 {
4590 }
4591
4592 /* make our updates visible */
4594 }
4595}
static void update_relispartition(Oid relationId, bool newval)
Definition indexcmds.c:4602
static void fix_dependencies(ArchiveHandle *AH)
END_CATALOG_STRUCT typedef FormData_pg_inherits * Form_pg_inherits
Definition pg_inherits.h:49

References Assert, BTEqualStrategyNumber, CatalogTupleDelete(), CommandCounterIncrement(), deleteDependencyRecordsForClass(), DEPENDENCY_PARTITION_PRI, DEPENDENCY_PARTITION_SEC, elog, ERROR, fb(), fix_dependencies(), Form_pg_inherits, GETSTRUCT(), HeapTupleIsValid, Int32GetDatum(), InvalidOid, LockRelationOid(), ObjectAddressSet, ObjectIdGetDatum(), OidIsValid, RelationData::rd_index, RelationData::rd_rel, recordDependencyOn(), relation_close(), relation_open(), RelationGetRelid, RowExclusiveLock, ScanKeyInit(), SetRelationHasSubclass(), ShareUpdateExclusiveLock, StoreSingleInheritance(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, and update_relispartition().

Referenced by ATExecAttachPartitionIdx(), AttachPartitionEnsureIndexes(), DefineIndex(), and DetachPartitionFinalize().

◆ itemptr_decode()

static void itemptr_decode ( ItemPointer  itemptr,
int64  encoded 
)
inlinestatic

Definition at line 211 of file index.h.

212{
213 BlockNumber block = (BlockNumber) (encoded >> 16);
214 OffsetNumber offset = (OffsetNumber) (encoded & 0xFFFF);
215
216 ItemPointerSet(itemptr, block, offset);
217}
uint32 BlockNumber
Definition block.h:31
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
Definition itemptr.h:135
uint16 OffsetNumber
Definition off.h:24

References fb(), and ItemPointerSet().

Referenced by heapam_index_validate_scan().

◆ itemptr_encode()

static int64 itemptr_encode ( const ItemPointerData itemptr)
inlinestatic

Definition at line 190 of file index.h.

191{
192 BlockNumber block = ItemPointerGetBlockNumber(itemptr);
195
196 /*
197 * Use the 16 least significant bits for the offset. 32 adjacent bits are
198 * used for the block number. Since remaining bits are unused, there
199 * cannot be negative encoded values (We assume a two's complement
200 * representation).
201 */
202 encoded = ((uint64) block << 16) | (uint16) offset;
203
204 return encoded;
205}
uint64_t uint64
Definition c.h:601
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition itemptr.h:124
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition itemptr.h:103

References fb(), ItemPointerGetBlockNumber(), and ItemPointerGetOffsetNumber().

Referenced by validate_index_callback().

◆ reindex_index()

void reindex_index ( const ReindexStmt stmt,
Oid  indexId,
bool  skip_constraint_checks,
char  persistence,
const ReindexParams params 
)
extern

Definition at line 3608 of file index.c.

3611{
3612 Relation iRel,
3613 heapRelation;
3614 Oid heapId;
3615 Oid save_userid;
3616 int save_sec_context;
3617 int save_nestlevel;
3618 IndexInfo *indexInfo;
3619 volatile bool skipped_constraint = false;
3620 PGRUsage ru0;
3621 bool progress = ((params->options & REINDEXOPT_REPORT_PROGRESS) != 0);
3622 bool set_tablespace = false;
3623
3625
3626 /*
3627 * Open and lock the parent heap relation. ShareLock is sufficient since
3628 * we only need to be sure no schema or data changes are going on.
3629 */
3631 (params->options & REINDEXOPT_MISSING_OK) != 0);
3632 /* if relation is missing, leave */
3633 if (!OidIsValid(heapId))
3634 return;
3635
3636 if ((params->options & REINDEXOPT_MISSING_OK) != 0)
3637 heapRelation = try_table_open(heapId, ShareLock);
3638 else
3639 heapRelation = table_open(heapId, ShareLock);
3640
3641 /* if relation is gone, leave */
3642 if (!heapRelation)
3643 return;
3644
3645 /*
3646 * Switch to the table owner's userid, so that any index functions are run
3647 * as that user. Also lock down security-restricted operations and
3648 * arrange to make GUC variable changes local to this command.
3649 */
3650 GetUserIdAndSecContext(&save_userid, &save_sec_context);
3651 SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
3652 save_sec_context | SECURITY_RESTRICTED_OPERATION);
3653 save_nestlevel = NewGUCNestLevel();
3655
3656 if (progress)
3657 {
3658 const int progress_cols[] = {
3661 };
3662 const int64 progress_vals[] = {
3664 indexId
3665 };
3666
3668 heapId);
3670 }
3671
3672 /*
3673 * Open the target index relation and get an exclusive lock on it, to
3674 * ensure that no one else is touching this particular index.
3675 */
3676 if ((params->options & REINDEXOPT_MISSING_OK) != 0)
3678 else
3680
3681 /* if index relation is gone, leave */
3682 if (!iRel)
3683 {
3684 /* Roll back any GUC changes */
3685 AtEOXact_GUC(false, save_nestlevel);
3686
3687 /* Restore userid and security context */
3688 SetUserIdAndSecContext(save_userid, save_sec_context);
3689
3690 /* Close parent heap relation, but keep locks */
3691 table_close(heapRelation, NoLock);
3692 return;
3693 }
3694
3695 if (progress)
3697 iRel->rd_rel->relam);
3698
3699 /*
3700 * If a statement is available, telling that this comes from a REINDEX
3701 * command, collect the index for event triggers.
3702 */
3703 if (stmt)
3704 {
3705 ObjectAddress address;
3706
3710 (Node *) stmt);
3711 }
3712
3713 /*
3714 * Partitioned indexes should never get processed here, as they have no
3715 * physical storage.
3716 */
3717 if (iRel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
3718 elog(ERROR, "cannot reindex partitioned index \"%s.%s\"",
3721
3722 /*
3723 * Don't allow reindex on temp tables of other backends ... their local
3724 * buffer manager is not going to cope.
3725 */
3727 ereport(ERROR,
3729 errmsg("cannot reindex temporary tables of other sessions")));
3730
3731 /*
3732 * Don't allow reindex of an invalid index on TOAST table. This is a
3733 * leftover from a failed REINDEX CONCURRENTLY, and if rebuilt it would
3734 * not be possible to drop it anymore.
3735 */
3738 ereport(ERROR,
3740 errmsg("cannot reindex invalid index on TOAST table")));
3741
3742 /*
3743 * System relations cannot be moved even if allow_system_table_mods is
3744 * enabled to keep things consistent with the concurrent case where all
3745 * the indexes of a relation are processed in series, including indexes of
3746 * toast relations.
3747 *
3748 * Note that this check is not part of CheckRelationTableSpaceMove() as it
3749 * gets used for ALTER TABLE SET TABLESPACE that could cascade across
3750 * toast relations.
3751 */
3752 if (OidIsValid(params->tablespaceOid) &&
3754 ereport(ERROR,
3756 errmsg("cannot move system relation \"%s\"",
3758
3759 /* Check if the tablespace of this index needs to be changed */
3760 if (OidIsValid(params->tablespaceOid) &&
3762 set_tablespace = true;
3763
3764 /*
3765 * Also check for active uses of the index in the current transaction; we
3766 * don't want to reindex underneath an open indexscan.
3767 */
3768 CheckTableNotInUse(iRel, "REINDEX INDEX");
3769
3770 /* Set new tablespace, if requested */
3771 if (set_tablespace)
3772 {
3773 /* Update its pg_class row */
3775
3776 /*
3777 * Schedule unlinking of the old index storage at transaction commit.
3778 */
3781
3782 /* Make sure the reltablespace change is visible */
3784 }
3785
3786 /*
3787 * All predicate locks on the index are about to be made invalid. Promote
3788 * them to relation locks on the heap.
3789 */
3791
3792 /* Fetch info needed for index_build */
3793 indexInfo = BuildIndexInfo(iRel);
3794
3795 /* If requested, skip checking uniqueness/exclusion constraints */
3797 {
3798 if (indexInfo->ii_Unique || indexInfo->ii_ExclusionOps != NULL)
3799 skipped_constraint = true;
3800 indexInfo->ii_Unique = false;
3801 indexInfo->ii_ExclusionOps = NULL;
3802 indexInfo->ii_ExclusionProcs = NULL;
3803 indexInfo->ii_ExclusionStrats = NULL;
3804 }
3805
3806 /* Suppress use of the target index while rebuilding it */
3808
3809 /* Create a new physical relation for the index */
3810 RelationSetNewRelfilenumber(iRel, persistence);
3811
3812 /* Initialize the index and rebuild */
3813 /* Note: we do not need to re-establish pkey setting */
3814 index_build(heapRelation, iRel, indexInfo, true, true);
3815
3816 /* Re-allow use of target index */
3818
3819 /*
3820 * If the index is marked invalid/not-ready/dead (ie, it's from a failed
3821 * CREATE INDEX CONCURRENTLY, or a DROP INDEX CONCURRENTLY failed midway),
3822 * and we didn't skip a uniqueness check, we can now mark it valid. This
3823 * allows REINDEX to be used to clean up in such cases.
3824 *
3825 * We can also reset indcheckxmin, because we have now done a
3826 * non-concurrent index build, *except* in the case where index_build
3827 * found some still-broken HOT chains. If it did, and we don't have to
3828 * change any of the other flags, we just leave indcheckxmin alone (note
3829 * that index_build won't have changed it, because this is a reindex).
3830 * This is okay and desirable because not updating the tuple leaves the
3831 * index's usability horizon (recorded as the tuple's xmin value) the same
3832 * as it was.
3833 *
3834 * But, if the index was invalid/not-ready/dead and there were broken HOT
3835 * chains, we had better force indcheckxmin true, because the normal
3836 * argument that the HOT chains couldn't conflict with the index is
3837 * suspect for an invalid index. (A conflict is definitely possible if
3838 * the index was dead. It probably shouldn't happen otherwise, but let's
3839 * be conservative.) In this case advancing the usability horizon is
3840 * appropriate.
3841 *
3842 * Another reason for avoiding unnecessary updates here is that while
3843 * reindexing pg_index itself, we must not try to update tuples in it.
3844 * pg_index's indexes should always have these flags in their clean state,
3845 * so that won't happen.
3846 */
3847 if (!skipped_constraint)
3848 {
3852 bool index_bad;
3853
3855
3859 elog(ERROR, "cache lookup failed for index %u", indexId);
3861
3862 index_bad = (!indexForm->indisvalid ||
3863 !indexForm->indisready ||
3864 !indexForm->indislive);
3865 if (index_bad ||
3866 (indexForm->indcheckxmin && !indexInfo->ii_BrokenHotChain))
3867 {
3868 if (!indexInfo->ii_BrokenHotChain)
3869 indexForm->indcheckxmin = false;
3870 else if (index_bad)
3871 indexForm->indcheckxmin = true;
3872 indexForm->indisvalid = true;
3873 indexForm->indisready = true;
3874 indexForm->indislive = true;
3876
3877 /*
3878 * Invalidate the relcache for the table, so that after we commit
3879 * all sessions will refresh the table's index list. This ensures
3880 * that if anyone misses seeing the pg_index row during this
3881 * update, they'll refresh their list before attempting any update
3882 * on the table.
3883 */
3884 CacheInvalidateRelcache(heapRelation);
3885 }
3886
3888 }
3889
3890 /* Log what we did */
3891 if ((params->options & REINDEXOPT_VERBOSE) != 0)
3892 ereport(INFO,
3893 (errmsg("index \"%s\" was reindexed",
3895 errdetail_internal("%s",
3896 pg_rusage_show(&ru0))));
3897
3898 /* Roll back any GUC changes executed by index functions */
3899 AtEOXact_GUC(false, save_nestlevel);
3900
3901 /* Restore userid and security context */
3902 SetUserIdAndSecContext(save_userid, save_sec_context);
3903
3904 /* Close rels, but keep locks */
3906 table_close(heapRelation, NoLock);
3907
3908 if (progress)
3910}
void pgstat_progress_start_command(ProgressCommandType cmdtype, Oid relid)
void pgstat_progress_update_param(int index, int64 val)
void pgstat_progress_end_command(void)
@ PROGRESS_COMMAND_CREATE_INDEX
bool IsToastNamespace(Oid namespaceId)
Definition catalog.c:261
int int errdetail_internal(const char *fmt,...) pg_attribute_printf(1
#define INFO
Definition elog.h:34
void EventTriggerCollectSimpleCommand(ObjectAddress address, ObjectAddress secondaryObject, Node *parsetree)
#define stmt
static void ResetReindexProcessing(void)
Definition index.c:4170
static void SetReindexProcessing(Oid heapOid, Oid indexOid)
Definition index.c:4151
#define REINDEXOPT_MISSING_OK
Definition index.h:43
#define REINDEXOPT_REPORT_PROGRESS
Definition index.h:42
#define REINDEXOPT_VERBOSE
Definition index.h:41
Relation try_index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:152
#define ShareLock
Definition lockdefs.h:40
char * get_rel_name(Oid relid)
Definition lsyscache.c:2146
bool get_index_isvalid(Oid index_oid)
Definition lsyscache.c:3798
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3586
const ObjectAddress InvalidObjectAddress
const char * pg_rusage_show(const PGRUsage *ru0)
Definition pg_rusage.c:40
void pg_rusage_init(PGRUsage *ru0)
Definition pg_rusage.c:27
static int progress
Definition pgbench.c:262
#define PROGRESS_CREATEIDX_ACCESS_METHOD_OID
Definition progress.h:109
#define PROGRESS_CREATEIDX_COMMAND_REINDEX
Definition progress.h:138
#define PROGRESS_CREATEIDX_INDEX_OID
Definition progress.h:108
#define PROGRESS_CREATEIDX_COMMAND
Definition progress.h:107
#define RELATION_IS_OTHER_TEMP(relation)
Definition rel.h:667
void RelationSetNewRelfilenumber(Relation relation, char persistence)
Definition relcache.c:3763
void RelationAssumeNewRelfilelocator(Relation relation)
Definition relcache.c:3966
Oid tablespaceOid
Definition index.h:36
bits32 options
Definition index.h:35
Relation try_table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:60
bool CheckRelationTableSpaceMove(Relation rel, Oid newTableSpaceId)
Definition tablecmds.c:3713
void SetRelationTableSpace(Relation rel, Oid newTableSpaceId, RelFileNumber newRelFilenumber)
Definition tablecmds.c:3770

References AccessExclusiveLock, AtEOXact_GUC(), BuildIndexInfo(), CacheInvalidateRelcache(), CatalogTupleUpdate(), CheckRelationTableSpaceMove(), CheckTableNotInUse(), CommandCounterIncrement(), elog, ereport, errcode(), errdetail_internal(), errmsg, ERROR, EventTriggerCollectSimpleCommand(), fb(), Form_pg_index, get_index_isvalid(), get_namespace_name(), get_rel_name(), GETSTRUCT(), GetUserIdAndSecContext(), HeapTupleIsValid, IndexInfo::ii_BrokenHotChain, IndexInfo::ii_ExclusionOps, IndexInfo::ii_ExclusionProcs, IndexInfo::ii_ExclusionStrats, IndexInfo::ii_Unique, index_build(), index_close(), index_open(), IndexGetRelation(), INFO, InvalidObjectAddress, InvalidOid, IsSystemRelation(), IsToastNamespace(), NewGUCNestLevel(), NoLock, ObjectAddressSet, ObjectIdGetDatum(), OidIsValid, ReindexParams::options, pg_rusage_init(), pg_rusage_show(), pgstat_progress_end_command(), pgstat_progress_start_command(), pgstat_progress_update_multi_param(), pgstat_progress_update_param(), progress, PROGRESS_COMMAND_CREATE_INDEX, PROGRESS_CREATEIDX_ACCESS_METHOD_OID, PROGRESS_CREATEIDX_COMMAND, PROGRESS_CREATEIDX_COMMAND_REINDEX, PROGRESS_CREATEIDX_INDEX_OID, RelationData::rd_rel, REINDEXOPT_MISSING_OK, REINDEXOPT_REPORT_PROGRESS, REINDEXOPT_VERBOSE, RELATION_IS_OTHER_TEMP, RelationAssumeNewRelfilelocator(), RelationDropStorage(), RelationGetNamespace, RelationGetRelationName, RelationSetNewRelfilenumber(), ResetReindexProcessing(), RestrictSearchPath(), RowExclusiveLock, SearchSysCacheCopy1, SECURITY_RESTRICTED_OPERATION, SetReindexProcessing(), SetRelationTableSpace(), SetUserIdAndSecContext(), ShareLock, stmt, table_close(), table_open(), ReindexParams::tablespaceOid, TransferPredicateLocksToHeapRelation(), try_index_open(), and try_table_open().

Referenced by reindex_relation(), ReindexIndex(), and ReindexMultipleInternal().

◆ reindex_relation()

bool reindex_relation ( const ReindexStmt stmt,
Oid  relid,
int  flags,
const ReindexParams params 
)
extern

Definition at line 3948 of file index.c.

3950{
3951 Relation rel;
3953 List *indexIds;
3954 char persistence;
3955 bool result = false;
3957 int i;
3958
3959 /*
3960 * Open and lock the relation. ShareLock is sufficient since we only need
3961 * to prevent schema and data changes in it. The lock level used here
3962 * should match ReindexTable().
3963 */
3964 if ((params->options & REINDEXOPT_MISSING_OK) != 0)
3965 rel = try_table_open(relid, ShareLock);
3966 else
3967 rel = table_open(relid, ShareLock);
3968
3969 /* if relation is gone, leave */
3970 if (!rel)
3971 return false;
3972
3973 /*
3974 * Partitioned tables should never get processed here, as they have no
3975 * physical storage.
3976 */
3977 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3978 elog(ERROR, "cannot reindex partitioned table \"%s.%s\"",
3981
3982 toast_relid = rel->rd_rel->reltoastrelid;
3983
3984 /*
3985 * Get the list of index OIDs for this relation. (We trust the relcache
3986 * to get this with a sequential scan if ignoring system indexes.)
3987 */
3989
3991 {
3992 /* Suppress use of all the indexes until they are rebuilt */
3994
3995 /*
3996 * Make the new heap contents visible --- now things might be
3997 * inconsistent!
3998 */
4000 }
4001
4002 /*
4003 * Reindex the toast table, if any, before the main table.
4004 *
4005 * This helps in cases where a corruption in the toast table's index would
4006 * otherwise error and stop REINDEX TABLE command when it tries to fetch a
4007 * toasted datum. This way. the toast table's index is rebuilt and fixed
4008 * before it is used for reindexing the main table.
4009 *
4010 * It is critical to call reindex_relation() *after* the call to
4011 * RelationGetIndexList() returning the list of indexes on the relation,
4012 * because reindex_relation() will call CommandCounterIncrement() after
4013 * every reindex_index(). See REINDEX_REL_SUPPRESS_INDEX_USE for more
4014 * details.
4015 */
4017 {
4018 /*
4019 * Note that this should fail if the toast relation is missing, so
4020 * reset REINDEXOPT_MISSING_OK. Even if a new tablespace is set for
4021 * the parent relation, the indexes on its toast table are not moved.
4022 * This rule is enforced by setting tablespaceOid to InvalidOid.
4023 */
4024 ReindexParams newparams = *params;
4025
4027 newparams.tablespaceOid = InvalidOid;
4028 result |= reindex_relation(stmt, toast_relid, flags, &newparams);
4029 }
4030
4031 /*
4032 * Compute persistence of indexes: same as that of owning rel, unless
4033 * caller specified otherwise.
4034 */
4036 persistence = RELPERSISTENCE_UNLOGGED;
4037 else if (flags & REINDEX_REL_FORCE_INDEXES_PERMANENT)
4038 persistence = RELPERSISTENCE_PERMANENT;
4039 else
4040 persistence = rel->rd_rel->relpersistence;
4041
4042 /* Reindex all the indexes. */
4043 i = 1;
4044 foreach(indexId, indexIds)
4045 {
4046 Oid indexOid = lfirst_oid(indexId);
4048
4049 /*
4050 * Skip any invalid indexes on a TOAST table. These can only be
4051 * duplicate leftovers from a failed REINDEX CONCURRENTLY, and if
4052 * rebuilt it would not be possible to drop them anymore.
4053 */
4055 !get_index_isvalid(indexOid))
4056 {
4059 errmsg("cannot reindex invalid index \"%s.%s\" on TOAST table, skipping",
4061 get_rel_name(indexOid))));
4062
4063 /*
4064 * Remove this invalid toast index from the reindex pending list,
4065 * as it is skipped here due to the hard failure that would happen
4066 * in reindex_index(), should we try to process it.
4067 */
4069 RemoveReindexPending(indexOid);
4070 continue;
4071 }
4072
4073 reindex_index(stmt, indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
4074 persistence, params);
4075
4077
4078 /* Index should no longer be in the pending list */
4079 Assert(!ReindexIsProcessingIndex(indexOid));
4080
4081 /* Set index rebuild count */
4083 i);
4084 i++;
4085 }
4086
4087 /*
4088 * Close rel, but continue to hold the lock.
4089 */
4090 table_close(rel, NoLock);
4091
4092 result |= (indexIds != NIL);
4093
4094 return result;
4095}
#define WARNING
Definition elog.h:36
bool ReindexIsProcessingIndex(Oid indexOid)
Definition index.c:4140
static void RemoveReindexPending(Oid indexOid)
Definition index.c:4200
bool reindex_relation(const ReindexStmt *stmt, Oid relid, int flags, const ReindexParams *params)
Definition index.c:3948
static void SetReindexPending(List *indexes)
Definition index.c:4184
void reindex_index(const ReindexStmt *stmt, Oid indexId, bool skip_constraint_checks, char persistence, const ReindexParams *params)
Definition index.c:3608
#define REINDEX_REL_PROCESS_TOAST
Definition index.h:159
#define REINDEX_REL_FORCE_INDEXES_UNLOGGED
Definition index.h:162
#define REINDEX_REL_SUPPRESS_INDEX_USE
Definition index.h:160
#define REINDEX_REL_FORCE_INDEXES_PERMANENT
Definition index.h:163
#define REINDEX_REL_CHECK_CONSTRAINTS
Definition index.h:161
Oid get_rel_namespace(Oid relid)
Definition lsyscache.c:2170
#define PROGRESS_REPACK_INDEX_REBUILD_COUNT
Definition progress.h:92
List * RelationGetIndexList(Relation relation)
Definition relcache.c:4825

References Assert, CommandCounterIncrement(), elog, ereport, errcode(), errmsg, ERROR, fb(), get_index_isvalid(), get_namespace_name(), get_rel_name(), get_rel_namespace(), i, InvalidOid, IsToastNamespace(), lfirst_oid, NIL, NoLock, OidIsValid, ReindexParams::options, pgstat_progress_update_param(), PROGRESS_REPACK_INDEX_REBUILD_COUNT, RelationData::rd_rel, reindex_index(), REINDEX_REL_CHECK_CONSTRAINTS, REINDEX_REL_FORCE_INDEXES_PERMANENT, REINDEX_REL_FORCE_INDEXES_UNLOGGED, REINDEX_REL_PROCESS_TOAST, REINDEX_REL_SUPPRESS_INDEX_USE, reindex_relation(), ReindexIsProcessingIndex(), REINDEXOPT_MISSING_OK, RelationGetIndexList(), RelationGetNamespace, RelationGetRelationName, RemoveReindexPending(), SetReindexPending(), ShareLock, stmt, table_close(), table_open(), try_table_open(), and WARNING.

Referenced by ExecuteTruncateGuts(), finish_heap_swap(), reindex_relation(), ReindexMultipleInternal(), and ReindexTable().

◆ ReindexIsProcessingHeap()

bool ReindexIsProcessingHeap ( Oid  heapOid)
extern

Definition at line 4119 of file index.c.

4120{
4121 return heapOid == currentlyReindexedHeap;
4122}
static Oid currentlyReindexedHeap
Definition index.c:4109

References currentlyReindexedHeap.

◆ ReindexIsProcessingIndex()

bool ReindexIsProcessingIndex ( Oid  indexOid)
extern

Definition at line 4140 of file index.c.

4141{
4142 return indexOid == currentlyReindexedIndex ||
4144}
static Oid currentlyReindexedIndex
Definition index.c:4110
bool list_member_oid(const List *list, Oid datum)
Definition list.c:722

References currentlyReindexedIndex, list_member_oid(), and pendingReindexedIndexes.

Referenced by CatalogIndexInsert(), reindex_relation(), systable_beginscan(), and systable_beginscan_ordered().

◆ ResetReindexState()

void ResetReindexState ( int  nestLevel)
extern

Definition at line 4213 of file index.c.

4214{
4215 /*
4216 * Because reindexing is not re-entrant, we don't need to cope with nested
4217 * reindexing states. We just need to avoid messing up the outer-level
4218 * state in case a subtransaction fails within a REINDEX. So checking the
4219 * current nest level against that of the reindex operation is sufficient.
4220 */
4221 if (reindexingNestLevel >= nestLevel)
4222 {
4225
4226 /*
4227 * We needn't try to release the contents of pendingReindexedIndexes;
4228 * that list should be in a transaction-lifespan context, so it will
4229 * go away automatically.
4230 */
4232
4234 }
4235}
static int reindexingNestLevel
Definition index.c:4112

References currentlyReindexedHeap, currentlyReindexedIndex, InvalidOid, NIL, pendingReindexedIndexes, and reindexingNestLevel.

Referenced by AbortSubTransaction(), and AbortTransaction().

◆ RestoreReindexState()

void RestoreReindexState ( const void reindexstate)
extern

Definition at line 4271 of file index.c.

4272{
4274 int c = 0;
4275 MemoryContext oldcontext;
4276
4277 currentlyReindexedHeap = sistate->currentlyReindexedHeap;
4278 currentlyReindexedIndex = sistate->currentlyReindexedIndex;
4279
4282 for (c = 0; c < sistate->numPendingReindexedIndexes; ++c)
4285 sistate->pendingReindexedIndexes[c]);
4286 MemoryContextSwitchTo(oldcontext);
4287
4288 /* Note the worker has its own transaction nesting level */
4290}
MemoryContext TopMemoryContext
Definition mcxt.c:166
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
char * c
int GetCurrentTransactionNestLevel(void)
Definition xact.c:931

References Assert, currentlyReindexedHeap, currentlyReindexedIndex, fb(), GetCurrentTransactionNestLevel(), lappend_oid(), MemoryContextSwitchTo(), NIL, pendingReindexedIndexes, reindexingNestLevel, and TopMemoryContext.

Referenced by ParallelWorkerMain().

◆ SerializeReindexState()

void SerializeReindexState ( Size  maxsize,
char start_address 
)
extern

Definition at line 4253 of file index.c.

4254{
4256 int c = 0;
4257 ListCell *lc;
4258
4259 sistate->currentlyReindexedHeap = currentlyReindexedHeap;
4260 sistate->currentlyReindexedIndex = currentlyReindexedIndex;
4261 sistate->numPendingReindexedIndexes = list_length(pendingReindexedIndexes);
4262 foreach(lc, pendingReindexedIndexes)
4263 sistate->pendingReindexedIndexes[c++] = lfirst_oid(lc);
4264}

References currentlyReindexedHeap, currentlyReindexedIndex, fb(), lfirst_oid, list_length(), and pendingReindexedIndexes.

Referenced by InitializeParallelDSM().

◆ validate_index()

void validate_index ( Oid  heapId,
Oid  indexId,
Snapshot  snapshot 
)
extern

Definition at line 3350 of file index.c.

3351{
3352 Relation heapRelation,
3353 indexRelation;
3354 IndexInfo *indexInfo;
3357 Oid save_userid;
3358 int save_sec_context;
3359 int save_nestlevel;
3360
3361 {
3362 const int progress_index[] = {
3368 };
3369 const int64 progress_vals[] = {
3371 0, 0, 0, 0
3372 };
3373
3375 }
3376
3377 /* Open and lock the parent heap relation */
3379
3380 /*
3381 * Switch to the table owner's userid, so that any index functions are run
3382 * as that user. Also lock down security-restricted operations and
3383 * arrange to make GUC variable changes local to this command.
3384 */
3385 GetUserIdAndSecContext(&save_userid, &save_sec_context);
3386 SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
3387 save_sec_context | SECURITY_RESTRICTED_OPERATION);
3388 save_nestlevel = NewGUCNestLevel();
3390
3391 indexRelation = index_open(indexId, RowExclusiveLock);
3392
3393 /*
3394 * Fetch info needed for index_insert. (You might think this should be
3395 * passed in from DefineIndex, but its copy is long gone due to having
3396 * been built in a previous transaction.)
3397 */
3398 indexInfo = BuildIndexInfo(indexRelation);
3399
3400 /* mark build is concurrent just for consistency */
3401 indexInfo->ii_Concurrent = true;
3402
3403 /*
3404 * Scan the index and gather up all the TIDs into a tuplesort object.
3405 */
3406 ivinfo.index = indexRelation;
3407 ivinfo.heaprel = heapRelation;
3408 ivinfo.analyze_only = false;
3409 ivinfo.report_progress = true;
3410 ivinfo.estimated_count = true;
3411 ivinfo.message_level = DEBUG2;
3412 ivinfo.num_heap_tuples = heapRelation->rd_rel->reltuples;
3413 ivinfo.strategy = NULL;
3414
3415 /*
3416 * Encode TIDs as int8 values for the sort, rather than directly sorting
3417 * item pointers. This can be significantly faster, primarily because TID
3418 * is a pass-by-reference type on all platforms, whereas int8 is
3419 * pass-by-value on most platforms.
3420 */
3422 InvalidOid, false,
3425 state.htups = state.itups = state.tups_inserted = 0;
3426
3427 /* ambulkdelete updates progress metrics */
3430
3431 /* Execute the sort */
3432 {
3433 const int progress_index[] = {
3437 };
3438 const int64 progress_vals[] = {
3440 0, 0
3441 };
3442
3444 }
3445 tuplesort_performsort(state.tuplesort);
3446
3447 /*
3448 * Now scan the heap and "merge" it with the index
3449 */
3452 table_index_validate_scan(heapRelation,
3453 indexRelation,
3454 indexInfo,
3455 snapshot,
3456 &state);
3457
3458 /* Done with tuplesort object */
3459 tuplesort_end(state.tuplesort);
3460
3461 /* Make sure to release resources cached in indexInfo (if needed). */
3462 index_insert_cleanup(indexRelation, indexInfo);
3463
3464 elog(DEBUG2,
3465 "validate_index found %.0f heap tuples, %.0f index tuples; inserted %.0f missing tuples",
3466 state.htups, state.itups, state.tups_inserted);
3467
3468 /* Roll back any GUC changes executed by index functions */
3469 AtEOXact_GUC(false, save_nestlevel);
3470
3471 /* Restore userid and security context */
3472 SetUserIdAndSecContext(save_userid, save_sec_context);
3473
3474 /* Close rels, but keep locks */
3475 index_close(indexRelation, NoLock);
3476 table_close(heapRelation, NoLock);
3477}
#define DEBUG2
Definition elog.h:29
int maintenance_work_mem
Definition globals.c:133
static bool validate_index_callback(ItemPointer itemptr, void *opaque)
Definition index.c:3483
IndexBulkDeleteResult * index_bulk_delete(IndexVacuumInfo *info, IndexBulkDeleteResult *istat, IndexBulkDeleteCallback callback, void *callback_state)
Definition indexam.c:805
void index_insert_cleanup(Relation indexRelation, IndexInfo *indexInfo)
Definition indexam.c:241
#define PROGRESS_CREATEIDX_PHASE_VALIDATE_TABLESCAN
Definition progress.h:124
#define PROGRESS_CREATEIDX_PHASE_VALIDATE_SORT
Definition progress.h:123
#define PROGRESS_CREATEIDX_PHASE_VALIDATE_IDXSCAN
Definition progress.h:122
static void table_index_validate_scan(Relation table_rel, Relation index_rel, IndexInfo *index_info, Snapshot snapshot, ValidateIndexState *state)
Definition tableam.h:1829
void tuplesort_performsort(Tuplesortstate *state)
Definition tuplesort.c:1259
void tuplesort_end(Tuplesortstate *state)
Definition tuplesort.c:847
#define TUPLESORT_NONE
Definition tuplesort.h:67
Tuplesortstate * tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, int workMem, SortCoordinate coordinate, int sortopt)

References AtEOXact_GUC(), BuildIndexInfo(), DEBUG2, elog, fb(), GetUserIdAndSecContext(), IndexInfo::ii_Concurrent, index_bulk_delete(), index_close(), index_insert_cleanup(), index_open(), InvalidOid, maintenance_work_mem, NewGUCNestLevel(), NoLock, pgstat_progress_update_multi_param(), pgstat_progress_update_param(), PROGRESS_CREATEIDX_PHASE, PROGRESS_CREATEIDX_PHASE_VALIDATE_IDXSCAN, PROGRESS_CREATEIDX_PHASE_VALIDATE_SORT, PROGRESS_CREATEIDX_PHASE_VALIDATE_TABLESCAN, PROGRESS_CREATEIDX_TUPLES_DONE, PROGRESS_CREATEIDX_TUPLES_TOTAL, PROGRESS_SCAN_BLOCKS_DONE, PROGRESS_SCAN_BLOCKS_TOTAL, RelationData::rd_rel, RestrictSearchPath(), RowExclusiveLock, SECURITY_RESTRICTED_OPERATION, SetUserIdAndSecContext(), ShareUpdateExclusiveLock, table_close(), table_index_validate_scan(), table_open(), tuplesort_begin_datum(), tuplesort_end(), TUPLESORT_NONE, tuplesort_performsort(), and validate_index_callback().

Referenced by DefineIndex(), and ReindexRelationConcurrently().