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 AttrMap AttrMap
 
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 27 of file index.h.

◆ INDEX_CONSTR_CREATE_DEFERRABLE

#define INDEX_CONSTR_CREATE_DEFERRABLE   (1 << 1)

Definition at line 98 of file index.h.

◆ INDEX_CONSTR_CREATE_INIT_DEFERRED

#define INDEX_CONSTR_CREATE_INIT_DEFERRED   (1 << 2)

Definition at line 99 of file index.h.

◆ INDEX_CONSTR_CREATE_MARK_AS_PRIMARY

#define INDEX_CONSTR_CREATE_MARK_AS_PRIMARY   (1 << 0)

Definition at line 97 of file index.h.

◆ INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS

#define INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS   (1 << 4)

Definition at line 101 of file index.h.

◆ INDEX_CONSTR_CREATE_UPDATE_INDEX

#define INDEX_CONSTR_CREATE_UPDATE_INDEX   (1 << 3)

Definition at line 100 of file index.h.

◆ INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS

#define INDEX_CONSTR_CREATE_WITHOUT_OVERLAPS   (1 << 5)

Definition at line 102 of file index.h.

◆ INDEX_CREATE_ADD_CONSTRAINT

#define INDEX_CREATE_ADD_CONSTRAINT   (1 << 1)

Definition at line 68 of file index.h.

◆ INDEX_CREATE_CONCURRENT

#define INDEX_CREATE_CONCURRENT   (1 << 3)

Definition at line 70 of file index.h.

◆ INDEX_CREATE_IF_NOT_EXISTS

#define INDEX_CREATE_IF_NOT_EXISTS   (1 << 4)

Definition at line 71 of file index.h.

◆ INDEX_CREATE_INVALID

#define INDEX_CREATE_INVALID   (1 << 6)

Definition at line 73 of file index.h.

◆ INDEX_CREATE_IS_PRIMARY

#define INDEX_CREATE_IS_PRIMARY   (1 << 0)

Definition at line 67 of file index.h.

◆ INDEX_CREATE_PARTITIONED

#define INDEX_CREATE_PARTITIONED   (1 << 5)

Definition at line 72 of file index.h.

◆ INDEX_CREATE_SKIP_BUILD

#define INDEX_CREATE_SKIP_BUILD   (1 << 2)

Definition at line 69 of file index.h.

◆ REINDEX_REL_CHECK_CONSTRAINTS

#define REINDEX_REL_CHECK_CONSTRAINTS   0x04

Definition at line 167 of file index.h.

◆ REINDEX_REL_FORCE_INDEXES_PERMANENT

#define REINDEX_REL_FORCE_INDEXES_PERMANENT   0x10

Definition at line 169 of file index.h.

◆ REINDEX_REL_FORCE_INDEXES_UNLOGGED

#define REINDEX_REL_FORCE_INDEXES_UNLOGGED   0x08

Definition at line 168 of file index.h.

◆ REINDEX_REL_PROCESS_TOAST

#define REINDEX_REL_PROCESS_TOAST   0x01

Definition at line 165 of file index.h.

◆ REINDEX_REL_SUPPRESS_INDEX_USE

#define REINDEX_REL_SUPPRESS_INDEX_USE   0x02

Definition at line 166 of file index.h.

◆ REINDEXOPT_CONCURRENTLY

#define REINDEXOPT_CONCURRENTLY   0x08 /* concurrent mode */

Definition at line 50 of file index.h.

◆ REINDEXOPT_MISSING_OK

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

Definition at line 49 of file index.h.

◆ REINDEXOPT_REPORT_PROGRESS

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

Definition at line 48 of file index.h.

◆ REINDEXOPT_VERBOSE

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

Definition at line 47 of file index.h.

Typedef Documentation

◆ AttrMap

Definition at line 24 of file index.h.

◆ 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 30 of file index.h.

31{
IndexStateFlagsAction
Definition index.h:31
@ INDEX_CREATE_SET_VALID
Definition index.h:33
@ INDEX_DROP_CLEAR_VALID
Definition index.h:34
@ INDEX_DROP_SET_DEAD
Definition index.h:35
@ INDEX_CREATE_SET_READY
Definition index.h:32

Function Documentation

◆ BuildDummyIndexInfo()

IndexInfo * BuildDummyIndexInfo ( Relation  index)
extern

Definition at line 2489 of file index.c.

2490{
2491 IndexInfo *ii;
2492 Form_pg_index indexStruct = index->rd_index;
2493 int i;
2494 int numAtts;
2495
2496 /* check the number of keys, and copy attr numbers into the IndexInfo */
2497 numAtts = indexStruct->indnatts;
2499 elog(ERROR, "invalid indnatts %d for index %u",
2501
2502 /*
2503 * Create the node, using dummy index expressions, and pretending there is
2504 * no predicate.
2505 */
2506 ii = makeIndexInfo(indexStruct->indnatts,
2507 indexStruct->indnkeyatts,
2508 index->rd_rel->relam,
2510 NIL,
2511 indexStruct->indisunique,
2512 indexStruct->indnullsnotdistinct,
2513 indexStruct->indisready,
2514 false,
2515 index->rd_indam->amsummarizing,
2516 indexStruct->indisexclusion && indexStruct->indisunique);
2517
2518 /* fill in attribute numbers */
2519 for (i = 0; i < numAtts; i++)
2520 ii->ii_IndexAttrNumbers[i] = indexStruct->indkey.values[i];
2521
2522 /* We ignore the exclusion constraint if any */
2523
2524 return ii;
2525}
#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:5146
AttrNumber ii_IndexAttrNumbers[INDEX_MAX_KEYS]
Definition execnodes.h:186
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 2429 of file index.c.

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

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 2670 of file index.c.

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

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 2538 of file index.c.

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

4244{
4247}
static List * pendingReindexedIndexes
Definition index.c:4112
static int list_length(const List *l)
Definition pg_list.h:152
Size mul_size(Size s1, Size s2)
Definition shmem.c:500

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 2731 of file index.c.

2736{
2738 int i;
2739
2740 if (indexInfo->ii_Expressions != NIL &&
2741 indexInfo->ii_ExpressionsState == NIL)
2742 {
2743 /* First time through, set up expression evaluation state */
2744 indexInfo->ii_ExpressionsState =
2745 ExecPrepareExprList(indexInfo->ii_Expressions, estate);
2746 /* Check caller has set up context correctly */
2747 Assert(GetPerTupleExprContext(estate)->ecxt_scantuple == slot);
2748 }
2750
2751 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
2752 {
2753 int keycol = indexInfo->ii_IndexAttrNumbers[i];
2754 Datum iDatum;
2755 bool isNull;
2756
2757 if (keycol < 0)
2758 iDatum = slot_getsysattr(slot, keycol, &isNull);
2759 else if (keycol != 0)
2760 {
2761 /*
2762 * Plain index column; get the value we need directly from the
2763 * heap tuple.
2764 */
2765 iDatum = slot_getattr(slot, keycol, &isNull);
2766 }
2767 else
2768 {
2769 /*
2770 * Index expression --- need to evaluate it.
2771 */
2772 if (indexpr_item == NULL)
2773 elog(ERROR, "wrong number of index expressions");
2775 GetPerTupleExprContext(estate),
2776 &isNull);
2778 }
2779 values[i] = iDatum;
2780 isnull[i] = isNull;
2781 }
2782
2783 if (indexpr_item != NULL)
2784 elog(ERROR, "wrong number of index expressions");
2785}
static Datum values[MAXATTR]
Definition bootstrap.c:188
List * ExecPrepareExprList(List *nodes, EState *estate)
Definition execExpr.c:872
#define GetPerTupleExprContext(estate)
Definition executor.h:660
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:439
#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:178
List * ii_ExpressionsState
Definition execnodes.h:191
List * ii_Expressions
Definition execnodes.h:189
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 3003 of file index.c.

3008{
3009 IndexBuildResult *stats;
3010 Oid save_userid;
3011 int save_sec_context;
3012 int save_nestlevel;
3013
3014 /*
3015 * sanity checks
3016 */
3017 Assert(RelationIsValid(indexRelation));
3018 Assert(indexRelation->rd_indam);
3019 Assert(indexRelation->rd_indam->ambuild);
3020 Assert(indexRelation->rd_indam->ambuildempty);
3021
3022 /*
3023 * Determine worker process details for parallel CREATE INDEX. Currently,
3024 * only btree, GIN, and BRIN have support for parallel builds.
3025 *
3026 * Note that planner considers parallel safety for us.
3027 */
3029 indexRelation->rd_indam->amcanbuildparallel)
3030 indexInfo->ii_ParallelWorkers =
3032 RelationGetRelid(indexRelation));
3033
3034 if (indexInfo->ii_ParallelWorkers == 0)
3036 (errmsg_internal("building index \"%s\" on table \"%s\" serially",
3037 RelationGetRelationName(indexRelation),
3038 RelationGetRelationName(heapRelation))));
3039 else
3041 (errmsg_internal("building index \"%s\" on table \"%s\" with request for %d parallel workers",
3042 RelationGetRelationName(indexRelation),
3043 RelationGetRelationName(heapRelation),
3044 indexInfo->ii_ParallelWorkers)));
3045
3046 /*
3047 * Switch to the table owner's userid, so that any index functions are run
3048 * as that user. Also lock down security-restricted operations and
3049 * arrange to make GUC variable changes local to this command.
3050 */
3051 GetUserIdAndSecContext(&save_userid, &save_sec_context);
3052 SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
3053 save_sec_context | SECURITY_RESTRICTED_OPERATION);
3054 save_nestlevel = NewGUCNestLevel();
3056
3057 /* Set up initial progress report status */
3058 {
3059 const int progress_index[] = {
3066 };
3067 const int64 progress_vals[] = {
3070 0, 0, 0, 0
3071 };
3072
3074 }
3075
3076 /*
3077 * Call the access method's build procedure
3078 */
3079 stats = indexRelation->rd_indam->ambuild(heapRelation, indexRelation,
3080 indexInfo);
3081 Assert(stats);
3082
3083 /*
3084 * If this is an unlogged index, we may need to write out an init fork for
3085 * it -- but we must first check whether one already exists. If, for
3086 * example, an unlogged relation is truncated in the transaction that
3087 * created it, or truncated twice in a subsequent transaction, the
3088 * relfilenumber won't change, and nothing needs to be done here.
3089 */
3090 if (indexRelation->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED &&
3091 !smgrexists(RelationGetSmgr(indexRelation), INIT_FORKNUM))
3092 {
3093 smgrcreate(RelationGetSmgr(indexRelation), INIT_FORKNUM, false);
3094 log_smgrcreate(&indexRelation->rd_locator, INIT_FORKNUM);
3095 indexRelation->rd_indam->ambuildempty(indexRelation);
3096 }
3097
3098 /*
3099 * If we found any potentially broken HOT chains, mark the index as not
3100 * being usable until the current transaction is below the event horizon.
3101 * See src/backend/access/heap/README.HOT for discussion. While it might
3102 * become safe to use the index earlier based on actual cleanup activity
3103 * and other active transactions, the test for that would be much more
3104 * complex and would require some form of blocking, so keep it simple and
3105 * fast by just using the current transaction.
3106 *
3107 * However, when reindexing an existing index, we should do nothing here.
3108 * Any HOT chains that are broken with respect to the index must predate
3109 * the index's original creation, so there is no need to change the
3110 * index's usability horizon. Moreover, we *must not* try to change the
3111 * index's pg_index entry while reindexing pg_index itself, and this
3112 * optimization nicely prevents that. The more complex rules needed for a
3113 * reindex are handled separately after this function returns.
3114 *
3115 * We also need not set indcheckxmin during a concurrent index build,
3116 * because we won't set indisvalid true until all transactions that care
3117 * about the broken HOT chains are gone.
3118 *
3119 * Therefore, this code path can only be taken during non-concurrent
3120 * CREATE INDEX. Thus the fact that heap_update will set the pg_index
3121 * tuple's xmin doesn't matter, because that tuple was created in the
3122 * current transaction anyway. That also means we don't need to worry
3123 * about any concurrent readers of the tuple; no other transaction can see
3124 * it yet.
3125 */
3126 if (indexInfo->ii_BrokenHotChain &&
3127 !isreindex &&
3128 !indexInfo->ii_Concurrent)
3129 {
3130 Oid indexId = RelationGetRelid(indexRelation);
3134
3136
3140 elog(ERROR, "cache lookup failed for index %u", indexId);
3142
3143 /* If it's a new index, indcheckxmin shouldn't be set ... */
3144 Assert(!indexForm->indcheckxmin);
3145
3146 indexForm->indcheckxmin = true;
3148
3151 }
3152
3153 /*
3154 * Update heap and index pg_class rows
3155 */
3156 index_update_stats(heapRelation,
3157 true,
3158 stats->heap_tuples);
3159
3160 index_update_stats(indexRelation,
3161 false,
3162 stats->index_tuples);
3163
3164 /* Make the updated catalog row versions visible */
3166
3167 /*
3168 * If it's for an exclusion constraint, make a second pass over the heap
3169 * to verify that the constraint is satisfied. We must not do this until
3170 * the index is fully valid. (Broken HOT chains shouldn't matter, though;
3171 * see comments for IndexCheckExclusion.)
3172 */
3173 if (indexInfo->ii_ExclusionOps != NULL)
3174 IndexCheckExclusion(heapRelation, indexRelation, indexInfo);
3175
3176 /* Roll back any GUC changes executed by index functions */
3177 AtEOXact_GUC(false, save_nestlevel);
3178
3179 /* Restore userid and security context */
3180 SetUserIdAndSecContext(save_userid, save_sec_context);
3181}
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
int64_t int64
Definition c.h:612
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:1384
#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:2810
static void IndexCheckExclusion(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo)
Definition index.c:3196
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:40
double index_tuples
Definition genam.h:41
bool ii_BrokenHotChain
Definition execnodes.h:223
int ii_ParallelWorkers
Definition execnodes.h:229
bool ii_Concurrent
Definition execnodes.h:221
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 203 of file index.c.

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

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

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 1301 of file index.c.

1303{
1304 Relation indexRelation;
1306 *newInfo;
1309 classTuple;
1317 bool isnull;
1319 List *indexExprs = NIL;
1320 List *indexPreds = NIL;
1321
1322 indexRelation = index_open(oldIndexId, RowExclusiveLock);
1323
1324 /* The new index needs some information from the old index */
1325 oldInfo = BuildIndexInfo(indexRelation);
1326
1327 /*
1328 * Concurrent build of an index with exclusion constraints is not
1329 * supported.
1330 */
1331 if (oldInfo->ii_ExclusionOps != NULL)
1332 ereport(ERROR,
1334 errmsg("concurrent index creation for exclusion constraints is not supported")));
1335
1336 /* Get the array of class and column options IDs from index info */
1339 elog(ERROR, "cache lookup failed for index %u", oldIndexId);
1343
1347
1348 /* Fetch reloptions of index if any */
1351 elog(ERROR, "cache lookup failed for relation %u", oldIndexId);
1353 Anum_pg_class_reloptions, &isnull);
1354
1355 /*
1356 * Fetch the list of expressions and predicates directly from the
1357 * catalogs. This cannot rely on the information from IndexInfo of the
1358 * old index as these have been flattened for the planner.
1359 */
1360 if (oldInfo->ii_Expressions != NIL)
1361 {
1363 char *exprString;
1364
1370 }
1371 if (oldInfo->ii_Predicate != NIL)
1372 {
1374 char *predString;
1375
1380
1381 /* Also convert to implicit-AND format */
1384 }
1385
1386 /*
1387 * Build the index information for the new index. Note that rebuild of
1388 * indexes with exclusion constraints is not supported, hence there is no
1389 * need to fill all the ii_Exclusion* fields.
1390 */
1391 newInfo = makeIndexInfo(oldInfo->ii_NumIndexAttrs,
1392 oldInfo->ii_NumIndexKeyAttrs,
1393 oldInfo->ii_Am,
1394 indexExprs,
1395 indexPreds,
1396 oldInfo->ii_Unique,
1397 oldInfo->ii_NullsNotDistinct,
1398 false, /* not ready for inserts */
1399 true,
1400 indexRelation->rd_indam->amsummarizing,
1401 oldInfo->ii_WithoutOverlaps);
1402
1403 /*
1404 * Extract the list of column names and the column numbers for the new
1405 * index information. All this information will be used for the index
1406 * creation.
1407 */
1408 for (int i = 0; i < oldInfo->ii_NumIndexAttrs; i++)
1409 {
1410 TupleDesc indexTupDesc = RelationGetDescr(indexRelation);
1412
1414 newInfo->ii_IndexAttrNumbers[i] = oldInfo->ii_IndexAttrNumbers[i];
1415 }
1416
1417 /* Extract opclass options for each attribute */
1418 opclassOptions = palloc0_array(Datum, newInfo->ii_NumIndexAttrs);
1419 for (int i = 0; i < newInfo->ii_NumIndexAttrs; i++)
1421
1422 /* Extract statistic targets for each attribute */
1423 stattargets = palloc0_array(NullableDatum, newInfo->ii_NumIndexAttrs);
1424 for (int i = 0; i < newInfo->ii_NumIndexAttrs; i++)
1425 {
1426 HeapTuple tp;
1427 Datum dat;
1428
1430 if (!HeapTupleIsValid(tp))
1431 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1432 i + 1, oldIndexId);
1434 ReleaseSysCache(tp);
1435 stattargets[i].value = dat;
1436 stattargets[i].isnull = isnull;
1437 }
1438
1439 /*
1440 * Now create the new index.
1441 *
1442 * For a partition index, we adjust the partition dependency later, to
1443 * ensure a consistent state at all times. That is why parentIndexRelid
1444 * is not set here.
1445 */
1446 newIndexId = index_create(heapRelation,
1447 newName,
1448 InvalidOid, /* indexRelationId */
1449 InvalidOid, /* parentIndexRelid */
1450 InvalidOid, /* parentConstraintId */
1451 InvalidRelFileNumber, /* relFileNumber */
1452 newInfo,
1454 indexRelation->rd_rel->relam,
1455 tablespaceOid,
1456 indexRelation->rd_indcollation,
1457 indclass->values,
1459 indcoloptions->values,
1463 0,
1464 true, /* allow table to be a system catalog? */
1465 false, /* is_internal? */
1466 NULL);
1467
1468 /* Close the relations used and clean up */
1469 index_close(indexRelation, NoLock);
1472
1473 return newIndexId;
1474}
#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:727
#define INDEX_CREATE_SKIP_BUILD
Definition index.h:69
#define INDEX_CREATE_CONCURRENT
Definition index.h:70
List * lappend(List *list, void *datum)
Definition list.c:339
Datum get_attoptions(Oid relid, int16 attnum)
Definition lsyscache.c:1089
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:814
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 1824 of file index.c.

1825{
1828
1829 /*
1830 * No more predicate locks will be acquired on this index, and we're about
1831 * to stop doing inserts into the index which could show conflicts with
1832 * existing predicate locks, so now is the time to move them to the heap
1833 * relation.
1834 */
1838
1839 /*
1840 * Now we are sure that nobody uses the index for queries; they just might
1841 * have it open for updating it. So now we can unset indisready and
1842 * indislive, then wait till nobody could be using it at all anymore.
1843 */
1845
1846 /*
1847 * Invalidate the relcache for the table, so that after this commit all
1848 * sessions will refresh the table's index list. Forgetting just the
1849 * index's relcache entry is not enough.
1850 */
1852
1853 /*
1854 * Close the relations again, though still holding session lock.
1855 */
1858}
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 1553 of file index.c.

1554{
1556 pg_index,
1558 pg_trigger;
1569 bool isPartition;
1572 ListCell *lc;
1573
1574 /*
1575 * Take a necessary lock on the old and new index before swapping them.
1576 */
1579
1580 /* Now swap names and dependencies of those indexes */
1582
1586 elog(ERROR, "could not find tuple for relation %u", oldIndexId);
1590 elog(ERROR, "could not find tuple for relation %u", newIndexId);
1591
1594
1595 /* Swap the names */
1596 namestrcpy(&newClassForm->relname, NameStr(oldClassForm->relname));
1597 namestrcpy(&oldClassForm->relname, oldName);
1598
1599 /* Swap the partition flags to track inheritance properly */
1600 isPartition = newClassForm->relispartition;
1601 newClassForm->relispartition = oldClassForm->relispartition;
1602 oldClassForm->relispartition = isPartition;
1603
1606
1609
1610 /* Now swap index info */
1612
1616 elog(ERROR, "could not find tuple for relation %u", oldIndexId);
1620 elog(ERROR, "could not find tuple for relation %u", newIndexId);
1621
1624
1625 /*
1626 * Copy constraint flags from the old index. This is safe because the old
1627 * index guaranteed uniqueness.
1628 */
1629 newIndexForm->indisprimary = oldIndexForm->indisprimary;
1630 oldIndexForm->indisprimary = false;
1631 newIndexForm->indisexclusion = oldIndexForm->indisexclusion;
1632 oldIndexForm->indisexclusion = false;
1633 newIndexForm->indimmediate = oldIndexForm->indimmediate;
1634 oldIndexForm->indimmediate = true;
1635
1636 /* Preserve indisreplident in the new index */
1637 newIndexForm->indisreplident = oldIndexForm->indisreplident;
1638
1639 /* Preserve indisclustered in the new index */
1640 newIndexForm->indisclustered = oldIndexForm->indisclustered;
1641
1642 /*
1643 * Mark the new index as valid, and the old index as invalid similarly to
1644 * what index_set_state_flags() does.
1645 */
1646 newIndexForm->indisvalid = true;
1647 oldIndexForm->indisvalid = false;
1648 oldIndexForm->indisclustered = false;
1649 oldIndexForm->indisreplident = false;
1650
1653
1656
1657 /*
1658 * Move constraints and triggers over to the new index
1659 */
1660
1662
1664
1667
1670
1671 foreach(lc, constraintOids)
1672 {
1676 ScanKeyData key[1];
1677 SysScanDesc scan;
1679
1680 /* Move the constraint from the old to the new index */
1684 elog(ERROR, "could not find tuple for constraint %u", constraintOid);
1685
1687
1688 if (conForm->conindid == oldIndexId)
1689 {
1690 conForm->conindid = newIndexId;
1691
1693 }
1694
1696
1697 /* Search for trigger records */
1698 ScanKeyInit(&key[0],
1702
1704 NULL, 1, key);
1705
1707 {
1709
1710 if (tgForm->tgconstrindid != oldIndexId)
1711 continue;
1712
1713 /* Make a modifiable copy */
1716
1717 tgForm->tgconstrindid = newIndexId;
1718
1720
1722 }
1723
1724 systable_endscan(scan);
1725 }
1726
1727 /*
1728 * Move comment if any
1729 */
1730 {
1732 ScanKeyData skey[3];
1734 HeapTuple tuple;
1736 bool nulls[Natts_pg_description] = {0};
1737 bool replaces[Natts_pg_description] = {0};
1738
1741
1742 ScanKeyInit(&skey[0],
1746 ScanKeyInit(&skey[1],
1750 ScanKeyInit(&skey[2],
1753 Int32GetDatum(0));
1754
1756
1758 NULL, 3, skey);
1759
1760 while ((tuple = systable_getnext(sd)) != NULL)
1761 {
1763 values, nulls, replaces);
1764 CatalogTupleUpdate(description, &tuple->t_self, tuple);
1765
1766 break; /* Assume there can be only one match */
1767 }
1768
1771 }
1772
1773 /*
1774 * Swap inheritance relationship with parent index
1775 */
1777 {
1779 Oid parentIndexRelid = linitial_oid(ancestors);
1780
1783
1784 list_free(ancestors);
1785 }
1786
1787 /*
1788 * Swap all dependencies of and on the old index to the new one, and
1789 * vice-versa. Note that a call to CommandCounterIncrement() would cause
1790 * duplicate entries in pg_depend, so this should not be done.
1791 */
1794
1797
1798 /* copy over statistics from old to new index */
1800
1801 /* Copy data of pg_statistic from the old index to the new one */
1803
1804 /* Close relations */
1809
1810 /* The lock taken previously is not released until the end of transaction */
1813}
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:1130
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:698
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:2247
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 1886 of file index.c.

1895{
1896 Oid namespaceId = RelationGetNamespace(heapRelation);
1898 idxaddr;
1899 Oid conOid;
1900 bool deferrable;
1901 bool initdeferred;
1902 bool mark_as_primary;
1903 bool islocal;
1904 bool noinherit;
1906 int16 inhcount;
1907
1908 deferrable = (constr_flags & INDEX_CONSTR_CREATE_DEFERRABLE) != 0;
1909 initdeferred = (constr_flags & INDEX_CONSTR_CREATE_INIT_DEFERRED) != 0;
1912
1913 /* constraint creation support doesn't work while bootstrapping */
1915
1916 /* enforce system-table restriction */
1918 IsSystemRelation(heapRelation) &&
1920 ereport(ERROR,
1922 errmsg("user-defined indexes on system catalog tables are not supported")));
1923
1924 /* primary/unique constraints shouldn't have any expressions */
1925 if (indexInfo->ii_Expressions &&
1927 elog(ERROR, "constraints cannot have index expressions");
1928
1929 /*
1930 * If we're manufacturing a constraint for a pre-existing index, we need
1931 * to get rid of the existing auto dependencies for the index (the ones
1932 * that index_create() would have made instead of calling this function).
1933 *
1934 * Note: this code would not necessarily do the right thing if the index
1935 * has any expressions or predicate, but we'd never be turning such an
1936 * index into a UNIQUE or PRIMARY KEY constraint.
1937 */
1941
1943 {
1944 islocal = false;
1945 inhcount = 1;
1946 noinherit = false;
1947 }
1948 else
1949 {
1950 islocal = true;
1951 inhcount = 0;
1952 noinherit = true;
1953 }
1954
1955 /*
1956 * Construct a pg_constraint entry.
1957 */
1961 deferrable,
1962 initdeferred,
1963 true, /* Is Enforced */
1964 true,
1966 RelationGetRelid(heapRelation),
1967 indexInfo->ii_IndexAttrNumbers,
1968 indexInfo->ii_NumIndexKeyAttrs,
1969 indexInfo->ii_NumIndexAttrs,
1970 InvalidOid, /* no domain */
1971 indexRelationId, /* index OID */
1972 InvalidOid, /* no foreign key */
1973 NULL,
1974 NULL,
1975 NULL,
1976 NULL,
1977 0,
1978 ' ',
1979 ' ',
1980 NULL,
1981 0,
1982 ' ',
1983 indexInfo->ii_ExclusionOps,
1984 NULL, /* no check constraint */
1985 NULL,
1986 islocal,
1987 inhcount,
1988 noinherit,
1990 is_internal);
1991
1992 /*
1993 * Register the index as internally dependent on the constraint.
1994 *
1995 * Note that the constraint has a dependency on the table, so we don't
1996 * need (or want) any direct dependency from the index to the table.
1997 */
2001
2002 /*
2003 * Also, if this is a constraint on a partition, give it partition-type
2004 * dependencies on the parent constraint as well as the table.
2005 */
2007 {
2009
2013 RelationGetRelid(heapRelation));
2015 }
2016
2017 /*
2018 * If the constraint is deferrable, create the deferred uniqueness
2019 * checking trigger. (The trigger will be given an internal dependency on
2020 * the constraint by CreateTrigger.)
2021 */
2022 if (deferrable)
2023 {
2025
2026 trigger->replace = false;
2027 trigger->isconstraint = true;
2028 trigger->trigname = (constraintType == CONSTRAINT_PRIMARY) ?
2029 "PK_ConstraintTrigger" :
2030 "Unique_ConstraintTrigger";
2031 trigger->relation = NULL;
2032 trigger->funcname = SystemFuncName("unique_key_recheck");
2033 trigger->args = NIL;
2034 trigger->row = true;
2035 trigger->timing = TRIGGER_TYPE_AFTER;
2037 trigger->columns = NIL;
2038 trigger->whenClause = NULL;
2039 trigger->transitionRels = NIL;
2040 trigger->deferrable = true;
2041 trigger->initdeferred = initdeferred;
2042 trigger->constrrel = NULL;
2043
2046 InvalidOid, NULL, true, false);
2047 }
2048
2049 /*
2050 * If needed, mark the index as primary and/or deferred in pg_index.
2051 *
2052 * Note: When making an existing index into a constraint, caller must have
2053 * a table lock that prevents concurrent table updates; otherwise, there
2054 * is a risk that concurrent readers of the table will miss seeing this
2055 * index at all.
2056 */
2058 (mark_as_primary || deferrable))
2059 {
2063 bool dirty = false;
2064 bool marked_as_primary = false;
2065
2067
2071 elog(ERROR, "cache lookup failed for index %u", indexRelationId);
2073
2074 if (mark_as_primary && !indexForm->indisprimary)
2075 {
2076 indexForm->indisprimary = true;
2077 dirty = true;
2078 marked_as_primary = true;
2079 }
2080
2081 if (deferrable && indexForm->indimmediate)
2082 {
2083 indexForm->indimmediate = false;
2084 dirty = true;
2085 }
2086
2087 if (dirty)
2088 {
2090
2091 /*
2092 * When we mark an existing index as primary, force a relcache
2093 * flush on its parent table, so that all sessions will become
2094 * aware that the table now has a primary key. This is important
2095 * because it affects some replication behaviors.
2096 */
2098 CacheInvalidateRelcache(heapRelation);
2099
2101 InvalidOid, is_internal);
2102 }
2103
2106 }
2107
2108 return myself;
2109}
int16_t int16
Definition c.h:610
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:102
#define INDEX_CONSTR_CREATE_UPDATE_INDEX
Definition index.h:100
#define INDEX_CONSTR_CREATE_REMOVE_OLD_DEPS
Definition index.h:101
#define INDEX_CONSTR_CREATE_DEFERRABLE
Definition index.h:98
#define INDEX_CONSTR_CREATE_MARK_AS_PRIMARY
Definition index.h:97
#define INDEX_CONSTR_CREATE_INIT_DEFERRED
Definition index.h:99
#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:162

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 727 of file index.c.

748{
749 Oid heapRelationId = RelationGetRelid(heapRelation);
751 Relation indexRelation;
753 bool shared_relation;
754 bool mapped_relation;
755 bool is_exclusion;
757 int i;
758 char relpersistence;
759 bool isprimary = (flags & INDEX_CREATE_IS_PRIMARY) != 0;
760 bool invalid = (flags & INDEX_CREATE_INVALID) != 0;
761 bool concurrent = (flags & INDEX_CREATE_CONCURRENT) != 0;
762 bool partitioned = (flags & INDEX_CREATE_PARTITIONED) != 0;
763 char relkind;
764 TransactionId relfrozenxid;
765 MultiXactId relminmxid;
767
768 /* constraint flags can only be set when a constraint is requested */
769 Assert((constr_flags == 0) ||
770 ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0));
771 /* partitioned indexes must never be "built" by themselves */
773
775 is_exclusion = (indexInfo->ii_ExclusionOps != NULL);
776
778
779 /*
780 * The index will be in the same namespace as its parent table, and is
781 * shared across databases if and only if the parent is. Likewise, it
782 * will use the relfilenumber map if and only if the parent does; and it
783 * inherits the parent's relpersistence.
784 */
785 namespaceId = RelationGetNamespace(heapRelation);
786 shared_relation = heapRelation->rd_rel->relisshared;
787 mapped_relation = RelationIsMapped(heapRelation);
788 relpersistence = heapRelation->rd_rel->relpersistence;
789
790 /*
791 * check parameters
792 */
793 if (indexInfo->ii_NumIndexAttrs < 1)
794 elog(ERROR, "must index at least one column");
795
797 IsSystemRelation(heapRelation) &&
801 errmsg("user-defined indexes on system catalog tables are not supported")));
802
803 /*
804 * Btree text_pattern_ops uses texteq as the equality operator, which is
805 * fine as long as the collation is deterministic; texteq then reduces to
806 * bitwise equality and so it is semantically compatible with the other
807 * operators and functions in that opclass. But with a nondeterministic
808 * collation, texteq could yield results that are incompatible with the
809 * actual behavior of the index (which is determined by the opclass's
810 * comparison function). We prevent such problems by refusing creation of
811 * an index with that opclass and a nondeterministic collation.
812 *
813 * The same applies to varchar_pattern_ops and bpchar_pattern_ops. If we
814 * find more cases, we might decide to create a real mechanism for marking
815 * opclasses as incompatible with nondeterminism; but for now, this small
816 * hack suffices.
817 *
818 * Another solution is to use a special operator, not texteq, as the
819 * equality opclass member; but that is undesirable because it would
820 * prevent index usage in many queries that work fine today.
821 */
822 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
823 {
824 Oid collation = collationIds[i];
825 Oid opclass = opclassIds[i];
826
827 if (collation)
828 {
829 if ((opclass == TEXT_BTREE_PATTERN_OPS_OID ||
831 opclass == BPCHAR_BTREE_PATTERN_OPS_OID) &&
833 {
835
838 elog(ERROR, "cache lookup failed for operator class %u", opclass);
841 errmsg("nondeterministic collations are not supported for operator class \"%s\"",
844 }
845 }
846 }
847
848 /*
849 * Concurrent index build on a system catalog is unsafe because we tend to
850 * release locks before committing in catalogs.
851 */
852 if (concurrent &&
853 IsCatalogRelation(heapRelation))
856 errmsg("concurrent index creation on system catalog tables is not supported")));
857
858 /*
859 * This case is currently not supported. There's no way to ask for it in
860 * the grammar with CREATE INDEX, but it can happen with REINDEX.
861 */
862 if (concurrent && is_exclusion)
865 errmsg("concurrent index creation for exclusion constraints is not supported")));
866
867 /*
868 * We cannot allow indexing a shared relation after initdb (because
869 * there's no way to make the entry in other databases' pg_class).
870 */
874 errmsg("shared indexes cannot be created after initdb")));
875
876 /*
877 * Shared relations must be in pg_global, too (last-ditch check)
878 */
880 elog(ERROR, "shared relations must be placed in pg_global tablespace");
881
882 /*
883 * Check for duplicate name (both as to the index, and as to the
884 * associated constraint if any). Such cases would fail on the relevant
885 * catalogs' unique indexes anyway, but we prefer to give a friendlier
886 * error message.
887 */
889 {
890 if ((flags & INDEX_CREATE_IF_NOT_EXISTS) != 0)
891 {
894 errmsg("relation \"%s\" already exists, skipping",
897 return InvalidOid;
898 }
899
902 errmsg("relation \"%s\" already exists",
904 }
905
906 if ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0 &&
909 {
910 /*
911 * INDEX_CREATE_IF_NOT_EXISTS does not apply here, since the
912 * conflicting constraint is not an index.
913 */
916 errmsg("constraint \"%s\" for relation \"%s\" already exists",
918 }
919
920 /*
921 * construct tuple descriptor for index tuples
922 */
924 indexInfo,
928 opclassIds);
929
930 /*
931 * Allocate an OID for the index, unless we were told what to use.
932 *
933 * The OID will be the relfilenumber as well, so make sure it doesn't
934 * collide with either pg_class OIDs or existing physical files.
935 */
937 {
938 /* Use binary-upgrade override for pg_class.oid and relfilenumber */
939 if (IsBinaryUpgrade)
940 {
944 errmsg("pg_class index OID value not set when in binary upgrade mode")));
945
948
949 /* Override the index relfilenumber */
950 if ((relkind == RELKIND_INDEX) &&
954 errmsg("index relfilenumber value not set when in binary upgrade mode")));
957
958 /*
959 * Note that we want create_storage = true for binary upgrade. The
960 * storage we create here will be replaced later, but we need to
961 * have something on disk in the meanwhile.
962 */
964 }
965 else
966 {
968 GetNewRelFileNumber(tableSpaceId, pg_class, relpersistence);
969 }
970 }
971
972 /*
973 * create the index relation's relcache entry and, if necessary, the
974 * physical disk file. (If we fail further down, it's the smgr's
975 * responsibility to remove the disk file again, if any.)
976 */
977 indexRelation = heap_create(indexRelationName,
984 relkind,
985 relpersistence,
989 &relfrozenxid,
990 &relminmxid,
992
993 Assert(relfrozenxid == InvalidTransactionId);
994 Assert(relminmxid == InvalidMultiXactId);
995 Assert(indexRelationId == RelationGetRelid(indexRelation));
996
997 /*
998 * Obtain exclusive lock on it. Although no other transactions can see it
999 * until we commit, this prevents deadlock-risk complaints from lock
1000 * manager in cases such as CLUSTER.
1001 */
1002 LockRelation(indexRelation, AccessExclusiveLock);
1003
1004 /*
1005 * Fill in fields of the index's pg_class entry that are not set correctly
1006 * by heap_create.
1007 *
1008 * XXX should have a cleaner way to create cataloged indexes
1009 */
1010 indexRelation->rd_rel->relowner = heapRelation->rd_rel->relowner;
1011 indexRelation->rd_rel->relam = accessMethodId;
1012 indexRelation->rd_rel->relispartition = OidIsValid(parentIndexRelid);
1013
1014 /*
1015 * store index's pg_class entry
1016 */
1017 InsertPgClassTuple(pg_class, indexRelation,
1018 RelationGetRelid(indexRelation),
1019 (Datum) 0,
1020 reloptions);
1021
1022 /* done with pg_class */
1024
1025 /*
1026 * now update the object id's of all the attribute tuple forms in the
1027 * index relation's tuple descriptor
1028 */
1029 InitializeAttributeOids(indexRelation,
1030 indexInfo->ii_NumIndexAttrs,
1032
1033 /*
1034 * append ATTRIBUTE tuples for the index
1035 */
1037
1038 /* ----------------
1039 * update pg_index
1040 * (append INDEX tuple)
1041 *
1042 * Note that this stows away a representation of "predicate".
1043 * (Or, could define a rule to maintain the predicate) --Nels, Feb '92
1044 * ----------------
1045 */
1047 indexInfo,
1051 !concurrent && !invalid,
1052 !concurrent);
1053
1054 /*
1055 * Register relcache invalidation on the indexes' heap relation, to
1056 * maintain consistency of its index list
1057 */
1058 CacheInvalidateRelcache(heapRelation);
1059
1060 /* update pg_inherits and the parent's relhassubclass, if needed */
1062 {
1066 }
1067
1068 /*
1069 * Register constraint and dependencies for the index.
1070 *
1071 * If the index is from a CONSTRAINT clause, construct a pg_constraint
1072 * entry. The index will be linked to the constraint, which in turn is
1073 * linked to the table. If it's not a CONSTRAINT, we need to make a
1074 * dependency directly on the table.
1075 *
1076 * We don't need a dependency on the namespace, because there'll be an
1077 * indirect dependency via our parent table.
1078 *
1079 * During bootstrap we can't register any dependencies, and we don't try
1080 * to make a constraint either.
1081 */
1083 {
1085 referenced;
1086 ObjectAddresses *addrs;
1087
1089
1090 if ((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0)
1091 {
1092 char constraintType;
1094
1095 if (isprimary)
1097 else if (indexInfo->ii_Unique)
1099 else if (is_exclusion)
1101 else
1102 {
1103 elog(ERROR, "constraint must be PRIMARY, UNIQUE or EXCLUDE");
1104 constraintType = 0; /* keep compiler quiet */
1105 }
1106
1107 localaddr = index_constraint_create(heapRelation,
1110 indexInfo,
1115 is_internal);
1116 if (constraintId)
1117 *constraintId = localaddr.objectId;
1118 }
1119 else
1120 {
1121 bool have_simple_col = false;
1122
1123 addrs = new_object_addresses();
1124
1125 /* Create auto dependencies on simply-referenced columns */
1126 for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
1127 {
1128 if (indexInfo->ii_IndexAttrNumbers[i] != 0)
1129 {
1132 indexInfo->ii_IndexAttrNumbers[i]);
1134 have_simple_col = true;
1135 }
1136 }
1137
1138 /*
1139 * If there are no simply-referenced columns, give the index an
1140 * auto dependency on the whole table. In most cases, this will
1141 * be redundant, but it might not be if the index expressions and
1142 * predicate contain no Vars or only whole-row Vars.
1143 */
1144 if (!have_simple_col)
1145 {
1149 }
1150
1152 free_object_addresses(addrs);
1153 }
1154
1155 /*
1156 * If this is an index partition, create partition dependencies on
1157 * both the parent index and the table. (Note: these must be *in
1158 * addition to*, not instead of, all other dependencies. Otherwise
1159 * we'll be short some dependencies after DETACH PARTITION.)
1160 */
1162 {
1165
1168 }
1169
1170 /* placeholder for normal dependencies */
1171 addrs = new_object_addresses();
1172
1173 /* Store dependency on collations */
1174
1175 /* The default collation is pinned, so don't bother recording it */
1176 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
1177 {
1179 {
1182 }
1183 }
1184
1185 /* Store dependency on operator classes */
1186 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
1187 {
1190 }
1191
1193 free_object_addresses(addrs);
1194
1195 /* Store dependencies on anything mentioned in index expressions */
1196 if (indexInfo->ii_Expressions)
1197 {
1199 (Node *) indexInfo->ii_Expressions,
1202 DEPENDENCY_AUTO, false);
1203 }
1204
1205 /* Store dependencies on anything mentioned in predicate */
1206 if (indexInfo->ii_Predicate)
1207 {
1209 (Node *) indexInfo->ii_Predicate,
1212 DEPENDENCY_AUTO, false);
1213 }
1214 }
1215 else
1216 {
1217 /* Bootstrap mode - assert we weren't asked for constraint support */
1218 Assert((flags & INDEX_CREATE_ADD_CONSTRAINT) == 0);
1219 }
1220
1221 /* Post creation hook for new index */
1223 indexRelationId, 0, is_internal);
1224
1225 /*
1226 * Advance the command counter so that we can see the newly-entered
1227 * catalog tuples for the index.
1228 */
1230
1231 /*
1232 * In bootstrap mode, we have to fill in the index strategy structure with
1233 * information from the catalogs. If we aren't bootstrapping, then the
1234 * relcache entry has already been rebuilt thanks to sinval update during
1235 * CommandCounterIncrement.
1236 */
1238 RelationInitIndexAccessInfo(indexRelation);
1239 else
1240 Assert(indexRelation->rd_indexcxt != NULL);
1241
1242 indexRelation->rd_index->indnkeyatts = indexInfo->ii_NumIndexKeyAttrs;
1243
1244 /* Validate opclass-specific options */
1245 if (opclassOptions)
1246 for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
1247 (void) index_opclass_options(indexRelation, i + 1,
1249 true);
1250
1251 /*
1252 * If this is bootstrap (initdb) time, then we don't actually fill in the
1253 * index yet. We'll be creating more indexes and classes later, so we
1254 * delay filling them in until just before we're done with bootstrapping.
1255 * Similarly, if the caller specified to skip the build then filling the
1256 * index is delayed till later (ALTER TABLE can save work in some cases
1257 * with this). Otherwise, we call the AM routine that constructs the
1258 * index.
1259 */
1261 {
1263 }
1264 else if ((flags & INDEX_CREATE_SKIP_BUILD) != 0)
1265 {
1266 /*
1267 * Caller is responsible for filling the index later on. However,
1268 * we'd better make sure that the heap relation is correctly marked as
1269 * having an index.
1270 */
1271 index_update_stats(heapRelation,
1272 true,
1273 -1.0);
1274 /* Make the above update visible */
1276 }
1277 else
1278 {
1279 index_build(heapRelation, indexRelation, indexInfo, false, true);
1280 }
1281
1282 /*
1283 * Close the index; but we keep the lock that we acquired above until end
1284 * of transaction. Closing the heap is caller's responsibility.
1285 */
1286 index_close(indexRelation, NoLock);
1287
1288 return indexRelationId;
1289}
void index_register(Oid heap, Oid ind, const IndexInfo *indexInfo)
Definition bootstrap.c:1123
TransactionId MultiXactId
Definition c.h:745
uint32 TransactionId
Definition c.h:735
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:87
static void InitializeAttributeOids(Relation indexRelation, int numatts, Oid indexoid)
Definition index.c:495
Oid binary_upgrade_next_index_pg_class_oid
Definition index.c:86
static void AppendAttributeTuples(Relation indexRelation, const Datum *attopts, const NullableDatum *stattargets)
Definition index.c:513
static TupleDesc ConstructTupleDescriptor(Relation heapRelation, const IndexInfo *indexInfo, const List *indexColNames, Oid accessMethodId, const Oid *collationIds, const Oid *opclassIds)
Definition index.c:282
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:1886
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:564
#define INDEX_CREATE_IS_PRIMARY
Definition index.h:67
#define INDEX_CREATE_IF_NOT_EXISTS
Definition index.h:71
#define INDEX_CREATE_PARTITIONED
Definition index.h:72
#define INDEX_CREATE_INVALID
Definition index.h:73
#define INDEX_CREATE_ADD_CONSTRAINT
Definition index.h:68
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:1200
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition lsyscache.c:2105
#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:1435
#define RelFileNumberIsValid(relnumber)
Definition relpath.h:27
#define ERRCODE_DUPLICATE_OBJECT
Definition streamutil.c:30
List * ii_Predicate
Definition execnodes.h:194
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:3678
#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 2123 of file index.c.

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

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

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 4471 of file indexcmds.c.

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

218{
219 BlockNumber block = (BlockNumber) (encoded >> 16);
220 OffsetNumber offset = (OffsetNumber) (encoded & 0xFFFF);
221
222 ItemPointerSet(itemptr, block, offset);
223}
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 196 of file index.h.

197{
198 BlockNumber block = ItemPointerGetBlockNumber(itemptr);
201
202 /*
203 * Use the 16 least significant bits for the offset. 32 adjacent bits are
204 * used for the block number. Since remaining bits are unused, there
205 * cannot be negative encoded values (We assume a two's complement
206 * representation).
207 */
208 encoded = ((uint64) block << 16) | (uint16) offset;
209
210 return encoded;
211}
uint64_t uint64
Definition c.h:616
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 3609 of file index.c.

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

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 3949 of file index.c.

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

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 4120 of file index.c.

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

References currentlyReindexedHeap.

◆ ReindexIsProcessingIndex()

bool ReindexIsProcessingIndex ( Oid  indexOid)
extern

Definition at line 4141 of file index.c.

4142{
4143 return indexOid == currentlyReindexedIndex ||
4145}
static Oid currentlyReindexedIndex
Definition index.c:4111
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 4214 of file index.c.

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

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

Referenced by AbortSubTransaction(), and AbortTransaction().

◆ RestoreReindexState()

void RestoreReindexState ( const void reindexstate)
extern

Definition at line 4272 of file index.c.

4273{
4275 int c = 0;
4276 MemoryContext oldcontext;
4277
4278 currentlyReindexedHeap = sistate->currentlyReindexedHeap;
4279 currentlyReindexedIndex = sistate->currentlyReindexedIndex;
4280
4283 for (c = 0; c < sistate->numPendingReindexedIndexes; ++c)
4286 sistate->pendingReindexedIndexes[c]);
4287 MemoryContextSwitchTo(oldcontext);
4288
4289 /* Note the worker has its own transaction nesting level */
4291}
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 4254 of file index.c.

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

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 3351 of file index.c.

3352{
3353 Relation heapRelation,
3354 indexRelation;
3355 IndexInfo *indexInfo;
3358 Oid save_userid;
3359 int save_sec_context;
3360 int save_nestlevel;
3361
3362 {
3363 const int progress_index[] = {
3369 };
3370 const int64 progress_vals[] = {
3372 0, 0, 0, 0
3373 };
3374
3376 }
3377
3378 /* Open and lock the parent heap relation */
3380
3381 /*
3382 * Switch to the table owner's userid, so that any index functions are run
3383 * as that user. Also lock down security-restricted operations and
3384 * arrange to make GUC variable changes local to this command.
3385 */
3386 GetUserIdAndSecContext(&save_userid, &save_sec_context);
3387 SetUserIdAndSecContext(heapRelation->rd_rel->relowner,
3388 save_sec_context | SECURITY_RESTRICTED_OPERATION);
3389 save_nestlevel = NewGUCNestLevel();
3391
3392 indexRelation = index_open(indexId, RowExclusiveLock);
3393
3394 /*
3395 * Fetch info needed for index_insert. (You might think this should be
3396 * passed in from DefineIndex, but its copy is long gone due to having
3397 * been built in a previous transaction.)
3398 */
3399 indexInfo = BuildIndexInfo(indexRelation);
3400
3401 /* mark build is concurrent just for consistency */
3402 indexInfo->ii_Concurrent = true;
3403
3404 /*
3405 * Scan the index and gather up all the TIDs into a tuplesort object.
3406 */
3407 ivinfo.index = indexRelation;
3408 ivinfo.heaprel = heapRelation;
3409 ivinfo.analyze_only = false;
3410 ivinfo.report_progress = true;
3411 ivinfo.estimated_count = true;
3412 ivinfo.message_level = DEBUG2;
3413 ivinfo.num_heap_tuples = heapRelation->rd_rel->reltuples;
3414 ivinfo.strategy = NULL;
3415
3416 /*
3417 * Encode TIDs as int8 values for the sort, rather than directly sorting
3418 * item pointers. This can be significantly faster, primarily because TID
3419 * is a pass-by-reference type on all platforms, whereas int8 is
3420 * pass-by-value on most platforms.
3421 */
3423 InvalidOid, false,
3426 state.htups = state.itups = state.tups_inserted = 0;
3427
3428 /* ambulkdelete updates progress metrics */
3431
3432 /* Execute the sort */
3433 {
3434 const int progress_index[] = {
3438 };
3439 const int64 progress_vals[] = {
3441 0, 0
3442 };
3443
3445 }
3446 tuplesort_performsort(state.tuplesort);
3447
3448 /*
3449 * Now scan the heap and "merge" it with the index
3450 */
3453 table_index_validate_scan(heapRelation,
3454 indexRelation,
3455 indexInfo,
3456 snapshot,
3457 &state);
3458
3459 /* Done with tuplesort object */
3460 tuplesort_end(state.tuplesort);
3461
3462 /* Make sure to release resources cached in indexInfo (if needed). */
3463 index_insert_cleanup(indexRelation, indexInfo);
3464
3465 elog(DEBUG2,
3466 "validate_index found %.0f heap tuples, %.0f index tuples; inserted %.0f missing tuples",
3467 state.htups, state.itups, state.tups_inserted);
3468
3469 /* Roll back any GUC changes executed by index functions */
3470 AtEOXact_GUC(false, save_nestlevel);
3471
3472 /* Restore userid and security context */
3473 SetUserIdAndSecContext(save_userid, save_sec_context);
3474
3475 /* Close rels, but keep locks */
3476 index_close(indexRelation, NoLock);
3477 table_close(heapRelation, NoLock);
3478}
#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:3484
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().